是否可以在一个视图中从两个表单创建两个对象并使它们相关?

时间:2016-06-14 09:14:44

标签: ruby-on-rails simple-form ruby-on-rails-5

我知道这个标题听起来有点不稳定,但这正是我想要做的。

我有两个模型 - JobCompany。有人可以创建作业列表,但在保存列表之前,它应该与公司关联。该公司可以是新创建的,也可以由current_user之前创建的公司填充。

job belongs_to :companycompany 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的回答,这就是现在正在发生的事情。

当我在公司下拉列表中选择New Company时,它不会显示<fieldset>中的字段。我相信是这种情况,因为HTML中呈现的选择标记中没有value=0,如下面的屏幕截图所示。

enter image description here

修改2

在尝试Jay-Ar的最新更新后,JS仍无效,表单不再隐藏。

这是首次加载时的样子,并始终:

enter image description here

理想情况下,我希望此表单在下拉列表中选择“新公司”之前不会显示。

这就是HTML现在的样子:

enter image description here

JS确实出现在源代码中,所以我知道它正在正确地加载到资产管道中。

2 个答案:

答案 0 :(得分:2)

你应该使用嵌套的模型表单,我建议你看一下video它对问题/答案模型的步骤有一个非常详细的解释,但它是一样的。

答案 1 :(得分:2)

更新&amp;测试工作

  • 现在支持Turbolinks

视图/作业/ _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();
})

控制器/ 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

模型/ job.rb

class Job < ActiveRecord::Base
  accepts_nested_attributes_for :company
  validates :company, presence: true
  ...
end

您应该获得以下内容:

  • 新鲜负荷:

fresh page load

  • 选择'新公司'选项'后:

after selecting 'New Company' option