Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the devise_mapping variable and how can I include it?

I'm trying to implement authentication with Devise in my Rails application (Rails 2.3.8, Devise 1.0.7, mongrel running on Windows Vista). But I'm getting the following error:

undefined local variable or method `devise_mapping' for #<ActionView::Base:0x6d63890>

This is when I use the auto-generated partial _devise_links.html.

<%- if controller_name != 'sessions' %>
  <%= link_to t('devise.sessions.link'), new_session_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.registerable? && controller_name != 'registrations' %>
  <%= link_to t('devise.registrations.link'), new_registration_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.recoverable? && controller_name != 'passwords' %>
  <%= link_to t('devise.passwords.link'), new_password_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %>
  <%= link_to t('devise.confirmations.link'), new_confirmation_path(resource_name) %><br />
<% end -%>

<%- if devise_mapping.lockable? && controller_name != 'unlocks' %>
  <%= link_to t('devise.unlocks.link'), new_unlock_path(resource_name) %><br />
<% end -%>

Any ideas on how to fix this? I'm assuming the devise_mapping variable is not getting included in my views, but what do I do about it?

like image 253
Johnny Avatar asked Dec 27 '10 19:12

Johnny


3 Answers

You can add helper methods to ApplicationHelper. Make sure to use the proper model name (in my case it's :user representing the User model).

def devise_mapping
  Devise.mappings[:user]
end

def resource_name
  devise_mapping.name
end

def resource_class
  devise_mapping.to
end

Update 1/28/2014

The master branch of Devise shows that devise_mapping is now stored in the request:

# Attempt to find the mapped route for devise based on request path
def devise_mapping
  @devise_mapping ||= request.env["devise.mapping"]
end

And resource_name is aliased as scope_name as well. See devise_controller.rb for more info.

like image 119
joelvh Avatar answered Nov 13 '22 02:11

joelvh


I realize this question is kind of old, but I think I figured out why you can't just render that partial. The partial you're trying to render is the partial for the links that show up below the sign_in/sign_up form.

If you'd like to add those links to your application, this page on the Devise Wiki will show you how to do it, and it involves creating your own partial(s).

EDIT (2019-04-01): Copying the information from the Devise wiki page here for persistence.

How To: Add sign_in, sign_out, and sign_up links to your layout template

First add sign_in/out links, so the appropriate one will show up depending on whether the user is _already_ signed in:
# views/devise/menu/_login_items.html.erb
<% if user_signed_in? %>
  <li>
  <%= link_to('Logout', destroy_user_session_path, method: :delete) %>        
  </li>
<% else %>
  <li>
  <%= link_to('Login', new_user_session_path)  %>  
  </li>
<% end %>
The method: :delete part is required if you use the default HTTP method. To change it, you will need to tell Devise this:
# config/initializers/devise.rb
  # The default HTTP method used to sign out a resource. Default is :delete.
  config.sign_out_via = :get
You can then omit method: :delete on all your sign_out links. Next come the sign_up links. Again, these can be substituted with something else useful if the user is already signed in:
# views/devise/menu/_registration_items.html.erb
<% if user_signed_in? %>
  <li>
  <%= link_to('Edit registration', edit_user_registration_path) %>
  </li>
<% else %>
  <li>
  <%= link_to('Register', new_user_registration_path)  %>
  </li>
<% end %>
Then use these templates in your layouts/application.html.erb, like this:
# layouts/application.html.erb
<ul class="hmenu">
  <%= render 'devise/menu/registration_items' %>
  <%= render 'devise/menu/login_items' %>
</ul>
<%= yield %>
Add some menu styling to the CSS (here for a horizontal menu):
ul.hmenu {
  list-style: none; 
  margin: 0 0 2em;
  padding: 0;
}

ul.hmenu li {
  display: inline;  
}
like image 6
philtr Avatar answered Nov 13 '22 00:11

philtr


Instead of using devise_mapping, you can use Devise.mappings[:user], given that the user class in question is User.

like image 3
Michael Hellein Avatar answered Nov 13 '22 02:11

Michael Hellein