Question

I'd like to test that a non signed in user can not access a page normally reserved for specific customers (one of their deal:only them can see the draft page the deal). It should redirect him to customer sign in page.

A customer has many deals

Models/customer.rb

class Customer < ActiveRecord::Base
  rolify

  has_many :customer_deals
  has_many :deals,                through: :customer_deals

models/deal.rb

class Deal < ActiveRecord::Base  
  belongs_to :admin_user,     :foreign_key => 'admin_user_id'
  belongs_to :partner,        :foreign_key => 'partner_id',       :counter_cache => true

  has_many   :customer_deals
  has_many   :customers,      through: :customer_deals      

  accepts_nested_attributes_for :customers #:reject_if     # needed for Active admin 

Models/customer_deal.rb

  belongs_to :customer,       :foreign_key => 'customer_id'
  belongs_to :deal,           :foreign_key => 'deal_id'

My tests below are failing with this error:

 1) Customer Interface pages As NON SIGNED-IN visitor does not have access to prepare deal page 
     Failure/Error: let(:deal) { FactoryGirl.create(:deal, :customer => customer) }
     NoMethodError:
       undefined method `customer=' for #<Deal:0x007f4f34b3a788>
     # ./spec/requests/client_interface_pages_spec.rb:15:in `block (2 levels) in <top (required)>'
     # ./spec/requests/client_interface_pages_spec.rb:50:in `block (4 levels) in <top (required)>'

Here is the rspec test page: client_interface_pages_spec.rb

require 'spec_helper'
require 'cancan/matchers'

describe "Customer pages" do

    subject { page }
    let(:user)          { FactoryGirl.create(:user) }
    let(:customer)      { FactoryGirl.create(:customer) }
    let(:prospect)      { FactoryGirl.create(:prospect) }
    let(:wrong_customer){ FactoryGirl.create(:customer, email: "wrong@example.com") }
    let(:non_admin)     { FactoryGirl.create(:customer) }
    let(:deal)          { FactoryGirl.create(:deal, :customer => customer) }



    context "As NON SIGNED-IN visitor" do 

    let(:customer) {FactoryGirl.create(:customer)}

      describe "does not have access to prepare deal page" do
        it "cannot access the deal preparation page" do
          get :draft_deal_page, :deal_id => deal.id, :customer_id => customer.id
          response.should redirect_to(new_customer_session_path)
          flash[:alert].should eql("You need to login or sign up before continuing.")
        end
      end    


  end

Routes

match '/prepare/deal_:id/draft-deal-page',
    to:   'deals#draft_deal_page',
    via:  'get',
    as:   :draft_deal_page 

I don't know if it's related but here are the main factories I use:

customer_deals.rb

FactoryGirl.define do
  factory :customer_deal do
    customer
    deal
  end
end

customers.rb

FactoryGirl.define do
  factory :customer do 
    sequence(:email) { |n| "person_#{n}@example.com"}   
    password "abcde"
    password_confirmation "abcde"
    # required if the Devise Confirmable module is used
     confirmed_at Time.now
     confirmation_token nil 
   partner_id 3 

    # give customer role to customers
    factory :customer_with_customer_status do
      after(:create) {|customer| customer.add_role(:customer)}
    end

  end

end

deals.rb

FactoryGirl.define do
  factory :deal do
     title "lorem ipsum"
    featured  true
    admin_user_id 1
    partner_id 3
    customer_id 3

  end
end  
Was it helpful?

Solution

A deal has_many :customers. Your deal factory is attempting to assign the "customer_id" attribute. There is no such attribute on deal because a deal has many customers. The customer_deal factory might be more appropriate to use here:

let(:customer) { FactoryGirl.create(:customer_deal).customer }

This would require you to get rid of the customer_id in your deal factory. In general, I think it's poor form to pick an arbitrary integer to stand in for a foreign key in your factories. If a factory requires a relationship, that relationship should just be created by the factory. If the relationship isn't required for object validity then I'd leave it off of the factory altogether, perhaps adding it behind a trait if it's something you need often.

I'd suggest reading the GETTING STARTED guide -- the whole thing, but particularly the parts about has_many associations, traits, and associations.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top