【问题标题】:Rails 4 HABTM stops working when I add "multiple true" to collection_select当我将“multiple true”添加到 collection_select 时,Rails 4 HABTM 停止工作
【发布时间】:2013-12-04 17:41:25
【问题描述】:

在过去的几天里,我在谷歌上搜索并尝试了我能想到的一切来解决 has_and_belongs_to_many 关系的一个相对简单(我认为)的问题。

我成功地使用 HABTM 关系提交了一个关系值。这是示例代码:

型号:

class Livre < ActiveRecord::Base
  has_and_belongs_to_many : auteurs
end

class Auteur < ActiveRecord::Base
  has_and_belongs_to_many :livres
end

控制器:

def new
  @livre = Livre.new
  @auteurs = Auteur.all
end

def create
  @livre = Livre.new(livre_params)
  if @livre.save
    redirect_to [:admin, @livre]
  else
    render 'new'
  end
end

private
  def livre_params
    params.require(:livre).permit(:name, :auteur_ids)
  end

查看:

<% f.label :auteur %><br>
<% f.collection_select(:auteur_ids, @auteurs, :id, :name) %>

发布的参数:

{"utf8"=>"✓",
 "authenticity_token"=>"mAXUm7MRDgJgCH00VPb9bpgC+y/iOfxBjXSazcthWYs=",
 "livre"=>{"name"=>"sdfsdfd",
 "auteur_ids"=>"3"},
 "commit"=>"Create Livre"}

但是当我尝试将“multiple true”添加到视图的collection_select 助手时,(现在是多个)关系不再被保存。示例代码:

(模型和控制器均不变)

查看:

<% f.label :auteur %><br>
<% f.collection_select(:auteur_ids, @auteurs, :id, :name, {}, {:multiple => true}) %>

发布的参数:

{"utf8"=>"✓",
 "authenticity_token"=>"mAXUm7MRDgJgCH00VPb9bpgC+y/iOfxBjXSazcthWYs=",
 "livre"=>{"name"=>"sdfsdf",
 "auteur_ids"=>["1",
 "5",
 "3"]},
 "commit"=>"Create Livre"}

如您所见,“auteur_ids”的参数现在是一个数组。这是唯一的区别。

我做错了什么?

澄清一下:两段代码都能够将新记录添加到livres db 表中,但只有第一个代码能够将适当的记录添加到auteurs_livres db 表中。第二个根本没有在auteurs_livres 中插入任何东西。

(我在 ruby​​ 1.9.3p194 和 rails 4.0.1 上运行)

谢谢!


回答

对于遇到同样问题的优秀人士,答案如下:

编辑您的控制器并将允许的参数从 :auteur_ids 更改为 {:auteur_ids =&gt; []}

params.require(:livre).permit(:name, {:auteur_ids => []})

它现在可以工作了:)

【问题讨论】:

  • 已编辑为两个代码示例添加已发布的参数。
  • 很好——你有没有考虑过使用accepts_nested_attributes_for
  • @RichPeck 不,但我要看看它。谢谢。
  • 我本来打算为它写一个答案,但如果你要调查,那就太酷了!让我知道您是否需要提供一些想法的答案
  • @RichPeck 请贡献。我对 rails 和 ruby​​ 还是很陌生,感谢任何指导:)

标签: ruby-on-rails ruby


【解决方案1】:

对于遇到同样问题的优秀人士,答案如下:

编辑您的控制器并将允许的参数从 :auteur_ids 更改为 {:auteur_ids =&gt; []}

params.require(:livre).permit(:name, {:auteur_ids => []})

它现在可以工作了:)

【讨论】:

    【解决方案2】:

    您找到了解决方案,因为 Rails 现在期望 auteur_ids 是一个数组,而不是单个项目。这意味着它不仅仅将单个实体传递给模型,而是将参数打包为[0][1][2] 等,这就是您现在可以提交您的 HABTM 记录的方式

    还有一种更丰富的 Rails 方法可以做到这一点,那就是使用accepts_nested_attributes_for。这似乎需要做更多的工作,但它会使您的系统枯竭,并确保约定优于配置:

    型号

    class Livre < ActiveRecord::Base
      has_and_belongs_to_many : auteurs
      accepts_nested_attributes_for :auteurs
    end
    
    class Auteur < ActiveRecord::Base
      has_and_belongs_to_many :livres
    end
    

    控制器

    def new
      @livre = Livre.new
      @livre.auteurs.build
    
      @auteurs = Auteur.all
    end
    
    def create
      @livre = Livre.new(livre_params)
      if @livre.save
        redirect_to [:admin, @livre]
      else
        render 'new'
      end
    end
    
    private
      def livre_params
        params.require(:livre).permit(:name, auteur_attributes: [:auteur_id])
      end
    

    表格

    <%= form_for @livre do |f| %>
        <%= f.text_field :your_current_vars %>
        <%= f.fields_for :auteurs do |a| %>
            <%= a.collection_select(:auteur_id, @auteurs, :id, :name, {}) %>
        <% end %>
    <% end %>
    

    这将为您提交auteur_id(并自动关联HABTM模型中的livre_id外键。目前,这将仅提交已在new操作中构建的对象数量——因此按顺序要添加更多项目,您必须构建更多项目

    【讨论】:

    • 完全不行……Rails 在这条线上抱怨undefined method auteur_id &lt;%= a.collection_select(:auteur_id, @auteurs, :id, :name, {}) %&gt;
    • Hmmmmm - 也许它可能是 :id 代替?
    • 这样可以消除错误并让我提交表单,但它不会记录关系。另外,我只能选择一个值,如果我添加 {:multiple =&gt; true} 选项,我可以选择多个值,但它也不会保存它们。不知何故,我之前发现的解决方案效果更好,更容易理解。我会坚持下去,但感谢您的帮助,我真的很感激!
    • 是的,这是一个小警告——要让accepts_nested_attributes_for 处理多个元素,涉及到一些向导。但是,它确实使应用程序超级干燥且符合惯例。没问题 - 如果您的版本更适合您,您应该使用它!我们喜欢用“艰难的方式”做事,这样我们就可以了解它们是如何工作的 :)
    猜你喜欢
    • 2021-07-08
    • 1970-01-01
    • 2012-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 1970-01-01
    相关资源
    最近更新 更多