Rails 1.2.6
The setup for this question takes a bit… and I suspect there may be
a better solution than what my direct question is.
I have an intranet app that’s stuffed with all kinds of special
permission rights for what users can see and do. For the most part
the UI itself prevents users from seeing controls they can’t use,
however, I still wrap entire controller methods with access rights
conditionals to prevent direct attacks via URL that by pass the UI.
Inside any given controller action a number of instance vars might
get declared for use in the view. However, if an access right denies
that user the ability to run that action, those vars don’t get
declared (they’re inside the conditional). I know what you’re
thinking… just hold on a sec…
Because of Rails’ “backwards” (from everything I have ever worked
with) way of processing a view template before the layout, I cannot
use conditional logic in the layout to preclude the processing of the
view file.
In order to show the user a message that what they tried to do is not
allowed and not showing the otherwise default view, I am currently
adding a flag to the flash to alter the layout.
So, the controller code is written along these lines:
def my_action
if @user.is_not_allowed?(:delete_comment)
flash.now[:action_not_allowed] = true
else
..... the normal code .....
@some_var = ....whatever....
end
end
Then my layout is written like so:
<% if flash[:action_not_allowed] -%>
<%= render(:partial => (@app_site_paths.panels + ‘not_allowed’)) %>
<% else -%>
<%= yield %>
<% end -%>
OK, so none of that prevents the view file from being processed, and
it will complain that @some_var doesn’t exist. To solve that, I ended
up doing a couple extra things in the controller. First, I aded a
line to my not_allowed conditional:
if @user.is_not_allowed?(:delete_comment)
flash.now[:action_not_allowed] = true
render :action => 'empty'
else
And then, you guessed it, I have an empty.rhtml file which has
nothing in it.
It works, but of course it’s kind of kludgy.
I was hoping render :nothing would have done the trick, but that (and
other options I have tried) prevents the entire layout from being
rendered. Hrmm. Not so good.
So, a) is there a better way to “skip” processing a specific view
file, or b) does anyone see a more elegant replacement for my
approach with using flash in the layout?
Of course, I could repeat the whole not_allowed conditional in the
view, but it would certainly be nicer to leave all that centralized
in the controller which my kludge achieves.
For now I’m content to use my “empty” approach in order to keep
moving, but it seems worth collecting ideas as this pattern is
foundation-level stuff for bajillions of tasks in many of my
applications.
– gw