7

Ich habe die folgenden Klassen:Können verschachtelte Attribute in Kombination mit Vererbung verwendet werden?

  • Projekt
  • Person
  • Person>Entwickler
  • Person>-Manager

Im Project Modell habe ich die folgenden Anweisungen hinzugefügt:

has_and_belongs_to_many :people 
accepts_nested_attributes_for :people 

Und natürlich die entsprechenden Aussagen in der Klasse Person. Wie kann ich eine Developer zu einer Project über die Methode hinzufügen? Die folgende funktioniert nicht:

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

Wie Sie die type Attribute sehen können, ist auf nil statt "Developer".

Antwort

5

Ich bin vor ein paar Tagen auf ein ähnliches Problem gestoßen. Die Vererbungsspalte (d. H. type) in einem STI-Modell ist ein geschütztes Attribut. Führen Sie folgende Schritte aus, um den Standardschutz in Ihrer Klasse Person zu überschreiben.

Rails 2,3

class Person < ActiveRecord::Base 

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

Rails 3

die von @tokland vorgeschlagen solution finden.

Caveat:

Sie das Überschreiben der Systemattribut geschützt.

Referenz:

SO Question on the topic

+0

Hinweis: Dies funktioniert für Rails 2.3, siehe meine Antwort unten für Rails 3 – tokland

+0

@tokland, ich hatte diese Frage für einige Zeit nicht besucht. Ich habe meine Antwort mit einer Rails 3-Lösung aktualisiert. –

+0

großartig. Ich würde ein einfaches 'def self.atattributes_protected_by_default' schreiben, aber was auch immer. – tokland

4

Patches oben nicht für mich arbeiten, aber dies tat (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 ').Klasse == Baz

+0

Diese Lösung funktioniert für Assoziationen, aber nicht für die STI-Objektkonstruktion. Ich habe meine Antwort mit einer generischen Rails 3-Lösung aktualisiert. –

7

Lösung für Rails3: attributes_protected_by_default in jetzt eine Klasse-Methode:

class Person < ActiveRecord::Base 

    private 

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

+1 Dies ist knapp. –

+0

Hinweis: Stellen Sie sicher, dass Sie dies in der Nähe der Spitze der Klasse * vor * alle Aufrufe von 'attr_protected' setzen. Der erste Aufruf von 'attr_protected' wird dazu führen, dass es die aktuell definierte Version von' attributes_protected_by_default' aufruft. Dies ist die Standardversion von AR, es sei denn, Sie haben es bis zu diesem Punkt überschrieben ... –

0

Für diejenigen von uns mit Mongoid, müssen Sie erreichen die _type Feld machen:

class Person 
    include Mongoid::Document 
    attr_accessible :_type 
end 
Verwandte Themen