Nested Form complex has_many :through

跟風遠走 提交于 2019-12-13 17:23:24

问题


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

回答1:


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



来源:https://stackoverflow.com/questions/20813233/nested-form-complex-has-many-through

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!