2013-04-24 10 views
5

Il modo più semplice per un ciclo su tutti gli attributi di un oggetto quando si utilizza Active Record èLooping sugli attributi di oggetto di un non-Active-Record-modello

order_item_object.attributes.each do |key,value| 
.... 
end 

Ma questo non funziona, quando siamo non usare Active Record. Come posso poi ripetere tutti gli attributi di un oggetto?

Per esempio:: Ho un modello in Rails che non utilizza la registrazione attiva. L'oggetto dal modello order_item può essere utilizzato nel controller come order_item_object.product_id, order_item_object.quantity, order_item_object.quoted_price. Ma quando provo a order_item_object.attributes.each do |k,v| ...., ottengo undefined method "attributes" for #<Order:0x00000005aa81b0>

Come dovrei andare su questo?

+0

significa variabili di classe, variabili di istanza o cosa? –

+0

Questi sono gli attributi (attr_accessor) definiti nel modello, che voglio ripetere su un oggetto. Penso di usarlo nel controller che sta causando il problema? –

+0

hai un errore di battitura, in realtà. non c'è una doppia 'r' in 'attributes'. – shime

risposta

1

Questo è il modo migliore che ho trovato

C'è un codice per mostrare il suo utilizzo qui (guarda l'aggiornamento nella domanda stessa) - Grouping via an element in hash

0

Gli attributi a cui si fa riferimento è una variabile di istanza sui modelli ActiveRecord che restituisce un hash degli attributi db dei modelli.

Un modello non ActiveRecord non avrà il metodo degli attributi che si sta chiamando a meno che non lo si definisca esplicitamente. Tutti gli oggetti hanno un metodo chiamato instance_variables che puoi usare per ottenere un elenco di nomi di attributi e quindi trovare in modo riflessivo i valori degli attributi.

3

provare questo:

class Parent 
    def self.attr_accessor(*vars) 
    @attributes ||= [] 
    @attributes.concat vars 
    super(*vars) 
    end 

    def self.attributes 
    @attributes 
    end 

    def attributes 
    self.class.attributes 
    end 
end 

class ChildClass < Parent 
    attr_accessor :id, :title, :body 
end 

p ChildClass.new.attributes.inspect #=> [:id, :title, :body] 
+0

Grazie per questo: funziona nel caso d'uso in cui l'attributo potrebbe non avere ancora un valore. –

3

attr_accessor è semplicemente una macro che crea alcuni metodi per impostare una variabile di istanza. Quindi, forse, ciò che si vuole è il metodo instance_variables, che restituisce un array di variabili di istanza che si possono scorrere

class Foo 
    attr_accessor :bar 
    attr_accessor :baz 
end 

foo = Foo.new 
foo.bar = 123 
foo.baz 
foo.instance_variables.each do |ivar_name| 
    ivar_value = foo.instance_variable_get ivar_name 
    # do something with ivar_name and ivar_value 
end 

ma non vorrei veramente raccomandare questo. ActiveRecord mantiene separati i dati del modello per un motivo. L'istanza potrebbe avere molti usi per variabili di istanza. Ad esempio, forse vuoi monitorare se il record è stato salvato o meno. Questo può essere mantenuto nella variabile @saved, che riflette lo stato dell'istanza ma non i dati del modello.

Forse vuoi mantenere un hash di attributi? modo

+0

La variabile di istanza sicuramente non funzionerà ..... Questa app non è collegata al db. Più di un lavoro di front end. Penso che andrò con l'hash degli attributi permanentemente salvati. Volevo solo confermare se mi mancasse qualcosa di ovvio o meno. –

+0

Le variabili di istanza non hanno nulla a che fare con il DB. Ma il modo in cui attraversi i dati nel tuo modello ovviamente ha tutto a che fare con il modo in cui i dati nel tuo modello vengono sottratti. –

0

A non molto elegante di farlo:

class Test 
    attr_accessor :firstname,:lastname 
    def initialize(fn,ln); @firstname = fn; @lastname = ln; end 
end 

o = Test.new("Fernando", "Mendez") 
o.instance_variables.each {|e| p o.send e.to_s.sub("@","").to_sym} 
output: 
"Fernando" 
"Mendez" 

Se si vuole mantenere una traccia della coppia chiave-valore:

r = o.instance_variables.map {|e| Hash[e,(o.send e.to_s.sub("@","").to_sym)]} 

#[{:@firstname=>"Fernando"}, {:@lastname=>"Mendez"}] 
+0

Grazie ... Apprezzo lo sforzo, ma come hai detto non è elegante. –

+0

hehe abbastanza giusto ;-) – fmendez

1

Se si desidera che le rappresentazioni di stringa delle variabili di istanza, si può fare:

self.instance_values.keys.each do |k| 
.. 
end 

Questo deve essere ripetuto su tutti i tasti (esempio nomi di variabili come stringhe) che sono definiti per la vostra classe.

Problemi correlati