[rspec-users] defining context(s) dynamically

David Chelimsky dchelimsky at gmail.com
Fri Feb 16 08:51:20 EST 2007


On 2/16/07, Jerry West <jerry.west at ntlworld.com> wrote:
>
>  What is the value you are looking for by bypassing the convention
> here? I'm asking because perhaps there is a missing feature we can
> tease out of this.
>
>  I was trying to refactor out some shared (restful controller) specs, more
> as an experiment than anything else.
>
>  I really do like to be DRY so any essentially identical code (e.g. that
> generated by rspec_resource) is a candidate to be refactored into a
> parameter-ised function.  Actions like edit and destroy seem hardly to
> differ between controllers.  However, actions like new will tend to set
> defaults and create usually does some sanity checking, so I'm not sure how
> successful this refactoring would be in the long run.

Luke Redpath has some thoughts on this as well:

http://www.lukeredpath.co.uk/2007/2/2/refactoring-rest-searching-for-an-abstraction

Please do keep us posted on your own experimentation. As Spec::Rails
becomes less volatile, I'd like to see plugins emerge that work in
conjunction with it (as opposed to beefing up Spec::Rails itself).
Perhaps you could be among the first to contribute such to the
community.

>  Refactored code would be in a helper file  of course.  I put the helper
> file into my standard 'extensions' library plugin which is easy to share
> between rails apps.  It appears that spec uses the full directory path to
> identify the context - so even re-naming the helper file as
> 'lib/helper_controller_spec.rb' is not enough.  If I put that same file in
> the spec/controllers directory then the :context argument is not necessary.
> I could live with that if it ever disappeared.

As it turns out, I see that I actually DID document it in the
Spec::Rails::Runner::ContextFactory (in trunk), so I had already
considered making it official (sorry for not remembering that - there
is a lot going on right now and that aspect was low on my radar).

So I guess you can go ahead and count on it.

Cheers,
David

>
>  Bottom line: No big deal; if it goes it goes, if it stays it's very
> occasionally helpful.  My vote would be keep it unless it becomes awkward to
> maintain - extra flexibility can be very useful and if there's no
> opportunity cost there's no reason to bin it.
>
>  Best wishes,
>    Jerry
>
>
>
>  David Chelimsky wrote:
>  On 2/15/07, Jerry West <jerry.west at ntlworld.com> wrote:
>
>
>  Q. Why does code which defines a context work in the controller_spec file
> and not in a 'require'd helper file?
>
>  A. Because spec uses the filename to tell it what type of context
> (:controller, :model) it is creating.
>
>  Fix: use the (undocumented?) second parameter to #context(), :context_type
> => :controller.
>
>  Quite how this works, I do not know; the rdocs don't mention it and
> according to the source context doesn't take a second argument (except a
> block). My Ruby-fu isn't up to explaining it; if anyone else would like to
> do so that would be nice.
>
>  Hope this helps someone else save a half hour or so.
>
>  Rgds,
>  Jerry
>
>  Further details:
>
>  If I define a method which dynamically constructs a context in my
> controller_spec.rb file it works fine:
>
>  def restful_edit_specs(resource)
>  context "GET /#{resource}/:id;edit (:edit)" do
>  controller_name resource
>
>  resource = resource.to_s
>  sym = resource.singularize
>  klass = resource.classify
>
>  setup do
>  @mock = mock_model sym # based on
> http://metaclass.org/2006/12/22/making-a-mockery-of-activerecord
>  @model = Object.const_get(klass)
>  @model.should_receive(:find).with(@mock.id).and_return(@mock)
>  end
>
>  def do_get() get :edit, :id => @mock.id end
>
>  specify "should be successful" do
>  do_get
>  response.should_be_success
>  end
>  specify "should render edit.rhtml" do
>  do_get
>  controller.should_render :edit
>  end
>  specify "should find the #{klass} requested" do
>  @model.should_receive(:find).and_return(@mock)
>  do_get
>  end
>  specify "should assign the found #{klass} for the view" do
>  do_get
>  assigns(sym).should_equal @mock
>  end
>  end
>  end
>
>  restful_edit_specs(:assessments)
>
>  This all works fine when defined in the xx_controller_spec.rb file.
>
>  But if I move the exact same code to a helper file and require it, spec
> gets confused:
>
>  .../rspec-0.7.5.1/lib/spec/expectations/sugar.rb:13:in
> `call': undefined method `controller_name' for
> #<Spec::Runner::ContextEvalModule:0xb70496a8>
> (NoMethodError)
>  ... etc etc...
>
>  Clearly, there's some magic involved which means the context does not know
> what it's about (it was at this point in typing my original plea for help
> that I remembered seeing the :context_type parameter in the specs for the
> rspec_on_rails plugin itself).
>
>  Changing the context line to
>
>  context "GET /#{resource}/:id;edit (:edit)", :context_type =>
> :controller do
>
>  allows the specs to function as ex-spec-ted.
>
>  This is one of those "convention over configuration" things.
> Spec::Rails goes out of its way to provide different contexts for
> different types of specs, each providing specific facilities that are
> relevant to that kind of spec (model/view/controller/helper). Put your
> specs in the right directories and you get the right kind of context.
>
> The undocumented-second-parameter was added, as you note, to support
> our own specs of the plugin. The likelihood is that it will remain,
> but it is undocumented and subject to change without notice, so you do
> absorb some risk in using it.
>
> What is the value you are looking for by bypassing the convention
> here? I'm asking because perhaps there is a missing feature we can
> tease out of this.
>
> Cheers,
> David
>
>
>
>  _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>
>
>  _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>


More information about the rspec-users mailing list