Rails4中的嵌套简单表单 - 有很多通过,保存多个记录

2023-12-26

我通过关系得到了一个标准的 has_many 。 人类通过一个连接表与许多兽人进行交互。交互只是一个表格和模型;没有控制器或视图。

使用 Rails 4 中的 simpleform gem,我想从人类页面创建一个表单,以便从所有兽人池中选择多个兽人。提交后,我希望它在交互表中创建/更新尽可能多的记录,每个记录都有人类 ID,并选择尽可能多的兽人 ID。 :

又名列表表示法

  1. 从一端制作一个表格(人类)
  2. 列出表格中所有的兽人
  3. 从该列表中选择多个兽人
  4. 将尽可能多的记录保存到交互表中human_id and orc_id因为兽人是从该名单中选出的。 (这些记录中的 human_id 是相同的,因为它是从给定的人类表单页面开始的)

我将尽可能多地编写整个故事的代码。请随时要求澄清,并修复任何错误以实现此目的。

Tables

humans
  integer "id"

interactions
  integer "human_id"
  integer "orc_id"


  index ["human_id", "orc_id"] 
  # This is the primary key. no normal id.
  # Is it better to have a primary id for this join table, or does it not matter?

orcs
  integer "id"

Models

/模型/人类.rb

class Human < ActiveRecord::Base
  has_many :interaction
  has_many :orcs, through: :interactions

  accepts_nested_attributes_for :interactions
end

/模型/交互.rb

# Purely a join model and table. No controller, no scaffold.
class Interaction <ActiveRecord::Base
  belongs_to :human
  belongs_to :orc

  accepts_nested_attributes_for :orc 
  # Singular to match what was specified in the belongs_to relationship?
  # Do I even need this if I'm only trying to read orcs to save their id into the interactions table, and not trying to modify orcs?
end

/models/orc.rb

class Orc< ActiveRecord::Base
  has_many :interactions
  has_many :humans, through: :interactions

end

控制器

/controllers/ humans_controller.rb

class HumansController < ApplicationController

  before_action :set_human,         only: [:show, :edit, :update, :destroy]
  before_action :build_interaction, only: [:new, :edit]

  private
    def set_human
      @human = Human.find(params[:id])
    end

    def human_params
      params.require(:human).permit(
                                    interaction_attributes: [:human_id, 
                                                             :orc_ids,   # Is plural here correct?
                                                             :_destroy]
      )
    end

    def build_interaction
      @interaction = @human.interactions.build
                     # Is the human instance variable valid here?
                     # How many interactions are being built here?
                     # How do I ensure there are as many interaction builds as there will be selected orcs (i.e. as many interaction records to be saved or updated)?
    end
end

/controllers/orcs_controller.rb

class OrcsController < ApplicationController

  before_action :set_orc,   only: [:show, :edit, :update, :destroy]

  private
    def set_orc
      @orc = Orc.find(params[:id])
    end

    def orc_params
      params.require(:orc).permit()
    end

end

Views

/views/ humans/_form.html.haml

= simple_form_for(@human, html: { multipart: true }) do |f|
  = f.simple_fields_for :interactions do |i|
    = i.hidden_field :human_id, value: @human.id
    = i.association :orc, collection: Orc.all
                    ^                        
                    # Should this be :orc_id?
                    # Does this code automatically extract the orc_id when saving to the interactions table?

谢谢。

我缺少什么? 当我提交时,我确认交互连接表中没有创建任何记录。

我认为一些挑战是

  1. 重用单个隐藏输入字段创建多个记录。
  2. 当交互表必须是单个兽人时获取兽人列表(因为它是在交互模型中使用belongs_to :orc定义的)

另外,我在哪里可以找到更多关于如何使用模型 id 的复数形式的信息(即简单地使用orc_ids代替orc_id,以及这会带来什么具体后果)?


事实证明与simple_form这实际上相当简单(谁知道?)。它处理所有中间表的魔力(以及 Rails 的强大功能)。您需要做的就是:

= simple_form_for(@human, html: { Pmultipart: true }), do |f|
  = f.association :orcs

我并没有真正使用 HAML,所以我之前不确定那个逗号do |f|。这是我想在 ERB HTML 中表达的内容

<%= simple_form_for(@human) do |f| %>
  <%= f.association :orcs %>
<% end %>

然后在控制器的参数消毒器中:

def orc_params
  params.require(:orc).permit(orc_ids: [])
end

最后在你的模型中:

class Human < ActiveRecord::Base
  ...
  accepts_nested_attributes_for :orcs
end

就是这样!它将自动创建连接对象。你不是很喜欢魔法吗?

这将生成一个由所有兽人填充的多选字段。您可以使用以下方法轻松地将其更改为复选框f.association :orcs, as: :check_boxes.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Rails4中的嵌套简单表单 - 有很多通过,保存多个记录 的相关文章

随机推荐