是否可以在 1 个视图中从两个表单创建两个 objects 并将它们相关联?
Is it possible to create two objects from two forms in 1 view and have them related?
我知道标题听起来有点靠不住,但这就是我想要做的。
我有两个模型 - Job
和 Company
。有人可以创建职位列表,但在保存列表之前,它应该与公司相关联。这家公司可以是新创建的,或者应该从 current_user
之前创建的公司中填充。
一个job belongs_to :company
和一个company has_many :jobs
.
我知道我可以做两个不同的视图,只需将用户发送到两个不同控制器上的两个不同操作,但我想简化它并在一个视图中完成所有操作。
当他们转到 /jobs/new
时,他们应该会看到正常的 jobs/_form.html.erb
部分,但我希望能够显示现有公司或新公司创建字段的公司下拉列表用户填写,新公司与正在创建的新工作相关联。
这是我的 jobs/_form.html.erb
部分的样子:
<%= simple_form_for(@job) do |f| %>
<%= f.input_field :title %>
<%= f.input_field :salary %>
<%= f.input_field :description, as: :text %>
<%= f.input_field :apply_description, as: :text %>
<%= f.input_field :language %>
<%= f.input :premium, as: :boolean, inline_label: true, label: "Make this listing stand out", class: "form-control" %>
<%= f.button :submit, class: "btn btn-lg btn-primary pull-right" %>
<% end %>
这是我的 companies/_form.html.erb
的样子:
<%= simple_form_for(@company) do |f| %>
<%= f.input :name %>
<%= f.input :logo %>
<%= f.input :description %>
<%= f.input :city %>
<%= f.input :state %>
<%= f.input :country %>
<%= f.input :email %>
<%= f.button :submit %>
<% end %>
如何将它们合并为 1 个表单,或在 1 个视图中合并为用户无缝工作的其他统一工作流程?
编辑 1
根据Jay-Ar的回答,这就是现在发生的事情。
当我在公司下拉列表中 select New Company
时,它不显示 <fieldset>
中的字段。我认为是这种情况,因为在 HTML 中呈现的 select 标签中没有 value=0
,如下面的屏幕截图所示。
编辑 2
尝试 Jay-Ar 的最新更新后,JS 仍然无法正常工作,表单不再隐藏。
这是第一次加载时的样子,而且总是这样:
理想情况下,我希望在他们从下拉列表中选择 "New Company" 之前不要显示此表单。
这就是 HTML 现在的样子:
JS 确实出现在源代码中,所以我知道它正在正确加载到资产管道中。
你应该使用嵌套模型表单,我建议你看一下这个video它对问题/答案模型的步骤进行了非常详细的解释,但它是一回事。
更新和测试工作
- 现在支持 Turbolinks
views/jobs/_form.html.erb
<%= simple_form_for(@job) do |f| %>
<%# IMPORTANT: use `include_blank` below instead of `prompt` because prompt does not seem to work when updating, but only works when creating %>
<%= f.association :company, collection: [['New Company', nil]] + Company.pluck(:name, :id), include_blank: 'Please Select Company', input_html: { id: 'company-select' } %>
<fieldset id='job-fields'>
<%= f.simple_fields_for :company, @job.build_company do |ff| %>
<%= ff.input :name %>
<%= ff.input :logo %>
<%= ff.input :description %>
<%= ff.input :city %>
<%= ff.input :state %>
<%= ff.input :country %>
<%= ff.input :email %>
<% end %>
</fieldset>
<%= f.input_field :title %>
<%= f.input_field :salary %>
<%= f.input_field :description, as: :text %>
<%= f.input_field :apply_description, as: :text %>
<%= f.input_field :language %>
<%= f.input :premium, as: :boolean, inline_label: true, label: "Make this listing stand out", class: "form-control" %>
<%= f.button :submit, class: "btn btn-lg btn-primary pull-right" %>
<% end %>
JS
// for Rails 5, use turbolinks:load instead of page:change below
$(document).on('page:change', function(){
var companySelect = $('#company-select');
var jobFields = $('#job-fields');
companySelect.change(function(){
// if selected option is the second option
if ($(this).find('option:selected').index() == 1)
jobFields.show().find(':input').prop('disabled', false);
else
jobFields.hide().find(':input').prop('disabled', true);
})
// call change immediately so this still works when already updating and not just creating.
companySelect.change();
})
controllers/jobs_controller.rb
class JobsController < ApplicationController
...
def create
@job = Job.new(job_params)
...
end
def update
@job = Job.find(params[:id]) # not needed if using before_action #set_job
if @job.update(job_params)
...
end
private
def job_params
params.require(:job).permit(:id, :title, :salary, :description, :apply_description, :language, :premium, :company_id, company_attributes: [:name, :logo, :description, :city, :state, :country, :email]
end
end
models/job.rb
class Job < ActiveRecord::Base
accepts_nested_attributes_for :company
validates :company, presence: true
...
end
你应该得到如下内容:
- 新鲜加载:
- 选择 'New Company' 选项后':
我知道标题听起来有点靠不住,但这就是我想要做的。
我有两个模型 - Job
和 Company
。有人可以创建职位列表,但在保存列表之前,它应该与公司相关联。这家公司可以是新创建的,或者应该从 current_user
之前创建的公司中填充。
一个job belongs_to :company
和一个company has_many :jobs
.
我知道我可以做两个不同的视图,只需将用户发送到两个不同控制器上的两个不同操作,但我想简化它并在一个视图中完成所有操作。
当他们转到 /jobs/new
时,他们应该会看到正常的 jobs/_form.html.erb
部分,但我希望能够显示现有公司或新公司创建字段的公司下拉列表用户填写,新公司与正在创建的新工作相关联。
这是我的 jobs/_form.html.erb
部分的样子:
<%= simple_form_for(@job) do |f| %>
<%= f.input_field :title %>
<%= f.input_field :salary %>
<%= f.input_field :description, as: :text %>
<%= f.input_field :apply_description, as: :text %>
<%= f.input_field :language %>
<%= f.input :premium, as: :boolean, inline_label: true, label: "Make this listing stand out", class: "form-control" %>
<%= f.button :submit, class: "btn btn-lg btn-primary pull-right" %>
<% end %>
这是我的 companies/_form.html.erb
的样子:
<%= simple_form_for(@company) do |f| %>
<%= f.input :name %>
<%= f.input :logo %>
<%= f.input :description %>
<%= f.input :city %>
<%= f.input :state %>
<%= f.input :country %>
<%= f.input :email %>
<%= f.button :submit %>
<% end %>
如何将它们合并为 1 个表单,或在 1 个视图中合并为用户无缝工作的其他统一工作流程?
编辑 1
根据Jay-Ar的回答,这就是现在发生的事情。
当我在公司下拉列表中 select New Company
时,它不显示 <fieldset>
中的字段。我认为是这种情况,因为在 HTML 中呈现的 select 标签中没有 value=0
,如下面的屏幕截图所示。
编辑 2
尝试 Jay-Ar 的最新更新后,JS 仍然无法正常工作,表单不再隐藏。
这是第一次加载时的样子,而且总是这样:
理想情况下,我希望在他们从下拉列表中选择 "New Company" 之前不要显示此表单。
这就是 HTML 现在的样子:
JS 确实出现在源代码中,所以我知道它正在正确加载到资产管道中。
你应该使用嵌套模型表单,我建议你看一下这个video它对问题/答案模型的步骤进行了非常详细的解释,但它是一回事。
更新和测试工作
- 现在支持 Turbolinks
views/jobs/_form.html.erb
<%= simple_form_for(@job) do |f| %>
<%# IMPORTANT: use `include_blank` below instead of `prompt` because prompt does not seem to work when updating, but only works when creating %>
<%= f.association :company, collection: [['New Company', nil]] + Company.pluck(:name, :id), include_blank: 'Please Select Company', input_html: { id: 'company-select' } %>
<fieldset id='job-fields'>
<%= f.simple_fields_for :company, @job.build_company do |ff| %>
<%= ff.input :name %>
<%= ff.input :logo %>
<%= ff.input :description %>
<%= ff.input :city %>
<%= ff.input :state %>
<%= ff.input :country %>
<%= ff.input :email %>
<% end %>
</fieldset>
<%= f.input_field :title %>
<%= f.input_field :salary %>
<%= f.input_field :description, as: :text %>
<%= f.input_field :apply_description, as: :text %>
<%= f.input_field :language %>
<%= f.input :premium, as: :boolean, inline_label: true, label: "Make this listing stand out", class: "form-control" %>
<%= f.button :submit, class: "btn btn-lg btn-primary pull-right" %>
<% end %>
JS
// for Rails 5, use turbolinks:load instead of page:change below
$(document).on('page:change', function(){
var companySelect = $('#company-select');
var jobFields = $('#job-fields');
companySelect.change(function(){
// if selected option is the second option
if ($(this).find('option:selected').index() == 1)
jobFields.show().find(':input').prop('disabled', false);
else
jobFields.hide().find(':input').prop('disabled', true);
})
// call change immediately so this still works when already updating and not just creating.
companySelect.change();
})
controllers/jobs_controller.rb
class JobsController < ApplicationController
...
def create
@job = Job.new(job_params)
...
end
def update
@job = Job.find(params[:id]) # not needed if using before_action #set_job
if @job.update(job_params)
...
end
private
def job_params
params.require(:job).permit(:id, :title, :salary, :description, :apply_description, :language, :premium, :company_id, company_attributes: [:name, :logo, :description, :city, :state, :country, :email]
end
end
models/job.rb
class Job < ActiveRecord::Base
accepts_nested_attributes_for :company
validates :company, presence: true
...
end
你应该得到如下内容:
- 新鲜加载:
- 选择 'New Company' 选项后':