has_many mediante emissione aggiornamento
-
23-08-2019 - |
Domanda
cercato di risolvere la questione per più di un giorno all'altro, e sono sicuro che si tratta di qualcosa di semplice che mi manca.
Ho un progetto, che può avere una categoria principale e due categorie opzionali. Il mio codice rilevanti per il modello di progetto:
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'
Il relativo codice dalla classe Categoria:
has_many :project_categories
has_many :projects, :through => :project_categories, :source => :project
e dalla classe ProjectCategory:
class ProjectCategory < ActiveRecord::Base
belongs_to :project
belongs_to :category
end
A mio parere:
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>
e nel mio controllo:
@project.attributes = params[:project]
Ok, quindi quando si aggiorna un progetto esistente, ricevo il seguente errore:
undefined method `update_attributes' for #<Class:0x82efce0>
e la relativa analisi dello stack:
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'
E 'dicendo che c'è un problema con main_category e che si tratta di una classe generica? Ma perché? L'associazione definisce correttamente AFAIK.
Qualsiasi aiuto apprezzato!
Vikram
Soluzione
So che questo non risolve l'errore che stai ricevendo, ma mi piacerebbe suggerisco di usare tre uno-a-molti invece di uno molti-a-molti.
Lo scopo convenzionale di has_many :through => ...
(molti-a-molti) è per quando si ha qualcosa come students
e classes
. Uno studente può essere in qualsiasi il numero di classi. Una classe può avere qualsiasi numero di studenti. Numeri totalmente arbitrari su entrambi i lati della relazione.
Ma non è la situazione qui. I vostri progetti possono essere esattamente una categoria principale, una categoria opzionale 1, e una categoria opzionale 2. E 'un problema totalmente diverso e non è il problema che has_many :through
è stato progettato per risolvere.
Suggerisco questa disposizione:
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
Allora sarete in grado di fare cose del genere:
my_project.main_category
my_category.optional_category_1_projects
# etc...
Altri suggerimenti
Forse cambiare il controller per qualcosa come:
@project = Project.find(params[:id])
@project.update_attributes(params[:project])
Potrebbe essere necessario utilizzare main_category_id
nella vista, cioè.
Main Category: <%= f.select(:main_category_id, ...) %>
Si sta chiamando update_attributes
, ma main_category
non è propriamente un attributo - è un'associazione. main_category_id
è un attributo.
Dove vuoi arrivare @project
da? Stai solo facendo un Project.find(params[:project_id])
normale o qualcosa del genere?
Ho provato gettando in un comunicato debugger
e vedere quale classe il @project è e quali sono i metodi che ha su di esso?