I know the title sounded a bit wonky, but this is what I am trying to do.
I have two models - Job
and Company
. Someone can create a Job listing, but before the listing is saved, it should be associated with a company. This company can be newly created, or should be populated from companies the current_user
has previously created.
A job belongs_to :company
, and a company has_many :jobs
.
I know I could do two different views, and just send the user to two different actions on two different controllers, but I would like to simplify it and just have everything done in one view.
When they go to /jobs/new
, they should see the normal jobs/_form.html.erb
partial, but I would love to be able to show either a Company dropdown for existing companies or new company creation fields that the user fills out and that new company gets associated with this new job that is being created.
This is what my jobs/_form.html.erb
partial looks like:
<%= 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 %>
This is what my companies/_form.html.erb
looks like:
<%= 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 %>
How can I combine them into 1 form, or some other unified workflow within 1 view where it works seamlessly to the user?
Edit 1
Based on Jay-Ar's answer, this is what is happening now.
When I select New Company
in the Company Dropdown, it doesn't show the fields in the <fieldset>
. I believe that's the case because there is no value=0
in the select tags rendered in the HTML, as can be seen in the screenshot below.
Edit 2
After attempting the latest update from Jay-Ar, the JS still doesn't work and the form is no longer hidden.
This is what it looks like on first load, and always:
Ideally I would like for this form not to show up until they have chosen "New Company" from the dropdown.
This is what the HTML looks like now:
The JS does appear in the source, so I know it is being loaded in the asset pipeline correctly.
UPDATED & TESTED WORKING
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
You should get something like the following: