Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
565 views
in Technique[技术] by (71.8m points)

ruby on rails - How to convert from a string to object attribute name?

I am trying to convert a string value into a name of an attribute that belongs to an object. For example, in the following code, I need all the string values in the column_array turned into attribute names. The names "student_identification", "email", etc. are actual column names of my Student table. In the real scenario, column_array will be set by the user (by ticking check boxes). And new_array will be replaced by csv, as I want the data go into a csv file.

At the moment I am really struggling at the following line:

   new_array << r."#{column_array[i]}"

I want "#{column_array[i]}" to be turned into the attribute name so I can access the data.

def exp_tst

  @records =  Student.find(:all, :conditions=> session[:selection_scope],
                                 :order => sort_order('laboratory_id'))

  column_array = ["student_identification", "laboratory_id", "email", "current_status"]

  new_array = Array.new()

  @records.each do |r|

    (0..(column_array.size-1)).each do |i|
       new_array << r."#{column_array[i]}"
    end
  end

end
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Let's say column_array[i] = "foo", for an example.

If you want to call the method r.foo, use Object#send:

 r.send(column_array[i], arg1, arg2, arg3, ...)

If you want to access r's instance variable @foo, use Object#instance_variable_get and Object#instance_variable_set:

 r.instance_variable_get('@'+column_array[i])
 r.instance_variable_set('@'+column_array[i], new_value)

In this case we have to prepend the given name with an @ sigil, since that is required at the start of all instance variable names.

Since this is rails, and there's a whole lot of ActiveRecord magic going on with your models (and I'm guessing Student is a subclass of ActiveRecord::Base) you probably want to use the former, since ActiveRecord creates methods to access the database, and the values stored in instance variables may not be what you want or expect.

I'll use an example from some test data I've got lying around:

% script/console
Loading development environment (Rails 2.3.2)
irb> Customer
#=> Customer(id: integer, date_subscribed: datetime, rental_plan_id: integer, name: string, address: string, phone_number: string, credit_limit: decimal, last_bill_end_date: datetime, balance: decimal)
irb> example_customer = Customer.find(:all)[0]
#=> #<Customer id: 6, date_subscribed: "2007-12-24 05:00:00", rental_plan_id: 3, name: "Evagation Governessy", address: "803 Asbestous St, Uneradicated Stannous MP 37441", phone_number: "(433) 462-3416", credit_limit: #<BigDecimal:191edc0,'0.732E3',4(12)>, last_bill_end_date: "2009-05-15 04:00:00", balance: #<BigDecimal:191e870,'0.743E3',4(12)>>
irb> example_customer.name
#=> "Evagation Governessy"
irb> field = 'name'
#=> "name"
irb> example_customer.instance_variable_get(field)
NameError: `name` is not allowed as an instance variable name
from (irb):8:in `instance_variable_get`
from (irb):8
irb> example_customer.instance_variable_get('@'+field)
#=> nil
irb> example_customer.send(field)
#=> "Evagation Governessy"
irb> example_customer.send(field+'=', "Evagation Governessy Jr.")
#=> "Evagation Governessy Jr."
irb> example_customer.send(field)
#=> "Evagation Governessy Jr."
irb> example_customer.name
#=> "Evagation Governessy Jr."

So you can see how #send(field) accesses the record information, and trying to access the attributes doesn't. Also, we can use #send(field+'=') to change record information.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...