【问题标题】:grouped_collection_select for has_many :through Association not Updating为 has_many 选择 grouped_collection_select :通过关联未更新
【发布时间】:2013-11-19 06:20:48
【问题描述】:

我有一个场景,我创建了一些 has_many :通过我无法更新的关联。我非常感谢任何帮助。

这是我的设置:

  • 红宝石 1.9.3p392
  • Rails 3.2.13

这是场景:

  • 我有 3 个相关的模型
  • 有很多行业、很多关键词和很多会议
  • 行业有很多关键词
  • 会议有一个行业
  • 会议根据行业选择关键字

Keywords 有一个基本的 CRUD 模型。创建一个行业然后添加关键字可以正常工作。

我与会议、行业和关键字的关系是我遇到问题的地方。我正在尝试更新会议信息,更改当前关联的行业,根据新行业选择新关键字,所有这些都以相同的形式。当我从组合中删除关键字元素时,更新工作。但是当所有三个都在那里时,我就会得到错误。

我对行业和关键字的关系是:

class IKeywordable < ActiveRecord::Base

attr_accessible :industry_id, :keyword_id

belongs_to :industry
belongs_to :keyword

end

class CKeywordable < ActiveRecord::Base
attr_accessible :conference_id, :keyword_id

belongs_to :conference
belongs_to :keyword
end

以下是模型:

class Industry < ActiveRecord::Base
attr_accessible :name, 
                :conferences_attributes,
                :i_keywordables_attributes, 
                :keywords,
                :keywords_attributes,
                :keyword_ids

validates       :name, presence: true
validates       :name, uniqueness: true

# Associations
has_many    :conferences
accepts_nested_attributes_for :conferences

#Keywords
has_many :i_keywordables
has_many :keywords, through: :i_keywordables
accepts_nested_attributes_for :i_keywordables
accepts_nested_attributes_for :keywords

end

class Keyword < ActiveRecord::Base

attr_accessible 
               :name, :profile_id, :active, :rating, 
               :c_keywordables_attributes,
               :i_keywordables_attributes,
               :industries_atributes

# Associations

#Industries
  has_many :i_keywordables
  has_many :industries, through: :i_keywordables
  accepts_nested_attributes_for :i_keywordables

#Conferences
  has_many :c_keywordables
  has_many :conferences, through: :c_keywordables
  accepts_nested_attributes_for :c_keywordables

end

class Conference < ActiveRecord::Base
attr_accessible 
              :name, :address1, :address2, :city, :email,
              :web, :profile_id, :state_id, :conference, 
              :description, :date_start, :date_end, :venue, :venue_web, 
              :organizer, :organizer_web, :c_keywordables_attributes, 
              :industry_attributes, :industry_id,
              :industry, :keyword_ids

# Associations

belongs_to :state
belongs_to :industry
accepts_nested_attributes_for :industry

#Keywords
has_many :c_keywordables
has_many :keywords, through: :c_keywordables
accepts_nested_attributes_for :c_keywordables

serialize :keywords, Array

  def to_s
     state_id
  end

end

这里是会议/edit.html.erb

  <h2>edit <%= @conference.name %></h2>
        <%= form_for  @conference do |c| %>
            <%= c.label :name %>
            <%= c.text_field :name %>
            <%= c.label :address1 %>
            <%= c.text_field :address1 %>
            <%= c.label :address2 %>
            <%= c.text_field :address2 %>
            <%= c.label :city %>
            <%= c.text_field :city %>
            <%= c.label :state_id%>
            <%= c.collection_select :state_id, State.order(:name), :id, :name %>
            <%= c.label :email %>
            <%= c.text_field :email %>
            <%= c.label :web %>
            <%= c.text_field :web %>
       <hr width="80%">
            <%= c.label :industry_id %>
            <%= c.collection_select :industry_id, Industry.order(:name), :id, :name %>
      <br />
            <%= c.fields_for :industry, @industry do |ci| %>
             <%= ci.label :keyword_id %>
             <%= ci.grouped_collection_select :keywords, Industry.order(:name),
                :keywords, 
                :name, 
                :id, 
                :name, 
                {:include_blank => true}, { :multiple => true }
                 %>
       <% end %>
    <br />
<p><%= c.submit %></p>
<% end %>

这是会议控制器:

def edit
    @conference = Conference.find(params[:id])
end

def update
    @conference = Conference.find(params[:id])
        if @conference.update_attributes(params[:conference])
            redirect_to action: "all", notice: 'conference was successfully updated.'
        else
            render action: "edit" 
        end
end

