2009-05-24 5 views
18

Estoy tratando de convertir un valor de cadena en un nombre de un atributo que pertenece a un objeto. Por ejemplo, en el siguiente código, necesito todos los valores de cadena en el column_array convertidos en nombres de atributos. Los nombres "student_identification", "email", etc. son nombres de columnas reales de mi tabla Student. En el escenario real, column_array será establecido por el usuario (marcando las casillas de verificación). Y new_array será reemplazado por csv, ya que quiero que los datos entren en un archivo csv.Cómo convertir de una cadena a un nombre de atributo de objeto?

En este momento estoy realmente luchando en la siguiente línea:

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

Quiero "#{column_array[i]}" a ser convertido en el nombre del atributo para que pueda acceder a los datos.

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 
+0

'(0 .. (column_array.size -1)). Cada' puede ser reemplazado por 'column_array.each_index'. –

Respuesta

39

Digamos column_array[i] = "foo", para un ejemplo.

Si desea llamar al método r.foo, utilice Object#send:

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

Si desea acceder a r 's instancia de variable @foo, utilice Object#instance_variable_get y Object#instance_variable_set:

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

En En este caso tenemos que anteponer el nombre de pila con un sello @, ya que se requiere en el inicio de todos los nombres de variables de instancia.

Dado que este es raíles, y hay un montón de ActiveRecord magia pasando con sus modelos (y supongo Student es una subclase de ActiveRecord::Base) es probable que desee utilizar la primera, ya que ActiveRecord crea métodos para acceder a la base de datos, y los valores almacenados en variables de instancia pueden no ser lo que usted desea o espera.

voy a utilizar un ejemplo de algunos datos de prueba que tengo por ahí:

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

para que pueda ver cómo #send(field) accede a la información de los registros, y tratando de acceder a los atributos no. Además, podemos usar #send(field+'=') para cambiar la información del registro.

+0

Hola, sí El estudiante es la subclase de 'ActiveRecord :: Base' clase Estudiante Vicer

+1

Puede acceder al contenido de las columnas a través de métodos de acceso en ActiveRecord. No existe el concepto de "solo nombres de columnas" en Ruby. – Chuck

+0

Hola, Solo para tomar el problema un poco más avanzado ... digamos que su objeto 'example_customer' tiene un método llamado 'get_details_of_membership (' membership_type ')'. Aquí el 'membership_type' puede ser 'platinum', 'yearly', 'monthly' etc. Pero si utilicé este comando: example_customer.send ('get_details_of_membership (' platinum ')') , no lo hará trabajo. De hecho, me desea almacenar el 'get_details_of_membership cadena (' platino ')' en una variable como: campo = 'get_details_of_membership (' platino ')' y luego hacer: example_customer.send (campo) Puede alguien mostrarme una forma de abordar este? – Vicer

4

Mira método instance_eval ...

si tiene 'atributo' y necesita hacer

object.attribute = 'ololo' 

que puede hacer:

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