title: What to add to RSpec valid_attributes when it is validating related models
body: <p>I am new to RSpec and Cucumber BDD development, and it's a big leap up.</p>
  
  <p>Using rake generate scaffold model_name I've produced a ton of code that seems to make some sense, but that I'm not super confident with.</p>
  
  <p>I was doing ok with RSpec until I added some database relationships and model validations, and then it all blew up and I don't really know what the best-practice or cleanest way of fixing it would be.</p>
  
  <p>It's obvious my problem is that "valid attributes" needs to be defined with a foreign key linking to a valid Patient/Anaesthetist/Procedure/Surgeon, but I have no idea how I should write this in RSpec (maybe use FactoryGirl to generate a valid object of each model?)  The model RSpec code makes sense to me, but the controller code is out of my depth.</p>
  
  <p>Seems like it should be do-able in one line, or maybe four lines (one for each object), but that should be it.</p>
  
  <p><strong>The code</strong></p>
  
  <pre><code>#app/models/procedure.rb
  class Procedure &lt; ActiveRecord::Base
      belongs_to :patient
      belongs_to :surgeon
      belongs_to :anaesthetist
      belongs_to :hospital
  
      validates :patient_id, presence: true
      validates :surgeon_id, presence: true
      validates :anaesthetist_id, presence: true
      validates :hospital_id, presence: true
  end
  </code></pre>
  
  <hr>
  
  <pre><code>#spec/models/procedure_spec.rb
  require 'spec_helper'
  
  describe Procedure do
  
      it { should validate_presence_of(:patient_id) }
      it { should validate_presence_of(:surgeon_id) }
      it { should validate_presence_of(:anaesthetist_id) }
      it { should validate_presence_of(:hospital_id) }
  
  end
  </code></pre>
  
  <hr>
  
  <pre><code>#spec/controllers/procedures_controller_spec.rb
  describe ProceduresController do
  
    # This should return the minimal set of attributes required to create a valid
    # Procedure. As you add validations to Procedure, be sure to
    # adjust the attributes here as well.
    let(:valid_attributes) { { "description" =&gt; "MyText" } }
  
    # This should return the minimal set of values that should be in the session
    # in order to pass any filters (e.g. authentication) defined in
    # ProceduresController. Be sure to keep this updated too.
    let(:valid_session) { {} }
  
    describe "GET index" do
      it "assigns all procedures as @procedures" do
        procedure = Procedure.create! valid_attributes
        get :index, {}, valid_session
        assigns(:procedures).should eq([procedure])
      end
    end
  
  ....
  
  end
  </code></pre>
  
  <hr>
  
  <pre><code>#Terminal output, note failures 4 and 5, there's about 10 more errors after that with the exact same cause
  Failures:
  
    1) ProceduresController POST create with valid params redirects to the created procedure
       Failure/Error: response.should redirect_to(Procedure.last)
         Expected response to be a &lt;redirect&gt;, but was &lt;200&gt;
       # ./spec/controllers/procedures_controller_spec.rb:80:in `block (4 levels) in &lt;top (required)&gt;'
  
    2) ProceduresController POST create with valid params assigns a newly created procedure as @procedure
       Failure/Error: assigns(:procedure).should be_persisted
         expected persisted? to return true, got false
       # ./spec/controllers/procedures_controller_spec.rb:75:in `block (4 levels) in &lt;top (required)&gt;'
  
    3) ProceduresController POST create with valid params creates a new Procedure
       Failure/Error: expect {
         count should have been changed by 1, but was changed by 0
       # ./spec/controllers/procedures_controller_spec.rb:67:in `block (4 levels) in &lt;top (required)&gt;'
  
    4) ProceduresController PUT update with valid params redirects to the procedure
       Failure/Error: procedure = Procedure.create! valid_attributes
       ActiveRecord::RecordInvalid:
         Validation failed: Patient can't be blank, Surgeon can't be blank, Anaesthetist can't be blank, Hospital can't be blank
       # ./spec/controllers/procedures_controller_spec.rb:120:in `block (4 levels) in &lt;top (required)&gt;'
  
    5) ProceduresController PUT update with valid params assigns the requested procedure as @procedure
       Failure/Error: procedure = Procedure.create! valid_attributes
       ActiveRecord::RecordInvalid:
         Validation failed: Patient can't be blank, Surgeon can't be blank, Anaesthetist can't be blank, Hospital can't be blank
       # ./spec/controllers/procedures_controller_spec.rb:114:in `block (4 levels) in &lt;top (required)&gt;'
  
  etc.
  </code></pre>
  
  <hr>
  
  <p><strong>Fixing the problem</strong></p>
  
  <p>My poor attempt at fixing the problem to give an idea of what I want to do.  The obvious solution is to somehow include a link to a valid Patient/Anaesthetist/Surgeon/Hospital in the valid attributes. I just need to know the proper RSpec/FactoryGirl/Rails (?) syntax to do something like this:</p>
  
  <pre><code>describe ProceduresController do
  
    # This should return the minimal set of attributes required to create a valid
    # Procedure. As you add validations to Procedure, be sure to
    # adjust the attributes here as well.
    FactoryGirl.create(:patient)
    FactoryGirl.create(:surgeon)
    FactoryGirl.create(:anaesthetist)
    FactoryGirl.create(:hospital)
    let(:valid_attributes) { { "description" =&gt; "MyText", "patient_id" =&gt; :patientid, "surgeon_id" =&gt; :surgeon.id, "anaesthetist_id" =&gt; :anaesthetist.id, "hospital_id" =&gt; :hospital.id } }
  
    # This should return the minimal set of values that should be in the session
    # in order to pass any filters (e.g. authentication) defined in
    # ProceduresController. Be sure to keep this updated too.
    let(:valid_session) { {} }
  
    describe "GET index" do
      it "assigns all procedures as @procedures" do
        procedure = Procedure.create! valid_attributes
        get :index, {}, valid_session
        assigns(:procedures).should eq([procedure])
      end
    end
  
  ...
  
  end
  </code></pre>
  
  <p>Thanks.</p>