【问题标题】:Rails 5 - has_many through: and nested fields_for in formsRails 5 - has_many through: 和嵌套 fields_for 表单
【发布时间】:2018-04-23 22:21:43
【问题描述】:

我是 RoR 的新手(使用 rails 5)并且遇到了 has_many through: 关联的问题。

我想为不同的语言创建具有不同标签的类别。

这是我的模型:

class Language < ApplicationRecord
  has_many :category_infos
  has_many :categories, through: :category_infos
end

class Category < ApplicationRecord
  has_many :category_infos
  has_many :languages, through: :category_infos
  accepts_nested_attributes_for :category_infos
end

class CategoryInfo < ApplicationRecord
  belongs_to :language
  belongs_to :category
  accepts_nested_attributes_for :language
end

控制器:

class CategoriesController < ApplicationController

  def new
    @category = Category.new
    @languages = Language.all
    @languages.each do |language|
      @category.category_infos.new(language:language)
    end
  end

  def create
    @category = Category.new(category_params)
    if @category.save
      redirect_to @category
    else
      render 'new'
    end
  end

  private
    def category_params
      params.require(:category).permit(:name, category_infos_attributes:[:label, language_attributes: [:id, :language]])
    end

end

形式:

<%= form_with model: @category, local: true do |form| %>
  <% if @category.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@category.errors.count, "error") %>:
      </h2>
      <ul>
        <% @category.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
    <br/>
  <% end %>
  <p>
    <%= form.label :name %>
    <%= form.text_field :name %>
  </p>
  <p>
    Labels:
  </p>
  <table>
    <% @category.category_infos.each do |category_info| %>
      <tr>
        <td>
          <%= category_info.language.name %>
        </td>
        <td>
          <%= form.fields_for :category_infos, category_info do |category_info_form| %>
            <%= category_info_form.fields_for :language, category_info.language do |language_form| %>
              <%= language_form.hidden_field :id, value: category_info.language.id %>
              <%= language_form.hidden_field :name, value: category_info.language.name %>
            <% end %>
            <%= category_info_form.text_field :label %>
          <% end %>
        </td>
      </tr>  
    <% end %>
  </table>
  <p>
    <%= form.submit %>
  </p>
<% end %>

当我创建一个新类别时,我收到了这个错误:

Couldn't find Language with ID=1 for CategoryInfo with ID=

在线:

@category = Category.new(category_params)

但是我已经在数据库中注册了几种语言(1 = 英语,2 = 法语等...)

我需要如何编写表单,以便我可以同时以英语、法语等...创建一个类别及其类别信息?

提前感谢您的回答

【问题讨论】:

    标签: ruby-on-rails nested-forms has-many-through fields-for


    【解决方案1】:

    当您只想通过传递 id 创建关联时,您犯了一个经典的新手错误并使用 fields_for

    <%= form_with model: @category, local: true do |f| %>
    
      # ... 
    
      <%= f.fields_for :category_infos do |cif| %>
        <%= cif.collection_select(:language_id, Language.all, :name, :id) %>
        <%= cif.text_field :label %>
      <% end %>
    <% end %>
    

    虽然您也可以传递属性让用户同时创建语言,但它在很大程度上是一种反模式,因为它为单个控制器添加了大量的职责。如果允许用户创建类别但不允许创建语言,也会产生授权问题。

    如果您需要该功能,请使用 ajax 将请求发送到单独的语言控制器。

    【讨论】:

    • 感谢您的快速回答。 Ofc 我还需要像这样更新 params 控件:params.require(:category).permit(:name, category_infos_attributes:[:language_id, :label])
    猜你喜欢
    • 2011-06-07
    • 2011-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-22
    • 2015-11-27
    • 2016-02-03
    • 1970-01-01
    相关资源
    最近更新 更多