Hello, I am having trouble to mock the chaining of named_scope in the controller, also I would like to use will_paginate. def index @things = Thing.allowed_for(@current_user).available.paginate :page => params[:page] end ?How to do it? Thanks Juanma Cervera -- Posted via http://www.ruby-forum.com/.
Maybe "utilization" is not correct an english word. I''m not sure. I would change the words in the subject Juanma Cervera -- Posted via http://www.ruby-forum.com/.
On Fri, Sep 12, 2008 at 5:20 AM, Juanma Cervera <lists at ruby-forum.com> wrote:> Hello, > I am having trouble to mock the chaining of named_scope in the > controller, also I would like to use will_paginate. > > def index > @things = Thing.allowed_for(@current_user).available.paginate :page => > params[:page] > end > > ?How to do it? > ThanksYou''re basically just going to have to chain some stubs. @available = stub("available things", :paginate => [:thing]) @allowed_for = stub("allowed things", :available => @available) Thing.stub!(:allowed_for).and_return @allowed_for I would probably wrap that chain up in a method though, that expresses what you want and makes it easier to stub class Thing def self.available_to(user) allowed_for(user).available end end This makes your test become @available = stub("available things", :paginate => [:thing]) Thing.stub!(:available_to).and_return @available and to mock it, you can do Thing.should_receive(:allowed_for).with(mock_user).and_return @available Pat
Very clear. Thank you very much Pat! -- Posted via http://www.ruby-forum.com/.
This trick to spec a named_scope method works very well. And it cleans up the chain mess in the controller. -- Posted via http://www.ruby-forum.com/.
On 4 Nov 2008, at 21:48, Fernando Perez wrote:> This trick to spec a named_scope method works very well. And it cleans > up the chain mess in the controller.Which trick is that? Sorry if this sounds a bit patronising, but it does help if you quote the relevant bits of a post you''re replying to, to give some context to your message. cheers, Matt
Here you go: It''s not easy to test for the following named_scopes: -- Thing.method1(@current_user).method2.method3 :page => params[:page] -- I tried: -- Thing.should_receive(:method1).. Thing.should_receive(:method2).. Thing.should_receive(:method3) -- But testing for these three method calls didn''t work. I have an error as "could not evaluate nil.method2". That''s because of the way Rails treats chained named_scopes, each method only exists in the context of its surrounding scopes. method1 doesn''t anything when followed by method2, it''s because rails dynamically creates a method that would be called something like method1_and_method2 if you know what I''m sayin''. Therefore a workaround is to define an instance method: -- class Thing def self.method1_and_method2(arg) method1(arg).method2 end end -- Then in the controller, you would call: Thing.method1_and_method2 Now you can spec that easily with: -- Thing.should_receive(:method1_and_method2).with(...) -- And it works. -- Posted via http://www.ruby-forum.com/.
Fernando Perez <lists at ruby-forum.com> writes:> Therefore a workaround is to define an instance method: > -- > class Thing > def self.method1_and_method2(arg) > method1(arg).method2 > end > endI''m inclined to call this an improvement rather than a workaround :) Pat
I dunno ... creating a bunch of joining methods seems to be an awfully disjoint way to deal with something that is, admittedly, designed to laugh in the face of the Law of Demeter. I''ve been handling chains through some heavy use of null_object stubs ... but, I''ve been doing that sort of manually. Could be rolled up, at least. I''m kind of spitballing something that might be somewhat less manual ... foo.stub_chains :method_1, :method_2 do |chain| end def stub_chains(*args) hades = stub("chain", :null_object => true) args.each do|chain| hades.stub!(chain).and_return(hades) self.stub!(chain).and_return(hades) end end This would more or less let named_scope be used like it''s intended in Rails, with one not-so-little exception -- I have to know what gets called last, so it can return a real value. For me, in practice, that''s been .paginate, so it''s not been a huge issue, but that''s a definite gotchya WDYT? On Tue, Nov 4, 2008 at 6:41 PM, Pat Maddox <pergesu at gmail.com> wrote:> Fernando Perez <lists at ruby-forum.com> writes: > > > Therefore a workaround is to define an instance method: > > -- > > class Thing > > def self.method1_and_method2(arg) > > method1(arg).method2 > > end > > end > > I''m inclined to call this an improvement rather than a workaround :) > > Pat > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >-- // anything worth taking seriously is worth making fun of // http://blog.devcaffeine.com/ -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20081104/e6d00868/attachment.html>
Right. Example passed a block, but stub_chains didn''t call it. Pretend there''s a yield(hades) in there somewhere. On Tue, Nov 4, 2008 at 10:26 PM, Chris Flipse <cflipse at gmail.com> wrote:> I dunno ... creating a bunch of joining methods seems to be an awfully > disjoint way to deal with something that is, admittedly, designed to laugh > in the face of the Law of Demeter. > > I''ve been handling chains through some heavy use of null_object stubs ... > but, I''ve been doing that sort of manually. Could be rolled up, at least. > > I''m kind of spitballing something that might be somewhat less manual ... > > foo.stub_chains :method_1, :method_2 do |chain| > end > > def stub_chains(*args) > hades = stub("chain", :null_object => true) > args.each do|chain| > hades.stub!(chain).and_return(hades) > self.stub!(chain).and_return(hades) > end > end > > This would more or less let named_scope be used like it''s intended in > Rails, with one not-so-little exception -- I have to know what gets called > last, so it can return a real value. For me, in practice, that''s been > .paginate, so it''s not been a huge issue, but that''s a definite gotchya > > > WDYT? > > > On Tue, Nov 4, 2008 at 6:41 PM, Pat Maddox <pergesu at gmail.com> wrote: > >> Fernando Perez <lists at ruby-forum.com> writes: >> >> > Therefore a workaround is to define an instance method: >> > -- >> > class Thing >> > def self.method1_and_method2(arg) >> > method1(arg).method2 >> > end >> > end >> >> I''m inclined to call this an improvement rather than a workaround :) >> >> Pat >> _______________________________________________ >> rspec-users mailing list >> rspec-users at rubyforge.org >> http://rubyforge.org/mailman/listinfo/rspec-users >> > > > > -- > // anything worth taking seriously is worth making fun of > // http://blog.devcaffeine.com/ >-- // anything worth taking seriously is worth making fun of // http://blog.devcaffeine.com/ -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20081104/eaea0261/attachment.html>
"Chris Flipse" <cflipse at gmail.com> writes:> I dunno ... creating a bunch of joining methods seems to be an awfully disjoint way to deal with something that is, admittedly, designed to > laugh in the face of the Law of Demeter. > > I''ve been handling chains through some heavy use of null_object stubs ... but, I''ve been doing that sort of manually. Could be rolled up, > at least. > > I''m kind of spitballing something that might be somewhat less manual ... > > foo.stub_chains :method_1, :method_2 do |chain| > end > > def stub_chains(*args) > hades = stub("chain", :null_object => true) > args.each do|chain| > hades.stub!(chain).and_return(hades) > self.stub!(chain).and_return(hades) > end > endYeah, that''s cool. In regards to Demeter, one of my former coworkers argued that if you don''t gain much by that encapsulation, you should default to following the ontological structure. Makes a lot of sense to me. Pat