Rails 3 undefined method nil:NilClass has_many :through when attempting create-Collection of common programming errors
I am encountering a problem when trying to .build a new appointment. But first a look at my Model(s)
class Patient < ActiveRecord::Base
attr_accessible :address1, :address2, :city, :comment, :email, :first_name, :init_date, :init_time, :last_name, :mobile, :notes, :phone, :state, :zip
before_validation :upcase_patient
before_save { self.email.downcase! }
has_many :appointments, dependent: :destroy
has_many :procedures, through: :appointments
class Procedure < ActiveRecord::Base
attr_accessible :comment, :occurence, :procedure, :procedure_code, :procedure_price, :procedure_time, :visits
before_validation :uppercase_procedure
has_many :appointments
has_many :patients, through: :appointments
class Appointment < ActiveRecord::Base
attr_accessible :appointment_date, :appointment_notes, :appointment_time, :procedure_id
belongs_to :patient
belongs_to :procedure
class AppointmentsController < ApplicationController
include PatientsHelper
before_filter :signed_in_user
def create
@patient = current_patient
@appointment = @patient.appointments.build(params[:appointment])
if @appointment.save
flash[:success] = "Appointment scheduled!"
redirect_to patient_path(@patient)
else
render patient_path(@patient)
end
end
module PatientsHelper
def current_patient=(patient)
@current_patient = patient
end
def current_patient
@current_patient
end
def current_patient?(patient)
patient == current_patient
end
end
These items including “PatientsHelper” which helps define current_patient make up the associations. I have created the form successfullly within the patients_controller
class PatientsController < ApplicationController
before_filter :signed_in_user
before_filter :admin_user, only: [:destroy]
def show
@patient = Patient.find(params[:id])
@procedures = Procedure.all
@appointments = @patient.appointments.paginate(page: params[:page])
@appointment = @patient.appointments.build
end
I would like to use the patients resources to create new appointments. Here is where I am fouled up. I continue to receive via rspec the following error:
NoMethodError:
undefined method `appointments' for nil:NilClass
Where am I going wrong? Any help would be greatly appreciated. If clarification is required, I would like to:
a_ associate
Patient model -> has_many [:appointments, :procedures (through :appointments)]
Procedure model -> has_many [:appointments, :patients (through :appointments)]
Appointment model -> belongs_to [:patients, :procedures]
b_ create new :appointments through the patients controller rather than create a new controller specifically for appointments model
my mistake! here is the spec test.
require 'spec_helper'
describe "Appointment Pages" do
subject { page }
let(:user) { FactoryGirl.create(:user) }
let(:patient) { FactoryGirl.create(:patient) }
let(:procedure) { FactoryGirl.create(:procedure) }
before { sign_in user }
describe "appointment creation" do
before { visit patient_path(patient) }
describe "with invalid information" do
it "should not create an appointment" do
expect { click_button "Schedule procedure" }.not_to change(Appointment,
:count)
end
describe "error messages" do
before { click_button "Schedule procedure" }
it { should have_content('error') }
end
end
describe "with valid information" do
before do
procedure_id = procedure.id
patient_id = patient.id
fill_in 'appointment_appointment_date', with: "2013-04-04"
fill_in 'appointment_appointment_time', with: "12:45:00"
fill_in 'appointment_appointment_notes', with: "Test the notes"
end
it "should create a micropost" do
expect { click_button "Schedule procedure" }.to change(Appointment,
:count).by(1)
end
end
end
end
errors show up on the following
Failures:
1) Appointment Pages appointment creation with invalid information should not create an appointment
Failure/Error: expect { click_button "Schedule procedure" }.not_to change(Appointment,
NoMethodError:
undefined method `appointments' for nil:NilClass
# ./app/controllers/appointments_controller.rb:7:in `create'
# (eval):2:in `click_button'
# ./spec/requests/appointment_pages_spec.rb:17:in `block (5 levels) in '
# ./spec/requests/appointment_pages_spec.rb:17:in `block (4 levels) in '
2) Appointment Pages appointment creation with invalid information error messages
Failure/Error: before { click_button "Schedule procedure" }
NoMethodError:
undefined method `appointments' for nil:NilClass
# ./app/controllers/appointments_controller.rb:7:in `create'
# (eval):2:in `click_button'
# ./spec/requests/appointment_pages_spec.rb:22:in `block (5 levels) in '
3) Appointment Pages appointment creation with valid information should create a micropost
Failure/Error: expect { click_button "Schedule procedure" }.to change(Appointment,
NoMethodError:
undefined method `appointments' for nil:NilClass
# ./app/controllers/appointments_controller.rb:7:in `create'
# (eval):2:in `click_button'
# ./spec/requests/appointment_pages_spec.rb:36:in `block (5 levels) in '
# ./spec/requests/appointment_pages_spec.rb:36:in `block (4 levels) in '
Finished in 1.08 seconds
23 examples, 3 failures
Failed examples:
rspec ./spec/requests/appointment_pages_spec.rb:16 # Appointment Pages appointment creation with invalid information should not create an appointment
rspec ./spec/requests/appointment_pages_spec.rb:23 # Appointment Pages appointment creation with invalid information error messages
rspec ./spec/requests/appointment_pages_spec.rb:35 # Appointment Pages appointment creation with valid information should create a micropost
-
Not exactly what I was looking for but made this work-around.
Using the following was able to get this to save accordingly. Still cannot find out why I am unable to pull the Patient from the URL — example would be app.dev/patients/2 — where patient information is pulling id 2… but now I am able to save the Appointment using what I suspect is a rather crude method.
- In the form I added a hidden field which pulls the appropriate patient_id
- In Appointments controller, added to attr_accessible :patient_id
-
In appointments_controller
def create @appointment = Appointment.new(params[:appointment]) @current_patient = @appointment.patient_id if @appointment.save flash[:success] = "Appointment scheduled!" redirect_to patient_path(@current_patient) else render 'patients/show' end end
render 'patients/show'
remains broken but will leave that for another thread. Thank you all for your help and guidance.
Originally posted 2013-11-09 22:49:22.