2012-03-06 18 views
15
modello

Let Quote hanno attributi [price, description]Rails: Copia attributi da un oggetto ad un altro utilizzando gli "attributi" metodo

modello

Let Invoice hanno attributi [price, description, priority]

Facciamo invoice un oggetto dal Modello Invoice con gli attributi {price: 10, description: 'lamp', priority: 10}

invoice = {price: 10, description: 'lamp', priority: 10} 

Diciamo che voglio copiare gli attributi invoice in un nuovo quote.

quote = Quote.new(invoice.attributes) 

Questo solleva un errore che priority non existe nel modello di Quote.

Come si copiano gli attributi invoice in un nuovo quote ma solo gli attributi che un quote può accettare?

risposta

19

È possibile select solo gli attributi che Quote ha:

Quote.new(invoice.attributes.select{ |key, _| Quote.attribute_names.include? key }) 

As noted by @aceofspades (ma non con una soluzione dinamica), è possibile utilizzare di ActiveSupport slice così:

Quote.new(invoice.attributes.slice(*Quote.attribute_names)) 
+0

Non tutti 'attribute_names' dovrebbero essere copiati però. 'id',' updated_at' e 'created_at' dovrebbero probabilmente essere' nil' in istanziazione. – Mischa

+3

Passando solo l'array restituisce {}, utilizzare sotto uno! Quote.new (invoice.attributes.slice (* Quote.attribute_names)) – Ajay

+0

@ajay Ciao, la tua risposta è davvero utile. Ho ottenuto lo stesso scenario per l'aggiunta di più attributi. quindi ho ricevuto un errore "attributi del metodo non definito". Come posso ripararlo? Grazie – Learner

0

Il modo più semplice è qualcosa del genere:

source = invoice.attributes 
target = (source.keys & Quote.attribute_names).inject({}) {|target, key| target[key] = source[key]; target } 
quote = Quote.new(target) 
12

E il metodo slice di ActiveSupport?

quote = Quote.new(invoice.attributes.slice(:price, :description)) 

o anche

quote = Quote.new(invoice.attributes.slice(*Quote.accessible_attributes)) 
+0

'accessible_attributes' sembra avere un comportamento strano, restituisce solo attributi che sono stati esplicitamente creati con' attr_accessible', quindi per impostazione predefinita questo non conterrà nessuno degli attributi. Questo, per me, è un bug in Rails però. –

+0

attr_accessible è davvero una buona idea, attribute_names potrebbe funzionare anche nella tua risposta. – aceofspades

+0

So che * dovresti * ma ciò non significa che le persone lo facciano (come è stato dimostrato domenica). Detto questo mi aspettavo che restituisse tutti gli attributi accessibili, non solo quelli esplicitamente contrassegnati come tali. –

Problemi correlati