David Chelimsky
2009-Apr-22 18:06 UTC
[rspec-users] [RSpec] Clarification on using shared_examples_for on a Rails Controller
On Wed, Apr 22, 2009 at 12:04 PM, Stephen H. Gerstacker <stephen at shortround.net> wrote:> I have a Rails controller that I am using ''before_filter'' on certain actions > to assign some extra variables.? I noticed the ''shared_examples_for'' method > and thought this would be a good way to test that the given actions are > loading what they need.? I wrote the following: > > shared_examples_for ''pages showing the yearly archive'' do > > ??? it ''should assign a list of yearly archives'' do > ????? Factory.create(:post, :published_at => Time.local(2009,02,01)) > ????? Factory.create(:post, :published_at => Time.local(2009,01,01)) > ????? Factory.create(:post, :published_at => Time.local(2008,01,01)) > ????? Factory.create(:post, :published_at => Time.local(2007,01,01)) > ????? Factory.create(:post, :published_at => Time.local(2001,01,01)) > > ????? get :index > > ????? assigns[:years].should == [ 2009, 2008, 2007, 2001 ] > ??? end > > ? end > > The problem is, it is specific to the ''index'' action.? I can''t use the > ''it_should_behave_like "pages showing the yearly archive"'' for other > actions. > > Am I just doing this wrong or is there a way to fix this?Shared examples don''t support parameterization, but macros do. Try something like this: module Macros def shows_yearly_archive_for(requests={}) requests.keys.each do |action| it "should assign a list of yearly archives on #{requests[action]} #{action}" do Factory.create(:post, :published_at => Time.local(2009,02,01)) Factory.create(:post, :published_at => Time.local(2009,01,01)) Factory.create(:post, :published_at => Time.local(2008,01,01)) Factory.create(:post, :published_at => Time.local(2007,01,01)) Factory.create(:post, :published_at => Time.local(2001,01,01)) send requests[action], action assigns[:years].should == [ 2009, 2008, 2007, 2001 ] end end end end describe SomeController do extend Macros shows_yearly_archive_for :index => :get end You can also extend with Macros from the config in spec_helper: Spec::Runner.configure {|c| c.extend(Macros, :type => :controller)} HTH, David ps - completely un-tested - that was off the top of my head> > - Stephen H. Gerstacker > > _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-users >
Mark Wilden
2009-Apr-22 18:07 UTC
[rspec-users] [RSpec] Clarification on using shared_examples_for on a Rails Controller
On Wed, Apr 22, 2009 at 10:04 AM, Stephen H. Gerstacker <stephen at shortround.net> wrote:> I have a Rails controller that I am using ''before_filter'' on certain actions > to assign some extra variables.? I noticed the ''shared_examples_for'' method > and thought this would be a good way to test that the given actions are > loading what they need.? I wrote the following: > > shared_examples_for ''pages showing the yearly archive'' do > > ??? it ''should assign a list of yearly archives'' do > ????? Factory.create(:post, :published_at => Time.local(2009,02,01)) > ????? Factory.create(:post, :published_at => Time.local(2009,01,01)) > ????? Factory.create(:post, :published_at => Time.local(2008,01,01)) > ????? Factory.create(:post, :published_at => Time.local(2007,01,01)) > ????? Factory.create(:post, :published_at => Time.local(2001,01,01)) > > ????? get :index > > ????? assigns[:years].should == [ 2009, 2008, 2007, 2001 ] > ??? end > > ? end > > The problem is, it is specific to the ''index'' action.? I can''t use the > ''it_should_behave_like "pages showing the yearly archive"'' for other > actions.Assign the action to an instance variable and set it to the desired value in a before(:all) in each of the sharers. In the shared example, do get @action. ///ark
r_j_h_box-sf at yahoo.com
2009-Apr-22 19:00 UTC
[rspec-users] [RSpec] Clarification on using shared_examples_for on a Rails Controller
----- Original Message ----> From: David Chelimsky <dchelimsky at gmail.com>> Shared examples don''t support parameterization, but macros do. Try > something like this: > > module Macros > def shows_yearly_archive_for(requests={})[...]> end > end > > describe SomeController do > extend Macros > shows_yearly_archive_for :index => :get > endNice. This must be newish (I see it in book beta4 - good!). I''d been using callbacks defined in the example group next to it_should_behave_like() to get any relevant parameters. A bit icky, I''ll admit. So I can just pass the details from the callback directly to the macro, when I port it/them. Sweet. I''ve been using a pattern for my shared example groups, similar to one I correlate (erroneously?) to a Ben Mabey post. The original pattern: do_foo(), where foo is get, post, whatever and the shared example probes the calling example group to find which one is relevant. My variation is do_action(), where the example group directly defines do_action() in whatever way is suitable to the example group (using instance variables set by before blocks, etc). This method could be defined usefully by either a Controller example group or a Model example group. I feel like even when using macros, I''d want to continue using my do_action() pattern. But maybe I have a hammer and so I''m looking for a nail. Is there another approach that gives different/better value when using macros? Thanks, Randy