如何从一种形式使用 fields_for 到 link 多个模型?
How to use fields_for to link multiple models from one form?
我正在构建一个注册应用程序。共有三种模型:Participant
、Volunteer_Detail
和Student_Detail
。 Participant
has_one
其他两个模型,而他们依次 belongs_to
Participant
。我正在尝试使用一种带有 fields_for 的表格向 Participant
和其他模型之一提供数据。
我一直收到错误消息,说用于 Student_Detail
的属性之一不是 Participant
的已定义属性。
我查看了 fields_for
上的几个指南,似乎有几种方法可以定义您的表单适用的第二个模型。
共识似乎应该是这样的:
<%= f.fields_for @participant.student_details do |student_detail_field| %>
<%= f.label :nationality, 'Nationality:' %>
<%= student_detail_field.text_field :nationality %>
然而,当我写 :student_details 而不是 @participant.student_details.
时,它似乎只显示我的表格
这是我的表格,显示了顶部部分,以及包含 fields_for 的部分(表格被修剪以保存 space):
<%= f.label :first_name, 'First:' %>
<%= f.text_field :first_name %>
<%= f.fields_for :student_details do |student_detail_field| %>
<%= f.label :nationality, 'Nationality:' %>
<%= student_detail_field.text_field :nationality %>
这是我的参与者控制器:
class ParticipantsController < ApplicationController
定义新
@参与者= Participant.new
结束
def new2
@participant= Participant.new
end
def create
@participant = Participant.create(participant_params)
@participant.save
if @participant.save
flash[:success] = "Successfully Registered!"
#email notifes admin of new registration
NotifyMailer.notify_email(@participant).deliver_later
redirect_to '/signup'
end
end
def edit
end
def update
end
def show
end
def index
end
private
def participant_params
params.require(:participant).permit(:first_name, :last_name, :gender, :email, :birthdate, :phone, :street_name, :city, :state, :zip, :nationality, :religion, :need_ride,
:has_spouse, :spouse_name, :english_level, :expectations, :length_of_stay, :exact_length, :volunteer_id, :matched, :returned_home, :participant_id, :participant_id_id)
end
end
这是服务器错误:
NoMethodError (undefined method `nationality' for #<Participant:0x000000000d039410>
Did you mean? Rational):
app/controllers/participants_controller.rb:11:in `create'
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (3.9ms)
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.0ms)
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.0ms)
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (790.6ms)
看看是否有人可以帮助澄清我的错误。
谢谢!
有几件事可能会有所帮助
如何定义has_one关系:
跟随 rails guide,因为参与者 has_one student_detail,那么 student_detail table 必须有字段 participant_id,也 volunteer_detail 必须有字段 participant_id
您可以将 participant.rb
(模型)设置为接受 student_detail 或 volunteer_detail 的嵌套属性(因为您说过为那些 table 提供一种形式)
class Participant < ActiveRecord::Base
has_one :student_detail, :dependent => :destroy
accepts_nested_attributes_for :student_detail, :allow_destroy => :true
# that allow_destroy is depend with your software design
has_one :volunteer_detail, :dependent => :destroy
accepts_nested_attributes_for :volunteer_detail, :allow_destroy => :true
end
如何为其他 table 设置 participant_params:
这里是为接受嵌套属性定义参与者参数的代码示例:
def participant_params
params.require(:participant).permit(
:first_name, :other_participant_field_name,
student_detail_attributes: [:participant_id, :other_student_field_name],
volunteer_detail_attributes: [:participant_id, :other_volunteer_field_name])
end
end
如果你想要学生记录的内容也用于 volunteer_detail
你可以在你的控制器中做(创建方法),我的提示尝试 refactor/redesign 最小化数据在你的系统中重复(学生和志愿者)
def create
@participant = Participant.create(participant_params)
@volunteer_detail = @participant.student_detail
# this will pass all the content of student detail to volunteer detail
if @participant.save
flash[:success] = "Successfully Registered!"
end
end
要了解更多关于接受嵌套属性我建议你学习railcast 196虽然它看起来很老但是你可以学习这个概念
我正在构建一个注册应用程序。共有三种模型:Participant
、Volunteer_Detail
和Student_Detail
。 Participant
has_one
其他两个模型,而他们依次 belongs_to
Participant
。我正在尝试使用一种带有 fields_for 的表格向 Participant
和其他模型之一提供数据。
我一直收到错误消息,说用于 Student_Detail
的属性之一不是 Participant
的已定义属性。
我查看了 fields_for
上的几个指南,似乎有几种方法可以定义您的表单适用的第二个模型。
共识似乎应该是这样的:
<%= f.fields_for @participant.student_details do |student_detail_field| %>
<%= f.label :nationality, 'Nationality:' %>
<%= student_detail_field.text_field :nationality %>
然而,当我写 :student_details 而不是 @participant.student_details.
时,它似乎只显示我的表格这是我的表格,显示了顶部部分,以及包含 fields_for 的部分(表格被修剪以保存 space):
<%= f.label :first_name, 'First:' %>
<%= f.text_field :first_name %>
<%= f.fields_for :student_details do |student_detail_field| %>
<%= f.label :nationality, 'Nationality:' %>
<%= student_detail_field.text_field :nationality %>
这是我的参与者控制器:
class ParticipantsController < ApplicationController 定义新 @参与者= Participant.new 结束
def new2
@participant= Participant.new
end
def create
@participant = Participant.create(participant_params)
@participant.save
if @participant.save
flash[:success] = "Successfully Registered!"
#email notifes admin of new registration
NotifyMailer.notify_email(@participant).deliver_later
redirect_to '/signup'
end
end
def edit
end
def update
end
def show
end
def index
end
private
def participant_params
params.require(:participant).permit(:first_name, :last_name, :gender, :email, :birthdate, :phone, :street_name, :city, :state, :zip, :nationality, :religion, :need_ride,
:has_spouse, :spouse_name, :english_level, :expectations, :length_of_stay, :exact_length, :volunteer_id, :matched, :returned_home, :participant_id, :participant_id_id)
end
end
这是服务器错误:
NoMethodError (undefined method `nationality' for #<Participant:0x000000000d039410>
Did you mean? Rational):
app/controllers/participants_controller.rb:11:in `create'
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_source.html.erb (3.9ms)
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_trace.html.erb (1.0ms)
Rendering C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/_request_and_response.html.erb (1.0ms)
Rendered C:/Ruby24-x64/lib/ruby/gems/2.4.0/gems/actionpack-5.0.7.1/lib/action_dispatch/middleware/templates/rescues/diagnostics.html.erb within rescues/layout (790.6ms)
看看是否有人可以帮助澄清我的错误。
谢谢!
有几件事可能会有所帮助
如何定义has_one关系:
跟随 rails guide,因为参与者 has_one student_detail,那么 student_detail table 必须有字段 participant_id,也 volunteer_detail 必须有字段 participant_id
您可以将
participant.rb
(模型)设置为接受 student_detail 或 volunteer_detail 的嵌套属性(因为您说过为那些 table 提供一种形式)class Participant < ActiveRecord::Base has_one :student_detail, :dependent => :destroy accepts_nested_attributes_for :student_detail, :allow_destroy => :true # that allow_destroy is depend with your software design has_one :volunteer_detail, :dependent => :destroy accepts_nested_attributes_for :volunteer_detail, :allow_destroy => :true end
如何为其他 table 设置 participant_params:
这里是为接受嵌套属性定义参与者参数的代码示例:
def participant_params params.require(:participant).permit( :first_name, :other_participant_field_name, student_detail_attributes: [:participant_id, :other_student_field_name], volunteer_detail_attributes: [:participant_id, :other_volunteer_field_name]) end end
如果你想要学生记录的内容也用于
volunteer_detail
你可以在你的控制器中做(创建方法),我的提示尝试 refactor/redesign 最小化数据在你的系统中重复(学生和志愿者)def create @participant = Participant.create(participant_params) @volunteer_detail = @participant.student_detail # this will pass all the content of student detail to volunteer detail if @participant.save flash[:success] = "Successfully Registered!" end end
要了解更多关于接受嵌套属性我建议你学习railcast 196虽然它看起来很老但是你可以学习这个概念