【问题标题】:has_many through update issuehas_many 通过更新问题
【发布时间】:2009-07-05 02:26:20
【问题描述】:

我已经尝试对这个进行排序超过一天了,我确信这是我缺少的一些简单的东西。

我有一个项目,它可以有一个主要类别和两个可选类别。我的项目模型的相关代码:

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'

Category 类的相关代码:

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

来自 ProjectCategory 类:

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

在我看来:

    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>

在我的控制器中:

      @project.attributes = params[:project]

好的,所以在更新现有项目时,我收到以下错误:

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

以及相关的堆栈跟踪:

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'

是不是说 main_category 存在问题并且它是一个泛型类?但为什么?该关联正确地定义了 AFAIK。

任何帮助表示赞赏!

维克拉姆

【问题讨论】:

    标签: ruby-on-rails has-many has-many-through


    【解决方案1】:

    我知道这并不能解决您遇到的错误,但我建议使用三个一对多关系而不是一个多对多关系。

    has_many :through =&gt; ...(多对多)的常规用途是当你有类似studentsclasses 的时候。一个学生可以在任何个班级。一个班级可以有任意个学生。关系两边的数字完全是任意的。

    但这不是你的情况。您的项目可以恰好属于一个主要类别、一个可选类别 1 和一个可选类别 2。这是一个完全不同的问题,这不是 has_many :through 旨在解决的问题。

    我建议这样安排:

    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
    

    然后您将能够执行以下操作:

    my_project.main_category
    
    my_category.optional_category_1_projects
    
    # etc...
    

    【讨论】:

    • 优秀。我从来没有完全理解has_many。这个问题的部分问题在于它来自遗留数据库,如果不重新处理许多其他事情,可能无法更改结构。但这是一个很好的建议,我会尝试看看我是否可以做到。我希望我能弄清楚为什么我的解决方案不起作用,因为它似乎在 has_many 的参数中是有效的。
    【解决方案2】:

    也许将控制器更改为:

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

    【讨论】:

    • 不,同样的错误。另外,在保存之前,我还需要对项目模型进行其他操作。
    【解决方案3】:

    您可能需要在视图中使用main_category_id,即

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

    您正在调用update_attributes,但main_category 并不是一个正确的属性——它是一个关联。 main_category_id 是一个属性。

    【讨论】:

    • 是的。但是,我实际上是在调用属性(而不是 update_attributes),当我在选择标记中替换 main_category_id 时,我得到了项目没有 main_category_id 属性的错误。它不会抱怨 main_category。
    【解决方案4】:

    你从哪里得到@project?你只是在做一个普通的Project.find(params[:project_id])还是什么?

    尝试抛出debugger 语句并查看@project 是什么类以及它有哪些方法?

    【讨论】:

    • 谢谢。是的。该项目来自此调用:@project = (Project.find(params[:id]) unless !params[:id]) || Project.new
    • 我认为这不是它抱怨的项目类。如果我从视图中删除类别,它不会抱怨。
    猜你喜欢
    • 2010-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-23
    • 2011-04-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多