视图呈现正常,但是当我提交更改时,出现错误。我看到的错误是:

无法为 ID=1 的会议找到 ID=3 的行业

这里是传递的参数:

{"utf8"=>"✓", "_method"=>"put", "authenticity_token"=>"k9fcAXF/iOXt3oVuTcxeDCaWOfE2PrVlBvFbQG8Mo/I=", "conference"=>{"name"=> "测试会议", "address1"=>"address 1", "address2"=>"address 2", "city"=>"City", "state_id"=>"38", "email"=>"test @example.com", "web"=>"www.example.com", "industry_id"=>"1", "industry_attributes"=>{"keywords"=>["", "6", "5" ], "id"=>"3"}}, "commit"=>"Update Conference", "action"=>"update", "controller"=>"conferences", "id"=>"1"}

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 activerecord associations


    【解决方案1】:

    我认为问题是您的 Conference 类中以下两个语句之间的冲突:

    class Conference
      ...
    
      has_many :keywords, through: :c_keywordables
    
      ...
    
      serialize :keywords, Array do
        ...
      end
    end
    

    第一个对关键字的引用期望建立一个与关键字表的 ActiveRecord 关联,而第二个引用期望一个由 db 支持的属性(列)命名的关键字,它将保存数组数据的序列化 (yaml) 表示。他们正在为如何帮助你而争吵,而你是这场战斗中的失败者。

    【讨论】:

    • 感谢您的回复。我注释掉了 'serialize :keyword, Array do' 但仍然得到相同的错误 "authenticity_token"=>"GOJBEAHuPz2swO1zTXVgvgi9+JLBdIlSitnkThH6YRs=", "conference"=>{"name"=>"test conference", "address1 "=>"地址 1", "address2"=>"地址 2", "city"=>"city", "state_id"=>"38", "email"=>"test@example.com", " web"=>"www.example.com", "industry_id"=>"2", "industry_attributes"=>{"keywords"=>[""], "id"=>"3"}}, "commit "=>"Update Conference", "action"=>"update", "controller"=>"conferences", "id"=>"1"} 有什么想法吗?
    • 抱歉,我忽略了参数。当您在 Rails 中使用嵌套属性时,您基本上是在说:“我想用 ...abc... 更新这个主对象,并用 ...xyz... 更新关联对象”。在这种情况下,您的意思是“我想使用会议参数更新 Conference #1,并使用行业属性哈希更新 Industry#3。”我怀疑那不是你想要的。相反,如果您想创建 Conf 和 Industry 以及 Conf 和 Keywords 之间的关联,则消除 attributes_for。参数哈希应包含行业 ID 和关键字 ID。
    • 首先,当我删除 accepts_nested_attributes_for :industry 时,我收到一个错误“unknown attribute: industry_attributes”。然后我从 attr_accessible 中删除 :industry_attributes 并收到“Can't mass-assign protected attributes: industry_attributes”错误。跨度>
    • 检查您的表格。我假设表单的一部分显示了用户从中选择关键字的复选框。表单的这一部分被写入,以便在行业属性中返回“关键字”数组。如果您检查 HTML 表单,复选框的名称可能会显示“conference[industry_attributes][keywords][]”。这是表单中需要更改的部分——它们应该是 f.checkbox :keyword_ids 而不是 attributes_for。
    • 我使用了一个选择框,如 Railscast 插曲中动态选择菜单中所示,但我认为我需要先简化它,使用复选框,然后从那里开始。我会重新发布我的结果。谢谢!!
    【解决方案2】:

    @AndyV,我终于解决了这个问题。原来是我如何称呼协会的问题。我进入控制台以进一步调查我是如何与协会互动的。我想通过行业将关键字与会议相关联,这是错误的。所以既然我有:

     has_many :c_keywordables
     has_many :keywords, through: :c_keywordables
    

    我可以直接调用关键字。所以在控制台中,我可以这样做:

     > c = Conference.first
     > c.keyword_ids
     > []
     > c.keyword_ids = [ 1, 2, 3 ]
     => [ 1, 2, 3 ]
    

    所以我开始使用基本的复选框表单来尝试让事情发挥作用:

    在 Railscast 的帮助下

    <% Keyword.all.each do |keyword| %>
      <p>
       <%= check_box_tag "conference[keyword_ids][]", keyword.id, @conference.keyword_ids.include?(keyword.id) %>
       <%= keyword.name %>
      </p>
    <% end %>
    

    它奏效了!现在我将返回并尝试更复杂的形式,让它看起来像我想要的那样。

    感谢大家的帮助。我很感激!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-06-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-01
      相关资源
      最近更新 更多