2009-07-05 10 views
0

Ich habe versucht, dies für über einen Tag zu sortieren, und ich bin mir sicher, dass es etwas einfaches ist, das ich vermisse.has_many durch Update Problem

Ich habe ein Projekt, das eine Hauptkategorie und zwei optionale Kategorien haben kann. Mein entsprechender Code für das Projektmodell:

has_many :project_categories 

has_one :optional_category_1, 
     :through => :project_categories, 
     :conditions => 'is_main_category = 0', 
     :order => 'category_id', 
     :source => :category, 
     :class_name => 'Category' 

has_one :optional_category_2, 
     :through => :project_categories, 
     :conditions => 'is_main_category = 0', 
     :order => 'category_id DESC', 
     :source => :category, 
     :class_name => 'Category' 

has_one :main_category, 
     :through => :project_categories, 
     :conditions => 'is_main_category = 1', 
     :source => :category, 
     :class_name => 'Category' 

Der entsprechende Code aus der Kategorie Klasse:

has_many :project_categories 
has_many :projects, :through => :project_categories, :source => :project 

und von der ProjectCategory Klasse:

class ProjectCategory < ActiveRecord::Base 
    belongs_to :project 
    belongs_to :category 
end 

Aus meiner Sicht:

Main Category: <%= f.select(:main_category, Category.find(:all, :order => 'parent_id, categories.desc').collect {|c| [c.display_name, c.id] }, :prompt => "Select a Main Category") %><br> 
Optional Category 1: <%= f.select(:optional_category_1, Category.find(:all, :order => 'parent_id, categories.desc').collect {|c| [c.display_name, c.id] }, :prompt => "Select an Optional Category") %><br> 
Optional Category 2: <%= f.select(:optional_category_2, Category.find(:all, :order => 'parent_id, categories.desc').collect {|c| [c.display_name, c.id] }, :prompt => "Select an Optional Category") %><br> 

und in meiner co ntroller:

 @project.attributes = params[:project] 

Ok, also wenn ein vorhandenes Projekt zu aktualisieren, erhalte ich folgende Fehlermeldung:

undefined method `update_attributes' for #<Class:0x82efce0> 

und den entsprechenden Stack-Trace:

C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/associations.rb:1255:in `main_category=' 
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2745:in `send' 
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2745:in `attributes=' 
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2741:in `each' 
C:/Software/Ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record/base.rb:2741:in `attributes=' 
C:/Development/craftbits_rails/app/controllers/projects_controller.rb:85:in `manage_project' 

es ist zu sagen, dass es ein Problem mit main_category und dass es sich um eine generische Klasse handelt? Aber warum? Die Assoziation definiert es richtig AFAIK.

Jede Hilfe wird geschätzt!

@project = Project.find(params[:id]) 
@project.update_attributes(params[:project]) 

Antwort

0

Ich weiß, dass dies nicht den Fehler behandelt, den Sie bekommen, aber ich würde vorschlagen, drei Eins-zu-viele-Beziehungen statt einer Viele-zu-Viele-Beziehung zu verwenden.

Der herkömmliche Zweck von (viele-zu-viele) ist für, wenn Sie so etwas wie und classes haben. Ein Student kann in jeder Anzahl der Klassen sein. Eine Klasse kann beliebig Anzahl der Studenten haben. Völlig willkürliche Zahlen auf beiden Seiten der Beziehung.

Aber das ist nicht Ihre Situation hier.Ihre Projekte können in genau einer Hauptkategorie, einer optionalen Kategorie 1 und einer optionalen Kategorie 2 sein. Es ist ein völlig anderes Problem und es ist nicht das Problem, das has_many :through lösen soll.

Ich schlage vor, diese Anordnung:

class Project < ActiveRecord::Base 

    belongs_to :main_category, :class_name => "Category", 
    :foreign_key => 'main_category_id' 

    belongs_to :optional_category_1, :class_name => "Category", 
    :foreign_key => 'optional_category_1_id' 

    belongs_to :optional_category_2, :class_name => "Category", 
    :foreign_key => 'optional_category_2_id' 

end 

class Category < ActiveRecord::Base 

    has_many :main_category_projects, :class_name => "Project", 
    :foreign_key => 'main_category_id' 

    has_many :optional_category_1_projects, :class_name => "Project", 
    :foreign_key => 'optional_category_1_id' 

    has_many :optional_category_2_projects, :class_name => "Project", 
    :foreign_key => 'optional_category_2_id' 

end 

Dann werden Sie in der Lage sein, Dinge zu tun wie:

my_project.main_category 

my_category.optional_category_1_projects 

# etc... 
+0

Ausgezeichnet. Ich habe has_many nie gut genug verstanden. Ein Teil des Problems mit diesem Problem ist, dass es aus einer Legacy-Datenbank stammt, in der eine Änderung der Struktur möglicherweise nicht möglich ist, ohne viele andere Dinge zu überarbeiten. Aber das ist ein guter Vorschlag, und ich werde versuchen zu sehen, ob ich es kann. Ich wünschte, ich könnte herausfinden, warum meine Lösung nicht funktioniert, da sie innerhalb der Parameter von has_many durch gültig zu sein scheint. –

0

Vielleicht den Controller etwas wie ändern ist nicht richtig ein Attribut - es ist eine Assoziation. main_category_id ist ein Attribut.

+0

Nein, gleiche Fehler. Außerdem muss ich vor dem Speichern andere Dinge zum Projektmodell machen. –

0

Sie müssen möglicherweise main_category_id in Ihrer Ansicht verwenden, dh

Main Category: <%= f.select(:main_category_id, ...) %> 

Sie update_attributes nennen, aber main_category:

Vikram

+0

Wahr. Allerdings rufe ich tatsächlich Attribute (und nicht update_attributes) auf, und wenn ich main_category_id im select-Tag ersetze, erhalte ich den Fehler, dass das Projekt das main_category_id-Attribut nicht besitzt. Es meckert nicht über main_category. –

0

Woher bekommen Sie @project? Machst du gerade einen normalen Project.find(params[:project_id]) oder etwas?

Versucht, eine debugger Anweisung zu werfen und zu sehen, welche Klasse das @Projekt ist und welche Methoden es hat?

+0

Danke. Ja. Das Projekt kommt von diesem Aufruf: @project = (Project.find (params [: id]), außer! Params [: id]) || Project.new –

+0

Und ich denke, es ist nicht die Projektklasse, über die es sich beschwert. Wenn ich die Kategorien aus der Ansicht entferne, wird nicht geklagt. –