# Help for beginners? Nested resources, Authentication, and Authorization

**URL:** <https://www.ruby-forum.com/t/help-for-beginners-nested-resources-authentication-and-authorization/182172>\
**Category:** Rails\
**Created:** [January 24, 2010, 1:33am UTC](https://www.ruby-forum.com/t/help-for-beginners-nested-resources-authentication-and-authorization/182172 "2010-01-24T01:33:27Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![acreadinglist](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/ccd318/32.png) [@acreadinglist](https://www.ruby-forum.com/u/acreadinglist)\
**Post date:** [January 24, 2010, 1:33am UTC](https://www.ruby-forum.com/t/help-for-beginners-nested-resources-authentication-and-authorization/182172/1 "2010-01-24T01:33:27Z")

</div>

In this thread, I hope to gather explanations from more experienced  
Rails users than I on how to approach the topics of nested resources,  
authentication, and authorization, areas that in my own experience as  
a Rails newcomer and based on my findings in newsgroups, forums, and  
articles, quickly present themselves as new users move beyond the  
tutorials to their first real apps.

In the tutorials, the user first learns how to create a model and its  
corresponding views and controllers. The user then learns how to make  
another model, and associate it with the first. Let me start  
attaching some names. We’ll have two models: Business and Customer.  
And we’ll say there’s a many-many association (the details of which  
don’t matter here and aren’t the goal of this post). Businesses have  
many customers; customers have many businesses.

I’ve chosen these two because, though there is a nesting relationship  
involved, the two are also distinct. In the [guides.rubyonrails.org](http://guides.rubyonrails.org)  
tutorials, the nesting relationship between Posts and Comments is  
different: whereas businesses and customers could very well stand  
alone in a commerce site, it seems much less likely that comments  
would be treated as a first class entity, since each comment is  
attached to a post. (I’m not trying argue about the nature of  
comments here, just trying to pick better models to exemplify the rest  
of the post).

A new user following the tutorials as they build their app would  
likely first build their Business MVC. They might then build their  
Customer MVC, with or without addressing the association. Without the  
association, the user will be able to go about creating businesses and  
customers, with the usual CRUD and RESTful routing. Adding the  
association brings in a new change: following the tutorial’s example,  
nesting customers under businesses should leverage the  
CustomersController. So, calls to /businesses/:business\_id/customers/  
should route to the CustomerController. The index method for the  
CustomerController changes in kind. @customers = Customer.all is  
replaced by something along the lines of @business = Business.find  
(:business\_id); @customers = @business.customers. With these changes,  
the user can no longer list all of the customers; he/she can only list  
all of a given business’s customers. We are now presented with the  
first question:

1. What is a/the good/best/recommended way to index a nestable but  
independent resource? In other words, what should be done to allow  
both the independent and nested views? Some possible solutions (for  
the case presented):

- Have conditional behavior reliant on whether the :business\_id  
parameter is present? (If so, get the nested customers, if not, get  
all)
- Have different controllers for nested access and unnested access?
- Have different routes and methods in the same controller for nested  
and unnested access?
- Some other method?

And at this point, the user encounters a new set of issues. The  
application will have users: businesses will access the app to see  
their customers, and court new ones; customers will want to view their  
favorite businesses, and look for others. [Let’s assume for the sake  
of this post that we’re not making a social app where everyone can see  
everyone else’s everything] - but businesses shouldn’t be able to see  
other businesses’ customers, and customers shouldn’t able to see other  
customers’ chosen businesses. If the user treads this path quickly,  
(and so that I can skip ahead a few steps), they’ll add an  
authentication plug-in and set up a bunch of callbacks, only to find  
themselves needing an administrator role: to 1) view all records as  
before, without any nesting, and to 2) act as if they were a given  
business or customer.

For the benefit of any other beginners that have made it this far,  
there are two separate pieces at play here: Authentication and  
Authorization. Authentication handles identifying the user: which  
business or which customer has logged in? Authorization handles  
access: what pages is the user allowed to see?

Around this point, my foundations falter, but I’ll try to proceed so  
as to reach what I believe are the next questions.

As part of setting up their authentication mechanism, the user most  
likely will have added something like a :require\_user callback (and  
may have put it in the ApplicationController) as a :before\_filter.  
This callback in general sets @current\_user; @current\_user is then  
used throughout the controller.

– I’d like to interject here with a particular question of my own  
that is well reflected by the model choices here. Since ‘users’ can  
refer to both businesses and customers here, how should authentication  
be handled? Should there be one user login/session that associates  
with a business or customer, and sets the appropriate  
@current\_business or @current\_customer in the require\_user callback?  
Or, should there be separate business login/sessions and customer  
login/sessions, with their own callbacks? –

Some new questions arise from the presence of @current\_user.  
Previously, the controller looked at the path parameters to determine,  
for example, which business’ customers to index.

1. How does routing and controller behavior change as a result of  
@current\_foo ?

- Should the RESTful, nested routing be maintained? e.g, /  
businesses/:business\_id/customers
- If so, how should :business\_id be handled?  
— Should it be ignored, so that regardless of :business\_id, we  
always use @current\_business ?  
— Should it redirect to the URL corresponding to  
@current\_business?
- If not, should /businesses/:business\_id/ be dropped entirely?  
— e.g, when logged in as a business, /customers presents  
@current\_business.customers , as managed by the CustomersController  
— the /businesses/:business\_id becomes implicit
  - and how should the logic be handled by the controller?

- Some other change?

1. How should the relationship between the :id from the path param and  
the :id from the session be enforced?

- Should there be additional callbacks to @require\_user, say  
@require\_specified\_user to compare the session and path param :ids?
- How should a mismatch be handled?  
— Should an unauthorized message be displayed?  
— Should the page be redirected to the closest relevant authorized  
page?/
- Some other method?

And that leads to what is, at least for me thus far, the last  
question. Having reached this point, the user will have created a  
Business model and a Customer model, and been able to view all of the  
associated records. Then the user will have made associations,  
allowing the indexing of all of a given business’ customers, and all  
of a customer’s business. Hopefully, by adddressing question 1, the  
user will still have a means of indexing all customers and all  
businesses. The user will have also added one or more callbacks (a  
monolithic :require\_user ?, :require\_business and :require\_customer  
that include the behavior of :require\_user ?, :require\_user that runs  
before :require\_business or :require\_customer ?), and a mechanism for  
enforcing the relationship between the session identification and the  
path parameters (from question 3). At this point, the user, who is  
now the Administrator, and neither a business nor a customer, wants to  
be able to view all the records, and also to be able to view the  
nested resources as seen by the ‘users.’

1. How should authorization for the administrator be handled?

- If the answer to question 1 was to create a separate controller,  
the answer is simple: a :require\_admin callback for that controller.
- If the answer to question 2 was to maintain RESTful nested routing,  
should the :require\_user (or equivalent callback) have an :unless  
=\> :as\_admin?  
— Thus falling back to the :business\_id path parameter to identify  
the top level resource.  
— How would this be handled if the controller was changed to  
always use, e.g, @current\_business, in the solution to question 2?
- Some method that works with the implicit logic from dropping the  
nested routing as in question 2?

Hopefully this post captures some of the most common questions that  
Rails newcomers have as they’re delving into their first real  
projects. With Rails’ emphasis on on DRY, and proper separation of  
controller, view, and model logic, I’m really interested to see what,  
if any, are the common, clean solutions. If there are other common  
questions that I’ve missed, please add them. To anyone who responds,  
thank you in advance. I’m going to append one more question that is  
less of a core issue, but has just caught my attention.

Thanks,  
Andrew

APPENDIX

Having set the nested associations as described above, there are now  
two ways to ‘show’ a customer: /customers/:id and /  
businesses/:business\_id/customers/:customer\_id . The administrator  
wants the businesses to see only a limited set of the customer’s  
profile in the nested view; the customer, of course, can see all of  
its own data.

A) What is a/the good/best/recommended solution to limit the business’  
view?

- Should there be two separate methods/views (e.g,  
CustomersController ‘show’ and ‘show\_business’)?
- Should the ‘show’ view have conditional logic that hides data based  
on the presence of @current\_business?
- Should the ‘show’ method render a different view for each case?
