Q&A about REST, namespaced controllers, authentication and authorization

Ok, so... this is gonna be a long read. I'd obviously appreciate you read it all, but I'll understand if you just mark it as read without doing so.

First, let me clarify that I DID my previous research which helped me a lot, but I still have problems deciding which way to go. I'm trying to make informed decisions here.

Also, according to my previous research I'm not the only one with this kind of concerns and it's about time to summarize it all in one e- mail.

I'm having problems deciding on some "architectural design" aspects of my new application. So I'll enumerate the functionalities which I see as the core ones that should pave the way to start coding.

= Core (high level) requirements

* It's a sort of on-line magazine with articles, news, events calendar, polls, services and products directory, comments, full-text search capabilities and maybe some other feature.

* There should be an administration application which serves as the backend to the content maintainers. This administrators should be categorized with roles as (at least) Editor and Writer. Each role would have a set of permissions to manage content. This administrative interface should be simple, non-cluttered, uniform and completely separated from the frontend.

* The public site (frontend) should have a homepage summarizing the latest content of the entire site, banners, etc (typical homepage). Each kind of content should have it's own main page accessible from the main navigation as a section of the site (Home, Articles, News, etc... would be the main menu). This frontend site should have it's own set of registered users whose "special feature" would be to have access to the private content. So occasional visitors AND logged in registered users would use and see the same interface, but registered users would see public and VIP content.

I think that briefly describes what I need to implement.

So now I'll present to you some questions that I think should have strong, backed, opinionated answers BEFORE I start coding (which should be soon according to my deadlines). I'll include my own still doubtful answers/opinions so some rails' GURUs can correct me (so I and others can learn) or not (so I feel gooood about my choices).

= REST & resources vs. Namespaced controllers

REST and resources oriented WebApps are getting a lot of attention in Rails at least since DHH's Keynote last year (which I've seen and felt amazed). I've read MANY posts and articles, read the RESTful Rails Development PDF, some RPC->REST refactoring articles, AWDwR2 (by the way, the REST part lacks the attention it deserves and all the book is headed the traditional /:controller/:action way. Having that in mind, it's a damn good book). I even bought the Peepcode REST screencast which also helped a lot. I downloaded Beast forum as an example of a modern RESTful Rails app. Still... I can't find good examples on how to achieve some things "the RESTful way". And according to my research in rubyonrails-talk, some of this concerns have been raised many times by different people in the last 8 months and it appears to me that the answers haven't been uniform enough. I know we all have our own ways to resolve some problems and many depend on the nature of the application. But being Rails such a good opinionated, "educative" framework, I'd really like to hear Rails' GURUs (maybe core team?) opinions loud and clear. And I think it's not only me in the public...(but hey! you're doing a wonderful job and I'm not pressing you in any way :wink: ).

== Questions about REST:

- How should I attend the clear separation between the administrative and public sites regarding resources' controllers?

- Should I use the same [Articles|Events|News|etc...]Controller to attend both apps? This would mean that /articles and other resource- related routes should behave different according to who is calling it, but it also has to differentiate between administrative users (Editor, Writer) and visitor users (unidentified guest and logged in registered user). I've seen this approach recommended (Peepcode's screencast comes to mind) using before_filters but I think the reality I have to model is much more complicated than the examples. According to the sources I've studied, this could also bring some caching problems too because it practically nullifies the possibility of using page and action cache. So my currently doubtful decision would be not to "merge" back and frontend controllers... but it drives me to controller name's collisions because ArticlesController is a great name to use in both apps. Unless... I use namespaced controllers...

- Should I use namespaced controllers and views to differentiate the administrative and public sites? I initially thought this would be a "cleaner" approach. I read some [1] saying namespaced controllers are getting out of fashion... but then Jeremy Kemper almost defending them on the same thread. If I go this way, should my namespaced controllers be resource or traditional controllers? This is my current choice... But it feels like going away from REST. And I want my app to be cool :- D.

[1] http://groups.google.com/group/rubyonrails-talk/browse_thread/thread/53cb3bc83409f7e/fd16338b5443cc30?lnk=gst&q=dhh&rnum=6#fd16338b5443cc30

- Rails 1.2.2's singleton resource controller appears to me as a good candidate to attend tipical general pages like homepage, about, dashboard (HomepageController, AboutController, DashboardController) seeing them as single resources with just the #index action. Am I in the right direction here?

= Auth[entication|orization]

I was thinking of using acts_as_authenticated (or Restful_authentication) and Authorization plugins to leverage the authentication/authorization layer of my app. But... wait! I have 2 separate models for users. I'm planning to use User (basically: login, name, e-mail) for the administrative users which use the administration site differentiated by an associated Roles model, and Subscriptor (login, name, e-mail, phone, address, country, and a LOT of etceteras...) for the registered visitors to the frontend application. Each one of this [back|front]end applications should have it's own login screens, etc...

== Questions about Authentication/Authorization:

- Will I be able to achieve this kind of functionality using the named plugins? - Can you suggest a better more simple way to do this?

Ok. I think this summarizes the 2 most prominent problems I'm in right now.

I'd appreciate your comments/examples/links...

Very good that someone started a thread like this. I'm having exactly the same problems as you have and exactly the same questions that I'd like to get answered before I start my project. Let's hope that we get some replies.


Bump for a very good thread that asks some very practical questions. :slight_smile:

I think you are asking excellent questions. Here's an approach that I am investigating for caching:

Since neither an editable (form) page nor a simple display page alters the data, they should both be available via http GET. However, the scaffold_resource generator produces an architecture that uses a query string (;edit) to specify which page is wanted. The query string is ignored by page caching. So, when you GET "/documents/1", it caches the display page, and when you GET "/documents/1;edit", it gets the display page out of the cache instead of making a nice editable form with the data inserted.

I think it's more appropriate to treat alternative html formats as just that; formats. I might send a request like "/documents/ 1.html_edit" (You have to add that mime type to the environment.rb, like:

. . . Mime::Type.register "text/html", :html_edit . . . Now, that "works" as far as being recognized by page caching: everything gets cached and served from cache.You have to add "caches_page :index, :show"

to the controller. The corresponding "show" method looks like:

  # GET /documents/1   # GET /documents/1.xml   # GET /documents/1.html_edit   def show     @document = Document.find(params[:id])

    respond_to do |format|       format.html # show.rhtml       format.html_edit {render 'documents/edit'}       format.xml { render :xml => @document.to_xml }     end   end

However, expiring the cache isn't pretty: in my controller's "update" action, for instance, I added: . . .        #expires /public/documents.html        expire_page(:controller=>'documents')

       #expires /public/1.html (the show.rhtml result)         expire_page(:controller=>'documents', :action=>'',:id => @document)

       #expires /public/show/1.html_edit

expire_page(:controller=>'documents', :action=>'show', :id=>"#{@document.id}.html_edit") . . . to get everything to clean up properly. Ugly.

I think perhaps multiple controllers is a good idea. What did you end up trying?


Caching: Edgerails is supposed to fix it by appending named actions to the URL with a "/" instead of a ";", which should do the trick.