如何设置"动态"变量值?

Bac*_*cko 20 ruby variables metaprogramming ruby-on-rails ruby-on-rails-3

我正在使用Ruby on Rails 3.0.9,我试图"动态"设置一些变量值.那是...

...在我的模型文件中我有:

attr_accessor :variable1, :variable2, :variable3


# The 'attributes' argument contains one or more symbols which name is equal to 
# one or more of the 'attr_accessor' symbols.

def set_variables(*attributes)

  # Here I should set to 'true' all ":variable<N>" attributes passed as symbol
  # in the 'attributes' array, but variable names should be interpolated in a 
  # string.
  # 
  # For example, I should set something like "prefix_#{':variable1'.to_s}_suffix".

end
Run Code Online (Sandbox Code Playgroud)

如何将这些变量值设置为true


我尝试使用该self.send(...)方法,但我没有成功(但是,可能,我不知道如何使用该send方法...是否可以通过使用该send方法来做到这一点?!).

Aru*_*nan 60

attr_accessor :variable1, :variable2, :variable3

def set_variables(*attributes)
  attributes.each {|attribute| self.send("#{attribute}=", true)}
end
Run Code Online (Sandbox Code Playgroud)


Mla*_*vić 9

这是sendvs 的基准比较instance_variable_set:

require 'benchmark'

class Test
  VAR_NAME = '@foo'
  ATTR_NAME = :foo

  attr_accessor ATTR_NAME

  def set_by_send i
    send("#{ATTR_NAME}=", i)
  end

  def set_by_instance_variable_set i
    instance_variable_set(VAR_NAME, i)
  end
end

test = Test.new

Benchmark.bm do |x|
  x.report('send                 ') do
    1_000_000.times do |i|
      test.set_by_send i
    end
  end
  x.report('instance_variable_set') do
    1_000_000.times do |i|
      test.set_by_instance_variable_set i
    end
  end
end
Run Code Online (Sandbox Code Playgroud)

时间是:

      user     system      total        real
send                   1.000000   0.020000   1.020000 (  1.025247)
instance_variable_set  0.370000   0.000000   0.370000 (  0.377150)
Run Code Online (Sandbox Code Playgroud)

(用1.9.2测量)

应当指出的是,只有在某些情况下(比如本,与存取器使用已定义的attr_accessor)是sendinstance_variable_set功能上等同的.如果涉及的访问器中存在某些逻辑,则会有所不同,您将不得不决定两者中需要哪种变体.instance_variable_set只需设置ivar,send实际执行访问器方法,无论它做什么.

另一个评论 - 这两种方法在另一个方面表现不同:如果你还有instance_variable_set一个尚不存在的ivar,它将被创建.如果调用不存在的访问器send,则会引发异常.

  • 我相信你忘了先向我投票. (4认同)
  • 你对skorks的回答的第一个评论是你认为`send`是_better alternative_,然后将其"投票"以"搞乱内部".为了上帝的缘故,它是一个实例方法,它的工作是"混乱内部",即改变对象的内部状态.两种方式都可以完成这项任务,他们会更改ivars,所以可以选择其中一种,但是不能直接投票.所以请恢复downvote然后我们可以继续. (2认同)
  • 没有必要争论不要贬低.你需要为downvoting提供一个可靠的论据.OP的问题足够广泛,可以提供多种可能的解决方案.我们可以争论哪种更好或更适合特定需求.但是,给定的答案都不是错误的,也不是误导性的. (2认同)