Controller Spec & DataMapper Chaining

Hi there,

I’m fairly new to RSpec, and DataMapper and I’m trying to write a
controller
spec for an index action that will include DM query chaining.

Here is a very simplified version of the Controller#index I’m working on

def index
@widgets = Widget.all(:order => [ :name.asc ])
if params[:alpha]
@widgets = @widgets.by_alpha(params[:alpha])
elsif params[:beta]
@widgets = @widgets.by_beta(params[:beta])
end
end

I’m trying to write a spec for this and I’m struggling. It feels like
it’ll
be something uber simple but I’m just not getting it.

describe “GET ‘index’” do
it “should be successful” do
get :index
response.should be_success
end

it “assigns all widgets as @widgets” do
widgets = [Factory.stub(:widget), Factory.stub(:widget)]
Widget.stub(:all) { [widgets] }
get :index
assigns(:widgets).should == [widgets]
end

#…
end

Any assistance would be greatly appreciated.

Kind regards,

Sid

Would you post the results of your spec? I’d like to see what you’re
getting.

I’m not familiar with DataMapper, but from an Active Record standpoint,
the order clause does not look right. e.g. should be
Square.all.order(:name)

Try running the spec without the order clause in index (e.g. Widget.all)
just to see if that works to rule out the order clause. You might have
to do stub chain on Widget for all and then order.

Everything else seems fine at quick glance.

Brian

What problems are you running into?

It appears that you should stub out Widget.all before all examples,
unless
you really want to hit the database.

Ken

2011/3/18 Sid W. [email protected]

Thanks Ken, but when I said I was new to RSpec I didn’t mean I was THAT
new!
;o)

I think people aren’t grasping the DataMapper chaining that is at the
root
of my testing confusion. I managed to come up with a solution that I’ve
outlined here http://pastie.org/1690040

Basically, I mocked out a couple DataMapper::Collections and nested
them.
I’d love to hear if anyone would have tackled this issue differently.

Thanks for the replies guys.

My problem is writing a test for

@widgets = @widgets.by_alpha(params[:alpha])

DataMapper allows you to chain additional criteria on an existing query
and
doesnt execute that query until in is used in the view. So the above
statement gets baked into the previous default query @widgets =
Widget.all(:order => [ :name.asc ]).

I’d just like to write a test that confirms the controller is in fact
calling @widgets.by_alpha(params[:alpha]) when the params[:alpha] is
present.

Here is the code again so you don’t have to scroll to see it

def index
@widgets = Widget.all(:order => [ :name.asc ])
if params[:alpha]
@widgets = @widgets.by_alpha(params[:alpha])
elsif params[:beta]
@widgets = @widgets.by_beta(params[:beta])
end
end

Just to recap, this code is valid and works, I just don’t know how to
write
a test for it.

Cheers,

Sid

When calling get/post/etc, the second optional parameter is a hash
representing the “params” hash.

So, in order to test the conditional(s) in your controller, you should
write:
get :index, :alpha => true #test the first conditional

In another example, pass in :beta => true like this:
get :index, :beta => true

HTH,
Ken

2011/3/18 Sid W. [email protected]

Thats great advice and now that you’ve pointed it out it seems so
obvious.
Thanks Matt. See you at Cukeup!

Sid

On 19 Mar 2011, at 17:49, Sid W. wrote:

Thanks Ken, but when I said I was new to RSpec I didn’t mean I was THAT new! ;o)

I think people aren’t grasping the DataMapper chaining that is at the root of my
testing confusion. I managed to come up with a solution that I’ve outlined here
http://pastie.org/1690040

Basically, I mocked out a couple DataMapper::Collections and nested them. I’d
love to hear if anyone would have tackled this issue differently.

Yes, I would have listened to the tests here, and heard that the
interface to my model was awkward.

I would either override Widget#all, or create a new method on the Widget
that simply takes the params hash (or the three specific params new,
name and materials) and figures out what to fetch from the database and
returns it. You have data access concerns leaking out into your
controller, which is why the interface is awkward to mock.

@widgets = @widgets.by_alpha(params[:alpha])

rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users

cheers,
Matt

[email protected]
07974 430184