Controller spec - pass parameter to before_filter method

207 views
Skip to first unread message

Javix

unread,
Nov 21, 2012, 10:23:38 AM11/21/12
to rs...@googlegroups.com
How to pass a parameter needed in before_filter in the controller ?
So given a controller as follows:

class AccountsController < ApplicationController
  before_filter :signed_in_user
  before_filter :find_client, only: :create

  def create
    @client.accounts.create!
    flash[:success] = t(:created_success, model: Account.model_name.human)
    redirect_to @client
  end

private
    def find_client
      @client = Client.find(params[:account][:client_id])
    end

end

As you see, I pass a client_id to create an account as accounts resources are defined in the context of clients. There is no new view, the account number is generated by the Account model method.
Any idea?
Thanks



Javix

unread,
Nov 21, 2012, 11:04:34 AM11/21/12
to rs...@googlegroups.com
When defined the spec as follows:

require 'spec_helper'

describe AccountsController do

  let(:admin) { create(:admin) }
  let(:client) { create(:client) }

  before(:each) { sign_in admin }

  describe "POST create" do
    it "creates a new account" do
      account =  build(:account, client: client)
      expect{
        post :create, account: attributes_for(:account, client: client)
      }.to change(Account, :count).by(1)
    end

    it "redirects to the client #show page" do
      response.should redirect_to client
    end
  end
end

I got the below errors:

AccountsController
  POST create
    creates a new account (FAILED - 1)
    redirects to the client #show page (FAILED - 2)

Failures:

  1) AccountsController POST create creates a new account
     Failure/Error: post :create, account: attributes_for(:account, client: client)
     ActiveRecord::RecordNotFound:
       Couldn't find Client without an ID
     # C:in `find'
     # ./app/controllers/accounts_controller.rb:37:in `find_client'
     # ./spec/controllers/accounts_controller_spec.rb:14:in `block (4 levels) in <top (required)>'
     # ./spec/controllers/accounts_controller_spec.rb:13:in `block (3 levels) in <top (required)>'

  2) AccountsController POST create redirects to the client #show page
     Failure/Error: response.should redirect_to client
       Expected response to be a <:redirect>, but was <200>
     # ./spec/controllers/accounts_controller_spec.rb:19:in `block (3 levels) in <top (required)>'

Finished in 3.89 seconds
2 examples, 2 failures

Failed examples:

rspec ./spec/controllers/accounts_controller_spec.rb:11 # AccountsController POST create creates a new account
rspec ./spec/controllers/accounts_controller_spec.rb:18 # AccountsController POST create redirects to the client #show page

Any idea ? Thansk and regards

David Chelimsky

unread,
Nov 21, 2012, 11:12:43 AM11/21/12
to rs...@googlegroups.com
I'd start by investigating this error message. Try printing out params
from the find_client method and make sure it's got what you expect.

> # C:in `find'
> # ./app/controllers/accounts_controller.rb:37:in `find_client'
> # ./spec/controllers/accounts_controller_spec.rb:14:in `block (4
> levels) in <top (required)>'
> # ./spec/controllers/accounts_controller_spec.rb:13:in `block (3
> levels) in <top (required)>'
>
> 2) AccountsController POST create redirects to the client #show page
> Failure/Error: response.should redirect_to client
> Expected response to be a <:redirect>, but was <200>
> # ./spec/controllers/accounts_controller_spec.rb:19:in `block (3
> levels) in <top (required)>'
>
> Finished in 3.89 seconds
> 2 examples, 2 failures
>
> Failed examples:
>
> rspec ./spec/controllers/accounts_controller_spec.rb:11 # AccountsController
> POST create creates a new account
> rspec ./spec/controllers/accounts_controller_spec.rb:18 # AccountsController
> POST create redirects to the client #show page
>
> Any idea ? Thansk and regards
>
> --
> You received this message because you are subscribed to the Google Groups
> "rspec" group.
> To post to this group, send email to rs...@googlegroups.com.
> To unsubscribe from this group, send email to
> rspec+un...@googlegroups.com.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/rspec/-/lgSio-qEqhQJ.
>
> For more options, visit https://groups.google.com/groups/opt_out.
>
>

Javix

unread,
Nov 21, 2012, 11:20:00 AM11/21/12
to rs...@googlegroups.com
Here is the params:

AccountsController
  POST create
++++++ params: {"account"=>{}, "controller"=>"accounts", "action"=>"create"}

dchel...@gmail.com

unread,
Nov 21, 2012, 11:30:42 AM11/21/12
to rs...@googlegroups.com
On Wednesday, November 21, 2012 10:20:00 AM UTC-6, Javix wrote:
Here is the params:

AccountsController
  POST create
++++++ params: {"account"=>{}, "controller"=>"accounts", "action"=>"create"}

Do you understand what the problem is now?

Javix

unread,
Nov 21, 2012, 3:28:08 PM11/21/12
to rs...@googlegroups.com
I was aware that I should pass client_id needed in the before_filter call (correct me if I'm wrong), that's why I put it in the post title. More of that, find_client method should get it as follows:


def find_client
      @client = Client.find(params[:account][:client_id])
    end

and I can't figure out hot to pass it in the spec, I believed that building an account the way I did would solve it, but was wrong.
So really, I can't see how.

dchel...@gmail.com

unread,
Nov 21, 2012, 3:31:31 PM11/21/12
to rs...@googlegroups.com
This line in the spec is not doing what you think it's doing:

  post :create, account: attributes_for(:account, client: client)

What you want there is something like:

  post :create, account: {client_id: client.id}

HTH,
David

 

Javix

unread,
Nov 22, 2012, 3:15:00 AM11/22/12
to rs...@googlegroups.com
Yeah, it works as expected:


describe AccountsController do

  let(:admin) { create(:admin) }
  let(:client) { create(:client) }

  before(:each) { sign_in admin }

  describe "POST create" do
    it "creates a new account" do
      #account =  build(:account, client: client)
      expect{

        post :create, account: { client_id: client.id }
      }.to change(Account, :count).by(1)
    end

    it "redirects to the client #show page" do

      post :create, account: { client_id: client.id }
      response.should redirect_to client
    end
  end
end

I believed that

1) the use of FactoryGirl build:


account =  build(:account, client: client)

would solve the problem.

2) that passing client in the hash will solve the client_id problem (I did the same in models specs, for example):

let(:client) { create(:client) }
before { @account = build(:account, client: client) }

Thanks for your help, David.




Reply all
Reply to author
Forward
0 new messages