How to set “programmatically”\“iteratively” each class object attribute to a value?

北战南征 提交于 2019-12-24 11:03:17

问题


I am using Ruby on Rails 3.0.9 and RSpec 2. I am trying to refactoring some spec file in the following way (in order to test with less code similar class object attribute values):

[
  :attribute_a,
  :attribute_b,
  :attribute_c
].each do |attr|
  before do
    # HERE I would like to set the "current" 'attr' related to the
    # class object instance 'attribute_< letter >' (read below for
    # more information) each time the iterator is called (note: all
    # following attributes are NOT attr_accesible - for that reason
    # I use the 'user.attribute_< letter >' in the 'before do'
    # statement)
    #
    # # Iteration 1
    #     user.attribute_a = 'a_value'
    # # No changes to 'user.attribute_b'
    # # No changes to 'user.attribute_c'
    #
    # # Iteration 2
    # # No changes to 'user.attribute_a'
    #     user.attribute_b = 'a_value'
    # # No changes to 'user.attribute_c'
    #
    # # Iteration 3
    # # No changes to 'user.attribute_a'
    # # No changes to 'user.attribute_b'
    #     user.attribute_c = 'a_value'

    # Maybe I should make something like the following but that, as well
    # as the 'send' method must be used, doesn't work (the below code-line
    # is just an example of what I would like to do).
    #
    # user.send(:"#{attr}") = 'a_value'
  end

  ...
end

How can I improve the above code so to accomplish what I aim (I refer to the user.send(:"#{attr}") = 'a_value' part in order to set "programmatically" - that is, set a different attribute value for each iteration made - each user attribute value to 'a_value')?


回答1:


You should use .send and append an = to the method name to invoke the setter, passing the value as the second argument to send:

[
  :attribute_a,
  :attribute_b,
  :attribute_c
].each do |attr|
  before do
    user.send("#{attr}=", 'a_value')
  end

You're effectively doing this:

user.send('attribute_a=', 'a_value');

Your syntax (user.send(:"#{attr}") = 'a_value') is wrong/weird for a couple reasons:

  • There's no reason to convert :attr to a string and them immediately back to a symbol
  • You can't assign a value to the return value of .send


来源:https://stackoverflow.com/questions/7477062/how-to-set-programmatically-iteratively-each-class-object-attribute-to-a-val

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!