7

Ho le seguenti classi:Gli attributi nidificati possono essere utilizzati in combinazione con l'ereditarietà?

  • progetto
  • persona
  • persona>Developer
  • Person>Gestione

Nel modello Project ho aggiunto le seguenti dichiarazioni:

has_and_belongs_to_many :people 
accepts_nested_attributes_for :people 

E, naturalmente, le dichiarazioni appropriate nella classe Person. Come posso aggiungere uno Developer a Project tramite il metodo nested_attributes? Quanto segue non funziona:

@p.people_attributes = [{:name => "Epic Beard Man", :type => "Developer"}] 
@p.people 
=> [#<Person id: nil, name: "Epic Beard Man", type: nil>] 

Come si può vedere gli attributi type è impostato su nil invece di "Developer".

risposta

5

Ho riscontrato un problema simile qualche giorno fa. La colonna di ereditarietà (ad esempio type) in un modello STI è un attributo protetto. Effettuare le seguenti operazioni per ignorare la protezione predefinita nella classe Person.

Rails 2.3

class Person < ActiveRecord::Base 

private 
    def attributes_protected_by_default 
    super - [self.class.inheritance_column] 
    end 
end 

Rails 3

Fare riferimento alla solution suggerito da @tokland.

Caveat:

Stai sovrascrivendo il sistema protetto attributo.

Riferimento:

SO Question on the topic

+0

nota: questo funziona per Rails 2.3, vedere la mia risposta qui sotto per Rails 3 – tokland

+0

@tokland, non avevo visitato questa domanda per qualche tempo. Ho aggiornato la mia risposta con una soluzione Rails 3. –

+0

ottimo. Scriverei un semplice 'def self.attributes_protected_by_default', ma qualunque cosa. – tokland

4

patch di cui sopra non ha funzionato per me, ma questo fatto (Rails3):

class ActiveRecord::Reflection::AssociationReflection 
    def build_association(*options) 
    if options.first.is_a?(Hash) and options.first[:type].presence 
     options.first[:type].to_s.constantize.new(*options) 
    else 
     klass.new(*options) 
    end 
    end 
end 

Foo.bars.build (: type =>' baz ').Classe == Baz

+0

Questa soluzione funziona per associazioni, ma non per la costruzione di oggetti STI stand-by. Ho aggiornato la mia risposta con una soluzione Rails 3 generica. –

7

Soluzione per Rails3: attributes_protected_by_default ora una classe di metodo:

class Person < ActiveRecord::Base 

    private 

    def self.attributes_protected_by_default 
    super - [inheritance_column] 
    end 
end 
+0

+1 questo è conciso .. –

+0

Nota: assicurati di metterlo vicino all'inizio della classe, * prima * qualsiasi chiamata a "attr_protected". La prima chiamata a "attr_protected' causerà il richiamo di qualunque versione di' attributes_protected_by_default' è attualmente definita, che sarà la versione predefinita da AR a meno che non l'abbia sovrascritta da quel punto ... –

0

Per quelli di noi utilizzando Mongoid, sarà necessario rendere il campo _type accessibile:

class Person 
    include Mongoid::Document 
    attr_accessible :_type 
end