【问题标题】:correct way of modifying a passed argument in the same way for many objects以相同方式为许多对象修改传递参数的正确方法
【发布时间】:2014-02-27 06:10:12
【问题描述】:

我有一些 Rails 服务(取决于服务)接受特定类型的对象、该对象的数组或该对象的 ActiveRecord::Relation。

所以:

FooService 接受 Foo 对象,BarService 接受 Bar 对象等。

但是..所有服务对象都希望将传入的内容按摩到给定对象的数组中。

在被调用的服务方法的范围内,我可以很容易地做到这一点。 我试图干掉事情并为所有服务制定一个方法,因为它们每个都有相同的代码块。不幸的是,我遇到了 Ruby 的问题。

例如:

def change_obj(element)
  element = [element]
end



blah = "hello"

change_obj(blah)

puts blah.class.to_s #I want it to be an array with the  string in it now.

我明白为什么它不起作用。但是,我不清楚正确的做法是什么。

理想情况下,我想要这样的东西:

class BarService < Service

 def initialize(foo)

   @foo = foo

 end


 def do_something(bars)

  massage_to_array(bars) #method inherited from Service. if bars is an ActiveRecordRelation, convert it to array..if bars is a singular object, flip it to an array with that object as the sole element.
  process_array_of_bars(bars)

 end

end

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    只要您正在修改传递的对象 - ruby​​ 将保留该对象的引用和更新内容,而不是创建新对象。例如,如果您将数组作为参数传递,然后将元素添加到方法内的数组中 - ruby​​ 会将元素添加到传入的对象,但如果您为对象重新分配值,那么 ruby​​ 将删除对传递对象并在本地范围内创建新对象,并将对它的引用添加到变量名。

    话虽如此,您仍然可以通过创建充当代理的类来获得类似的结果。请记住,只要您不将变量名称重新分配给新变量,ruby 就会保持对原始对象的引用。例如

    class ArgProxy
      attr_accessor :arg_object
    
      def initialize(arg=nil)
        self.arg_object = arg
      end
    end
    
    def some_method(arg_proxy)
      arg_proxy.arg_object = [arg_proxy.arg_object]
    end
    
    arg_proxy = ArgProxy.new("qwerty")
    some_method(arg_proxy)
    
    arg_proxy.arg_object #=> ["qwerty"]
    

    【讨论】:

    • 完全正确。因为变量正在改变类而不只是破坏现有对象,所以变量被指向一个新对象。代理对象可以工作,但我真的希望不必这样做。我可能不得不使用此选项并重新组织服务以适应。
    【解决方案2】:
    bars = massage_to_array(bars)
    process_array_of_bars(bars)
    

    【讨论】:

    • 另外,仅供参考 - 您可以使用 Array(bars) ,即使它已经是一个数组并且在您的原始方法中没有理由将数组分配回元素,它也可以正常工作
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-03-24
    • 1970-01-01
    • 2011-10-31
    • 2014-07-26
    • 2017-02-17
    • 2015-11-15
    相关资源
    最近更新 更多