Подтвердить что ты не робот

Как конвертировать из строки в имя атрибута объекта?

Я пытаюсь преобразовать строковое значение в имя атрибута, принадлежащего объекту. Например, в следующем коде мне нужны все строковые значения в column_array, превращенные в имена атрибутов. Имена "student_identification", "email" и т.д. Являются фактическими именами столбцов моей таблицы Student. В реальном сценарии column_array будет установлен пользователем (пометив флажки). И new_array будет заменен на csv, так как я хочу, чтобы данные перешли в файл csv.

В настоящий момент я действительно борюсь за следующую строку:

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

Я хочу, чтобы "#{column_array[i]}" превращался в имя атрибута, чтобы я мог получить доступ к данным.

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
4b9b3361

Ответ 1

Скажем column_array[i] = "foo", для примера.

Если вы хотите вызвать метод r.foo, используйте Object#send:

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

Если вы хотите получить доступ к переменной экземпляра r @foo, используйте Object#instance_variable_get и Object#instance_variable_set:

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

В этом случае мы должны добавить данное имя с помощью @ sigil, так как это необходимо в начале всех имен переменных экземпляра.

Так как это рельсы, и есть много магии ActiveRecord, идущей с вашими моделями (и я предполагаю, что Student является подклассом ActiveRecord::Base), вы, вероятно, захотите использовать первое, поскольку ActiveRecord создает методы для доступа к базе данных, а значения, хранящиеся в переменных экземпляра, могут быть не такими, которые вы хотите или ожидаете.

Я буду использовать пример из некоторых тестовых данных, которые у меня есть:

% 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."

Итак, вы можете видеть, как #send(field) получает доступ к информации о записи, а попытка доступа к атрибутам - нет. Кроме того, мы можем использовать #send(field+'=') для изменения информации о записи.

Ответ 2

Посмотрите на метод instance_eval...

если у вас есть атрибут и нужно сделать

 object.attribute = 'ololo'

вы можете сделать:

object.instance_eval('attribute') = 'ololo'