On Monday 20 April 2009, David Chelimsky wrote:
> On Sun, Apr 19, 2009 at 5:41 PM, Michael Schuerig
<[email protected]> wrote:
> > On Sunday 19 April 2009, Zach Dennis wrote:
> >> On Sun, Apr 19, 2009 at 2:09 PM, Michael Schuerig
> >
> > <[email protected]> wrote:
> >> > On Sunday 19 April 2009, Zach Dennis wrote:
> >> >> On Sun, Apr 19, 2009 at 12:27 PM, Michael Schuerig
> >> >
> >> > <[email protected]> wrote:
> >> >> > In a Rails controller I set the scope on a model class in an
> >> >> > around filter. I have defined expectations on the model
> >> >> > classes, and ideally, I would add a further expectation for
> >> >> > the scope. Is this already possible in some way? How would I
> >> >> > go about adding support a scope expectation?
> >> >>
> >> >> How are you setting the said scope?
> >> >
> >> > In an around filter. However, I don't want to test the around
> >> > filter mechanism, it might as well be rack middleware instead.
> >>
> >> Sorry, I don't know what scope means to you in your app. Can you
> >> share your around_filter?
> >
> > Oops, sorry, I assumed the concept from ActiveRecord would be
> > familiar.
>
> It *is* familiar, but setting a model scope from the controller
> violates the widely-accepted guideline of skinny controllers and fat
> models. I'm guessing that's why Zach wasn't sure what you were
> talking about.
My controllers are anorexic. The functionality I'm trying to spec is
completely generic, I just mix it into the controller.
[snip]
> > Somewhere in QueryScope
> >
> > def query_scope(options = {}, &config_block)
> > model_class = extract_resource!(options)
> > builder = QueryScopeBuilder.new(config_block)
> > around_filter(options) do |controller, action|
> > req = builder.build_request_conditioner(controller.request)
> > controller.instance_variable_set(:@offset_limit,
> > req.offset_limit) model_class.send(:with_scope, :find =>
> > req.find_options, &action) end
> > end
>
> Unless I'm mistaken, it is code like this outside models that was the
> underlying motivation for adding named scopes to active record. The
> reason it is problematic is that it tends to result in a lot of
> duplication outside the models, and makes the controllers really hard
> to understand.
You are mistaken as there is no duplication at all. Among other things,
I have Rack middleware that maps request like (appropriately escaped)
/resource/?[?name='Dav*'][/name]
to a params hash like
{ :query => [{:attribute => 'name', :op => '=', :target => 'Dav*'}],
:order => [{:attribute => 'name'}] }
This, in turn, is interpreted by a RequestConditioner (bad name) which
in this case would, with the help of some mappings passed to it, return
rc.conditions == ["(firstname || ' ' || lastname) LIKE ?", 'Dav%']
rc.order == 'lastname, firstname'
As the last step, these pieces are used to define a scope around certain
controller actions. I could pass them explicitly to, say, #find, but
then I'd have to manually merge them with other conditions.
As to whether this functionality belongs in the model -- I am against
it. What I've described is an adapter layer that translates from one
representation of a query to another. It is not at all related to the
core logic enclosed in the models.
> Consider this alternative:
>
> describe PeopleController do
> describe "GET index" do
> it "assigns a list of all people filtered by virtual name
> attributes" do people = [mock_model(Person)]
> Person.stub!(:all).and_return(people)
> people.should_receive(:with_virtual_names).and_return(people)
> get :index
> end
> end
> end
>
> class PeopleController
> def index
> @people = PeopleController.all.with_virtual_names
> end
> end
That code is sclerotic. I'm building a RIA-client that only requests
JSON-formatted data from the server. Say, I add a date of birth column
to the people grid. Then the most I want to (and have to) do is ensure
that the requisite attribute is whitelisted for querying and contained
in the response data. (Yes, I have JSON "views" with accompanying
specs.)
Taking your non-generic approach, I'd have to repeatedly write and
explicitly test, very similar code. Consider adding date of birth for
sorting and filtering to your example. Then consider writing another
controller that does roughly the same for movies with titles and release
dates. You'll end up with repetitive code. Of course, you're going to
factor out the repetition -- and that's where I already am.
So, long story short, I still think I could make good use of a way to
define an expectation for a specific scope in effect during a #find.
Apart from my current case, this would make it possible to check on
dynamic scopes introduced in Rails 2.3.
Michael
--
Michael Schuerig
mailto:[email protected]
http://www.schuerig.de/michael/
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users