Problem setting variables in ApplicationController

I’m dynamically generating menu options based on the currently logged
in user: current_user.
My menus are setup on the applicatin.rhtml file. The current_user is
defined in the application controller. But, attempting to assign it a
value while in the application controller results in an ‘undefined
method’ error.

ApplicationController …

def current_user
@cu = ::User.find(session[:rbac_user_id]) || “not logged in”
end

++Application.rhtml ++
Admin menu
<% if current_user.has_role?(“Admin”) %>
menu one
menu two
<%end%>

Apparently the current_user is not created by the time the
application.rhtml is rendered.
I think it might have something to do with the special nature of the
ApplicationController. But, I don’t fully understand what is
happening here.

Is there a better way of building dynamic menus??


Best Regards,
-Larry
“Work, work, work…there is no satisfactory alternative.”
— E.Taft Benson

Larry K. wrote:

I’m dynamically generating menu options based on the currently logged
in user: current_user.
My menus are setup on the applicatin.rhtml file. The current_user is
defined in the application controller. But, attempting to assign it a
value while in the application controller results in an ‘undefined
method’ error.

ApplicationController …

def current_user
@cu = ::User.find(session[:rbac_user_id]) || “not logged in”
end

++Application.rhtml ++
Admin menu
<% if current_user.has_role?(“Admin”) %>
menu one
menu two
<%end%>

Apparently the current_user is not created by the time the
application.rhtml is rendered.
I think it might have something to do with the special nature of the
ApplicationController. But, I don’t fully understand what is
happening here.

Methods defined in application.rb are not available in views (including
the layout). If you want methods for use in views, define them in a
helper. But that probably isn’t what you want here.

Keep this:

def current_user
@cu = ::User.find(session[:rbac_user_id]) || “not logged in”
end

And add:

before_filter :current_user

at the top of application.rb. In the layout, reference
@cu.has_role(“Admin”)

Also, note that things will break when there is no user logged in. If
you set @cu to a String, @cu.has_role will cause an error. Try changing
current_user to:

def current_user
if @cu = ::User.find(session[:rbac_user_id])
return true
else
return false
end
end

That “return false” will cause processing of the request to end. You can
add a “redirect_to” before “return false” if you’d like to do sometning
more useful on failure.

-matthew

This should be

<% if @cu && @cu.has_role?(“Admin”) %>
menu one
menu two
<%end%>

That way it makes sure there is a user, then checks their role.

You need to use instance variables to get data to your views. You can’t
call a method in your controller from the view.
Call current_user in your function before the page is rendered.
I’m working on a role-based project right now also, so if you find a
better way I’d like to hear about it.

Jason

Jason N. wrote:

Call current_user in your function before the page is rendered.
I’m working on a role-based project right now also, so if you find a
better way I’d like to hear about it.

before_filters are your friend.

-matthew

Definitely, for whole pages that are role-based. But for conditionally
displaying parts of a menu, what’s the best route?
Putting an if directly in the view is what I’ve been doing, but it seems
that there should be a more elegant approach.

Jason

Jason N. wrote:

Definitely, for whole pages that are role-based. But for conditionally
displaying parts of a menu, what’s the best route?
Putting an if directly in the view is what I’ve been doing, but it seems
that there should be a more elegant approach.

You can still use the before_filter for generic (auth/noauth) pages.
Just have it always return true. I think you’ll need to check “if @cu
in the view. Can’t think of any way around that.

-matthew