ahn*_*cad 3 ruby-on-rails nested-forms has-many-through simple-form
通过关系,我有一个标准的has_many.人类通过连接表交互有许多兽人.互动只是一个表格和模型; 没有控制器或视图.
使用Rails 4中的simpleform gem,我想从人体页面创建一个表单,以便从所有兽人的池中选择多个兽人.提交后,我希望它在交互表中创建/更新尽可能多的记录,每个记录都包含人工ID,并且选择了多个orc ID.:
AKA列表符号
human_id并且orc_id从该列表中选择兽人.(human_id在这些记录中将是相同的,因为它从给定的人类表单页面开始)我将尽可能多地编写整个故事的代码.请随时要求澄清,并解决任何错误,以实现这一点.
表
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"
Run Code Online (Sandbox Code Playgroud)
楷模
/models/human.rb
class Human < ActiveRecord::Base
has_many :interaction
has_many :orcs, through: :interactions
accepts_nested_attributes_for :interactions
end
Run Code Online (Sandbox Code Playgroud)
/models/interaction.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
Run Code Online (Sandbox Code Playgroud)
/models/orc.rb
class Orc< ActiveRecord::Base
has_many :interactions
has_many :humans, through: :interactions
end
Run Code Online (Sandbox Code Playgroud)
控制器
/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
Run Code Online (Sandbox Code Playgroud)
/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
Run Code Online (Sandbox Code Playgroud)
查看
/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?
Run Code Online (Sandbox Code Playgroud)
谢谢.
我错过了什么?当我提交时,我确认在交互连接表中没有创建记录.
我认为有些挑战是
另外,在哪里可以找到更多关于如何使用复数形式的模型ID的工作(即简单地使用orc_ids代替orc_id,以及具体的后果)?
事实证明,simple_form这实际上相当简单(谁知道?).它处理所有中间表的魔力(与Rails的真棒一起).你需要做的就是:
= simple_form_for(@human, html: { Pmultipart: true }), do |f|
= f.association :orcs
Run Code Online (Sandbox Code Playgroud)
我真的没有使用HAML所以我以前不确定这个逗号do |f|.以下是我在ERB HTML中要说的内容
<%= simple_form_for(@human) do |f| %>
<%= f.association :orcs %>
<% end %>
Run Code Online (Sandbox Code Playgroud)
然后在您的控制器的param清洁剂中:
def orc_params
params.require(:orc).permit(orc_ids: [])
end
Run Code Online (Sandbox Code Playgroud)
最后在你的模型中:
class Human < ActiveRecord::Base
...
accepts_nested_attributes_for :orcs
end
Run Code Online (Sandbox Code Playgroud)
就是这样!它将自动创建连接对象.难道你不爱魔术吗?
这将生成由所有兽人填充的多选字段.您可以使用,轻松地将其更改为复选框f.association :orcs, as: :check_boxes.