[rspec-users] Best Practice for Controllers

Andrew Premdas apremdas at gmail.com
Fri Jan 21 18:31:22 EST 2011


On 18 January 2011 12:28, Phillip Koebbe <phillipkoebbe at gmail.com> wrote:

>
>
> > On 17 January 2011 20:43, David Chelimsky <dchelim... at gmail.com> wrote:
> >
> > > On Jan 17, 2011, at 10:16 AM, David Kahn wrote:
> >
> > > On Mon, Jan 17, 2011 at 9:48 AM, Ants Pants <antsmailingl... at gmail.com
> >wrote:
> >
> > >> Hello all,
> >
> > >> From what I've seen, this type of question doesn't really seem to get
> an
> > >> answer on this list as most of the replies relate to failures of
> RSpec. If
> > >> this is the case, where is the best place to go to get advice about
> best
> > >> practices etc?
> >
> > >> I have a question about best practice. In some of my controllers only
> an
> > >> admin user can perform edit, update, show etc. So I have a before
> filter in
> > >> those controllers; ApplicationController#authorise_is_admin
> >
> > >> The ApplicationController#authorise_is_admin throws an AccessDenied
> > >> exception and that is caught in ApplicationController#access_denied
> >
> > >> My question is, in the spec for the calling controller, let's say
> > >> ProductGroups, what should I spec?
> >
> > >> I have a context "user is admin" and that's easy to spec, but the
> context
> > >> "user is not admin" is where I'm stuck as no actions are performed in
> that
> > >> controller but I would just like to cover that failure somehow.
> >
> > >> Interesting question. I had the same dilemma and decided that it took
> too
> > > much effort and test code to test this at the controller level. What I
> do
> > > (and this may or may not work for you depending on your apps security
> > > needs), is to have an authorize method in the User model. It returns
> success
> > > or failure based on the controller and action passed. The model looks
> > > something like this:
> >
> > >   def authorize(controller_name, action_name)
> > >     if self.role
> > >       current_role = self.role.name
> > >     else
> > >       # guest user is empty user
> > >       current_role = 'guest'
> > >     end
> >
> > >     case controller_name
> > >     when 'activations'
> > >       if current_role != 'guest'
> > >         return set_autorize_failure_value("You are already logged in to
> the
> > > system. If you are activating a new user please log out first and try
> > > again.")
> > >       end
> > >       return authorize_success_message
> >
> > >     when 'feedback_supports'
> > >       if current_role == 'guest' || current_role == 'sysadmin'
> > >         return set_autorize_failure_value(LOGIN_NOTICE)
> > >       end
> > >       return authorize_success_message
> > > ...
> >
> > > end
> >
> > > Then in the spec it is real easy:
> >
> > >   describe "user authorization - guest role" do
> > >     it "is authorized to access certain pages only" do
> > >       user = User.new
> > >       user.authorize('activations', 'create')[:success].should == true
> > >       user.authorize('home', 'index')[:success].should == false
> >
> > >     ....
> >
> > >     end
> > >   end
> >
> > > This might not be everyone's cup of tea and I am sure I can refactor
> and
> > > make this less verbose, but what I like is having the 'dna' of all my
> access
> > > rights app wide in one place.
> >
> > > Definitely agree with the idea of keeping decisions in one place. I
> don't
> > > really like the idea of 'controllers' living inside a model, but change
> > > 'controller_name' to 'resource_collection_name' and that solves that
> > > problem.
> >
> > > I would still want to specify that the controller asks the user for
> > > authorization. WDYT?
> >
> On Jan 18, 2:30 am, Ants Pants <antsmailingl... at gmail.com> wrote:
> > When I read the David Kahn's response, I thought it strange to have
> > controller code in the model and was going to query him on it so I'm glad
> > that others think the same.
> >
> > As for Nick's response, I will look into it_behaves_like (I remember
> seeing
> > that in the book with a pizza example) It sounds good to me.
> >
> > Thanks for the replies.
> >
> > -ants
> >
>
> One thing you might consider is to separate your admin functionality
> from your regular user functionality. This isn't for everyone, but it
> might work out well for you. I used to do it the way you are currently
> doing it, and it was okay until I ran into some situations in which a
> regular user and an admin could edit a resource, but only the admin
> could edit certain attributes. The logic in my controller started
> putting on a bit of weight. My practice now is to separate appropriate
> functionality into namespaced controllers. All features available for
> users not logged in go in the default namespace, all features
> requiring the user to be logged in (but not administrative) go in the /
> user/ namespace, and all features that require administrative rights
> go into the /admin/ namespace. Then, in each namespace, I create a
> base controller that does the authorization/redirection and all other
> controllers in the namespace inherit from it. Something like:
>
> https://gist.github.com/784363
>
> Doing it this way does create seeming duplication in the views, but
> partials can be used very easily to deal with that. This method also
> more or less demands a menu structure that completely separates the
> functionality of each role, but in the projects that I've been working
> on, that has been a benefit. To have all of the role-based
> functionality separated in controllers and menus has provided clear
> lines that are easy to follow. In short, it has worked out really
> well. But, as always, your own mileage may vary.
>
> Peace.
> Phillip
>
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users
>

+1 for the many controllers for one model pattern, you can really simplify
controllers with this approach. Having a separate view hierarchy for each of
these controllers also makes for simpler views, with less logic. However you
have be very disciplined with your view partials, or the number of files can
get a bit confusing

All best

Andrew

-- 
------------------------
Andrew Premdas
blog.andrew.premdas.org
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20110121/d368f1c5/attachment.html>


More information about the rspec-users mailing list