Reputation: 2845
I have a complex has_many through relationship, where Users can apply to Jobs through Applications.
When creating each job, the admin chooses certain questions. During Applications#new, when the user is applying to a new job, I'd also like the user to answer the questions in order to apply.
To do this, I set up my models like so:
Job
has many users through application
has many questions
Users
has_many jobs through application
Application
belongs_to :user
belongs_to :job
has_many :answers
Question
belongs_to :job
has_one :answer
Answer
belongs_to :application
belongs_to :question
I now have an application controller.
Here's where I am stuck. How do I get the user to have the ability to answer questions on the Applications#new view?
This is what it looks like so far ->
Applications Controller
class ApplicationsController < ApplicationController
def new
@application = Application.new()
if params[:job_id] # Applications will only be built by clicking on a specific job, which transfers the id of that job
@application.job_id = params[:job_id]
@application.user_id = current_user.id
else
redirect_to root_url, :notice => "Something went wrong. Please contact us and mention this"
end
@job = Job.find(@application.job_id)
@user = current_user
end
end
The controller essentially sets it up so that when the users clicks submit, the application will has the user id and the job id, effectively making the connection
Applications#new view
<%= form @application do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<% @job.questions.each do |question| %>
<h4><%= question.content %></h4>
#What do I do here to allow the user to answer the question?
<% end %>
<%= f.submit "Submit the application", class: "button" %>
<% end %>
The Application Model
# == Schema Information
#
# Table name: applications
#
# id :integer not null, primary key
# user_id :integer
# job_id :integer
# created_at :datetime
# updated_at :datetime
#
class Application < ActiveRecord::Base
belongs_to :job
belongs_to :user
validates :job_id, presence: true
validates :user_id, presence: true
has_many :answers
accepts_nested_attributes_for :answers, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
Upvotes: 1
Views: 249
Reputation: 76774
Tough question....
This might not work (specifically the associations & the save params), but I spent some time thinking about it, so hopefully will point you in the right direction:
Structure
I would create your associations as follows:
#app/models/job.rb
Class Job < ActiveRecord::Base
has_many :applications
has_many :questions
end
#app/models/application.rb
Class Application < ActiveRecord::Base
belongs_to :user
belongs_to :job
has_many :questions, class_name: "Question"
has_many :answers, class_name: "ApplicationAnswer"
accepts_nested_attributes_for :answers
end
#app/models/question.rb
Class Question < ActiveRecord::Base
belongs_to :job
end
#app/models/application_answer.rb
Class ApplicationAnswer < ActiveRecord::Base
belongs_to :application
belongs_to :question
end
Schemas
jobs
id | name | info | created_at | updated_at
applications
id | user_id | job_id | created_at | updated_at
questions
id | job_id | created_at | updated_at
answers
id | application_id | question_id | answer_info | created_at | updated_at
Routes
I would create nested routes so that you can only create an application for a specific job:
#config/routes.rb
resources :jobs do
resources :applications
end
Controller
#app/controllers/applications_controller.rb
def new
@job = Job.find(params[:job_id])
@application = Application.new
@job.questions.count.times do { @application.answers.build } #-> gives you fields equivalent for number of questions per job
end
Form
Using accepts_nested_attributes_for
, you'll be able to create the forms as follows (upgraded using this idea):
#app/views/applications/new.html.erb
<%= form_for @application do |f| %>
<% @job.questions.each_with_index do |question| %>
<%= f.fields_for :answers, question do |question_field| %>
<%= question_field.label_for :answer, question.text %>
<%= question_field.text_field :answer %>
<%= question_field.hidden_field :question_id, question.id %>
<% end %>
<% end %>
<% end %>
Saving
#app/controllers/applications_controller.rb
def create
@application = Application.new(application_params)
@application.save
end
private
def application_params
params.require(:application).permit(:job_id, :user_id, answers_attributes:[:answer, :question_id]).merge(user_id: current_user.id)
end
I think your issue is as much a system structure problem as a functional issue. To understand the nested model submission process, you'd benefit from watching this Railscast
Upvotes: 1