Chris Brooks
2004-Nov-24 07:43 UTC
Design question - integrating light-weight authorization
This might be more of an MVC design pattern question than a Rails-specific question, but I''m sure someone out there will be willing to help out. I have a number of pages that should render differently based on the authentication state of the user (much of the content can be viewed even if unauthenticated) and the role of the user. Usually this means that certain edit fields / buttons won''t be displayed if the user doesn''t have privs to do so. I''m struggling with the right way to represent this. Should I be using a single view for these pages with conditional hiding of certain portions of the rendered page? Or should I be using different views for each class of user, with appropriate render calls from the controller? Thanks, -- Chris Brooks http://www.chrisbrooks.org
David Heinemeier Hansson
2004-Nov-24 09:47 UTC
Re: Design question - integrating light-weight authorization
> I''m struggling with the right way to represent this. Should I be > using a single view for these pages with conditional hiding of certain > portions of the rendered page? Or should I be using different views > for each class of user, with appropriate render calls from the > controller?Are there more differences than similarities? That''s usually the question I ask when faced with this problem. Basecamp uses perhaps 80% conditional hiding and 20% different pages, so I think the majority of the time you can get away with just doing conditionals. -- David Heinemeier Hansson, http://www.basecamphq.com/ -- Web-based Project Management http://www.rubyonrails.org/ -- Web-application framework for Ruby http://macromates.com/ -- TextMate: Code and markup editor (OS X) http://www.loudthinking.com/ -- Broadcasting Brain
Gavin Sinclair
2004-Nov-24 10:32 UTC
Re: Design question - integrating light-weight authorization
[I accidentally replied to Chris, not the list. Probably nobody else is interested, but it might be good for the archives.] On Wednesday, November 24, 2004, 6:43:43 PM, Chris wrote:> This might be more of an MVC design pattern question than a > Rails-specific question, but I''m sure someone out there will be > willing to help out.> I have a number of pages that should render differently based on the > authentication state of the user (much of the content can be viewed > even if unauthenticated) and the role of the user. Usually this means > that certain edit fields / buttons won''t be displayed if the user > doesn''t have privs to do so.> I''m struggling with the right way to represent this. Should I be > using a single view for these pages with conditional hiding of certain > portions of the rendered page? Or should I be using different views > for each class of user, with appropriate render calls from the > controller?I''ve been experimenting with this, and have used two techniques so far: support from the helper module, and partial views. The first approach, support from the helper module, looks like this: # view (excerpt) <%= link(:edit_details) %> # helper (excerpt) def link(target) case target when :edit_details if logged_in? link_to :action => ''edit'' end when ... end end As far as the view is concerned, it _always_ shows the "edit details" link. But it uses the helper to create that link, and the helper is smart about whether the link should actually be shown. If logged_in? is false, the link() method returns nil, which appears as nothing in the final screen. The second approach, partial views, looks like this: # view (excerpt) <% if logged_in? %> <%= render_partial ''logged_in_table'', @data %> <% else %> <%= render_partial ''anonymous_table'', @data %> <% end %> The partials are files named _logged_in_table.rhtml and _anonymous_table.rhtml respectively. They both look like this: <div class="data_table"> <table> <% for d in @data %> ... <% end %> </table> </div> The ... in the partial above obviously contains different things for the logged in partial and the anonymous partial. The point is, they have the same structure, and both use the @data variable, which the containing view must pass on. You mentioned another approach, rendering different views from the controller, which I have thought about but not tried. Having tried the others, though, I think the this approach might actually suit my needs better. I don''t think there''s a single right answer. None of these techniques smell bad to me; it''s just a matter of working out how much needs to change with each state, and working out how much HTML code you can factor out. Just like you, my session state is not merely binary (logged in or not), even though my examples above don''t show that. When you introduce subtleties like user roles, you obviously need a subtle approach. Calling entirely different view files from the controller is certainly not subtle, so you should consider the other approaches. Please note that I''m a complete novice at this. It just happens I''ve been dealing with the same issue as you, so I hope this reply has been useful. Cheers, Gavin
Vincent Foley
2004-Nov-24 14:24 UTC
Re: Design question - integrating light-weight authorization
I don''t know about the others, but I think the way I would do it would be to have multiple views with a certain naming pattern. If you have users and admins in your system, your mainmenu.rhtml could instead be two files named admin_mainmenu.rhtml and user_mainmenu.rhtml and have something in your controller like: def index render_file "#{user.klass}_mainmenu.rhtml" end Something like that? Just a suggestion. Vincent. On Tue, 23 Nov 2004 23:43:43 -0800, Chris Brooks <brookscl-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> This might be more of an MVC design pattern question than a > Rails-specific question, but I''m sure someone out there will be > willing to help out. > > I have a number of pages that should render differently based on the > authentication state of the user (much of the content can be viewed > even if unauthenticated) and the role of the user. Usually this means > that certain edit fields / buttons won''t be displayed if the user > doesn''t have privs to do so. > > I''m struggling with the right way to represent this. Should I be > using a single view for these pages with conditional hiding of certain > portions of the rendered page? Or should I be using different views > for each class of user, with appropriate render calls from the > controller? > > Thanks, > > -- > Chris Brooks > http://www.chrisbrooks.org > _______________________________________________ > Rails mailing list > Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org > http://lists.rubyonrails.org/mailman/listinfo/rails >-- Vincent Foley-Bourgon Blog: http://www.livejournal.com/~gnuvince RSS: http://www.livejournal.com/~gnuvince/data/rss
Jarkko Laine
2004-Nov-24 14:54 UTC
Re: Design question - integrating light-weight authorization
On 24.11.2004, at 15:24, Vincent Foley wrote:> I don''t know about the others, but I think the way I would do it would > be to have multiple views with a certain naming pattern. If you have > users and admins in your system, your mainmenu.rhtml could instead be > two files named admin_mainmenu.rhtml and user_mainmenu.rhtml and have > something in your controller like: > > def index > render_file "#{user.klass}_mainmenu.rhtml" > endI disagree if you mean that you''d render totally different files depending on the user class. Why? DRY. If most parts of the pages are identical, you''d end up repeating the same html code in two places, potentially vulnerable to change-one-forget-the-other mistakes. If, however, you mean rendering a partial, I heartily agree. Then you''d have the differing parts (e.g. a navigation bar) in partials and you''d render the one needed. I feel that obeys a bit better the DRY principle. One possible way to tackle this problem is using layouts (described here: http://api.rubyonrails.org/classes/ActionController/Layout/ ClassMethods.html). Just my two cents. //jarkko -- Jarkko Laine http://jlaine.net _______________________________________________ Rails mailing list Rails-1W37MKcQCpIf0INCOvqR/iCwEArCW2h5@public.gmane.org http://lists.rubyonrails.org/mailman/listinfo/rails