user2570506
user2570506

Reputation: 45

Rails associations and passing another model :id as an argument

I have two associated models: Job and Candidate. The Candidate model is updated when a user applies to a job listing through the candidates 'new' view. Since I've associated Candidate with the Job model, I can't save any new instances of Candidate. I know that I have to pass job_id as a parameter so that any new instance of Candidate references a particular Job, but I just cant figure out what I'm doing wrong. Also, the Job model is associated with the Devise User model, but Candidate is not associated with the User model. Could that be the issue? Thanks in advance.

I've tried a ton of things in my candidates controller, but now I've put it back to how it was before I associated the Candidate model with Job model, so I can start over again as if I just ran the migration to AddJobToCandidate

candidates_controller.rb

class CandidatesController < ApplicationController
  def index
    @candidates = Candidate.all
  end

  def new
    @candidate = Candidate.new
    render layout: false
  end

  def single
    @candidate = Candidate.find(params[:id])
  end

  def create
    @candidate = Candidate.new(candidate_params)
    if @candidate.save
      redirect_to root_path
    else
      render "new"
    end
  end

  private 
  def candidate_params 
    params.require(:candidate)
          .permit(:first_name, :last_name, :email, :cover_letter, :ph, :job_id)
  end

end

views/candidates/new.html.erb

<h1>Work at <%= current_user.company %></h1>

<%= simple_form_for @candidate do |form| %>
  <%= form.input :first_name, label: "First Name" %>
  <%= form.input :last_name, label: "Last Name" %>
  <%= form.input :email, label: "Email" %>
  <%= form.input :cover_letter, label: "Cover Letter" %>
  <%= form.input :ph, label: "Phone Number" %>


  <%= form.button :submit %>
<% end %>

routes.rb

Rails.application.routes.draw do
  get 'candidates/index'
  get 'candidates/new/:id' => 'candidates#new', :as => 'apply'
  get 'candidates/single/:id' => 'candidates#single', :as => 'viewcandidate'
  get 'jobs/index'
  get 'jobs/new'
  get 'jobs/listing/:id' => 'jobs#listing', as: 'listing'
  get 'jobs/listings', :as => 'careerpage'
  get 'jobs/dashboard'
  get 'jobs/single/:id' => 'jobs#single', :as => 'viewjob'
  devise_for :users, controllers: { sessions: "users/sessions" }
  resources :candidates
  resources :jobs
  root 'jobs#dashboard'
end

views/jobs/listing.html.erb the only view that links to candidates/new.html/erb

<h1><%= @job.title %></h1>
<p><%= @job.description %></p>
<p><%= link_to "Apply", apply_path(@job.id) %></p>

Candidate/Job association migration

class AddJobToCandidate < ActiveRecord::Migration[5.2]
  def change
    add_reference :candidates, :job, foreign_key: true
  end
end

jobs_controller.rb (don't think this is necessary but I'll include anyway)

class JobsController < ApplicationController
   before_action :authenticate_user!

  def index
    @jobs = current_user.jobs.all
  end

  def dashboard

  end

  def new
    @job = Job.new
  end

  def listing
    @job = Job.find(params[:id])
    render layout: false
  end

  def listings
    @jobs = current_user.jobs.all
    render layout: false
  end

  def single
    @job = Job.find(params[:id])
    @candidates = Candidate.all
  end

  def create
    @job = current_user.jobs.new(job_params)
    if @job.save
      redirect_to jobs_index_path
    else
      render "new"
    end
  end

  private 
  def job_params 
    params.require(:job)
          .permit(:title, :description, :url, :user_id)
  end

end

No error is shown, but model is not updated.

One of the things I tried in candidate_controller #create action was:

def create
    @candidate = @job.candidates.create(candidate_params)
    if @candidate.save
      redirect_to root_path
    else
      render "new"
    end
  end

and the error I get is 'undefined method `candidates' for nil:NilClass'

Another thing I tried was adding this line in the #create action:

@job = Job.find(params[:id])

and the error I get is 'Couldn't find Job without an ID'

Upvotes: 0

Views: 861

Answers (1)

TomDunning
TomDunning

Reputation: 4877

When you arrive at candidate#new you’re just discarding the Job ID. You’re not making it part of the data submitted by the form to be picked up in the create controller.

Given you have completely abandoned RESTful routes, the quickest solution would be to add this to the form:

 <%= form.hidden_field :job_id, value: params[:id] %>

However, I highly recommend you look at RESTful routes and nested resources. You have a mess where the ID passed to Candidate#new is the ID of a different model. While you’re at it you may want to reconsider having a candidate belong to a job, what happens when a candidate is interested in multiple jobs? They create a new profile each time? In job sites one would normally have a Job, a Candidate (or User / Profile) and then a JobApplication, which joins the two.

Upvotes: 1

Related Questions