How do you tweak the arguments that get passed in rspec’s (v 2.6.1) post :create? Pointing me to rspec documentation that explains this command and how to use it would be fine with me. I’ve gone looking but can’t find anything that answers my question.
I’m having difficulty writing rspec to behave properly for my Customer :create action that receives parameters, both for the Customer, as well as a different User object. More precisely, I’m unable to get the values in the hash I pass in the rspec post :create to behave like the input that comes from my form.
Please note that my Customer and User objects are separate ActiveRecords, and each Customer :belongs_to a User.
Here’s my RSpec that’s not doing what I want it to:
describe CustomersController do
render_views
describe "for signed-in admins" do
before(:each) do
@customer_attr = Factory.attributes_for(:customer)
@admin = Factory(:admin)
test_sign_in(@admin.user)
end
describe "POST 'create'" do
describe "success" do
it "should create a customer" do
lambda do
post :create, :customer => @customer_attr # The problem is here
end.should change(Customer, :count).by(1)
end
end
end
end
end
Here’s the failure:
1) CustomersController for signed-in admins POST 'create' success should create a customer
Failure/Error: lambda do
count should have been changed by 1, but was changed by 0
# ./spec/controllers/customers_controller_spec.rb:323:in `block (5 levels) in <top (required)>'
The problem (as you’ll see below) is obviously that post :create, :customer => @customer_attr doesn’t include an argument that will end up in params[:user][:email], so the @user.save is failing because params[:user] is empty, but I’ve tried all kinds of ways to recompose the hash and pass it in that line but can’t get it to work.
Here’s the relevant controller code:
def create
@user = User.new(params[:user])
@user.user_type = 'customer'
@customer = Customer.new(params[:customer])
if @user.save
@user.customer = @customer
if @customer.save
# create stuff
redirect_to customer_path, :flash => { :success => "Customer created." }
else
# failure stuff
end
else
# more failure stuff
end
end
Here’s the relevant form code (which behaves how I want it to):
<%= form_for(@customer) do |f| %>
<%= fields_for :user do |user_form| %>
<%= user_form.label :email %>
<%= user_form.text_field :email %>
<% end %>
<%= f.label :first_name %>
<%= f.text_field :first_name %>
<%= f.label :last_name %>
<%= f.text_field :last_name %>
<%= f.submit "Create Customer Account" %>
<% end %>
Lastly, here’s my factories code:
factory :user do |f|
f.sequence :email do |n|
"person#{n}@example.com"
end
f.password "thepassword"
f.password_confirmation "thepassword"
end
factory :customer do |f|
f.first_name "First"
f.last_name "Last"
f.user
after_build { |customer| customer.user.user_type = 'customer' }
end
The solution I found was to compose my hash to make it look exactly how I wanted, then pass it directly, without the
:customer =>in front of it.Then in my controller I access items as e.g.
params[:customer][:first_name]orparams[:user][:email]And the rspec looks like: