has_many par numéro de mise à jour
-
23-08-2019 - |
Question
essayé de régler ce problème depuis plus d'un jour, et je suis sûr qu'il est quelque chose de simple que je suis absent.
J'ai un projet, ce qui peut avoir une catégorie principale et deux catégories en option. Mon code correspondant pour le modèle de projet:
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'
Le code correspondant de la catégorie classe:
has_many :project_categories
has_many :projects, :through => :project_categories, :source => :project
et de la classe ProjectCategory:
class ProjectCategory < ActiveRecord::Base
belongs_to :project
belongs_to :category
end
À mon avis:
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>
et dans mon contrôleur:
@project.attributes = params[:project]
Ok, donc quand la mise à jour d'un projet existant, je reçois l'erreur suivante:
undefined method `update_attributes' for #<Class:0x82efce0>
et la trace de la pile concernée:
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'
Est-il dire qu'il ya un problème avec main_category et qu'il est une classe générique? Mais pourquoi? L'association définit correctement AFAIK.
Toute aide appréciée!
Vikram
La solution
Je sais que cela ne résout pas l'erreur que vous obtenez, mais je suggère d'utiliser un trois à de nombreuses relations au lieu d'un grand nombre à plusieurs.
Le but classique de has_many :through => ...
(many-to-many) est pour quand vous avez quelque chose comme students
et classes
. Un étudiant peut être tout nombre de classes. Une classe peut avoir un certain nombre d'étudiants . nombres totalement arbitraire des deux côtés de la relation.
Mais ce n'est pas votre situation ici. Vos projets peuvent être exactement une catégorie principale, une catégorie en option 1, et une catégorie en option 2. Il est un problème tout à fait différent et il est pas le problème que has_many :through
est conçu pour résoudre.
Je suggère cet arrangement:
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
Ensuite, vous serez en mesure de faire des choses comme:
my_project.main_category
my_category.optional_category_1_projects
# etc...
Autres conseils
Peut-être changer le contrôleur à quelque chose comme:
@project = Project.find(params[:id])
@project.update_attributes(params[:project])
Vous devrez peut-être utiliser main_category_id
dans votre vue, i.e..
Main Category: <%= f.select(:main_category_id, ...) %>
Vous appelez update_attributes
, mais main_category
est pas correctement un attribut - c'est une association. main_category_id
est un attribut.
Où êtes-vous @project
de? Est-ce que vous faites juste un Project.find(params[:project_id])
normal ou quelque chose?
J'ai essayé de jeter dans une déclaration de debugger
et de voir quelle classe l'@project est et quelles méthodes il a sur elle?