Devise User Profile link in Navbar - ruby-on-rails

I have the following code for the nav-bar in my application, using Devise for user authentication.
<ul class="nav pull-right">
<li class="">
<%= link_to root_path do %>
<i class="icon-home"></i> Home
<% end %>
</li>
<li class="">
<%= link_to current_user do %>
<i class="icon-book"></i> Portfolio
<% end %>
</li>
<li class="">
<%= link_to help_path do %>
<i class="icon-question-sign"></i> Help
<% end %>
</li>
<li class="">
<%= link_to(destroy_user_session_path, :method=>'delete') do %>
<i class="icon-signout"></i> Logout
<% end %>
</li>
</ul>
It works fine on the home page and the user profile page, but when I go to the other pages, such as the Projects or Help page( both of which have before_filter :authenticate_user! in their controllers ), it throws the following error
NoMethodError in Projects#index
undefined method `find_by_remember_token' for #<Class:0x3ec18d0>
It says that the offending code is this part:
<%= link_to current_user do %>
Which I use to link the user to his/her profile. Any ideas how to fix this error?
Update:
It seems like the problem solved itself after adding
#user = current_user
to the page's respective controllers.

Try to check if user signed in.
<%= link_to if_user_signed_in?, current_user %>

Related

Ruby on rails - user is nil after creating a session and redirecting home

I am building a rails app.
I am using devise to handle authentication
If the user is an admin, he or she should be able to see a link in the navbar that redirects to the whole list of profiles (for testing purposes)
<% if !user_signed_in? %>
<li class="nav-item">
<%= link_to "Sign up", new_user_registration_path, class: "nav-link" %>
</li>
<li class="nav-item">
<%= link_to "Log in", new_user_session_path, class: "nav-link" %>
</li>
<% else %>
<li class="nav-item">
<%= link_to "Log out", destroy_user_session_path, method: :delete, class: "nav-link" %>
</li>
<% if !#user.nil? && #user.admin? %>
<li class="nav-item">
<%= link_to "See all profiles", profiles_path, class: "nav-link" %>
</li>
<% end %>
<li class="nav-item">
<%= link_to "My profile", user_profile_path(current_user, current_user.user_profile), class: "nav-link" %>
</li>
<% end %>
However, said link only shows after going inside the my profile link. I did a raise in the UserProfiles controller to see what's going on and apparently the user is nil in the homepage even after logging in, hence the reason why the see all profiles link is not appearing
My guess is that I am missing an instance variable that provides the user id somewhere, (pages controller perhaps?) I don't have a users controller or user sessions controller yet. Basically, I don't understand why is the user nil after logging in and why is the log out link showing up without a user?
UserProfiles controller
class UserProfilesController < ApplicationController
before_action :set_user, only: [:index, :show]
def index
#user_profiles = UserProfile.all
end
def show
#user_profile = UserProfile.find(params[:id])
#user_profile.user = #user
end
private
def set_user
#user = current_user
end
end
Thanks for your help
You are not passing #user from the controller so cannot use in the view.
You should change your code to
<% if !#user_profile.user.nil? && #user_profile.user.admin? %>
<li class="nav-item">
<%= link_to "See all profiles", profiles_path, class: "nav-link" %>
</li>
<% end %>

<% if !current_page?(action: 'edit') %> error . No route matches {:action=>"edit", :controller=>"…"}

My _footer.html.erb is (simplified):
<footer class="footer">
<nav class="navbar navbar-default navbar-fixed-bottom navbar-inverse">
<% if logged_in? %>
<li class="btn btn-primary"> <%= link_to 'Add New Connection', new_year_path %></li>
<li class="btn btn-primary"> <%= link_to 'Add New Person', new_person_path %> </li>
<li class="btn btn-primary"> <%= link_to 'Add New Address/Location', new_location_path %> </li>
<% end %>
</nav>
</footer>
But I don't want the footer to show up while editing; too easy to click on one of these buttons instead of Cancel or Submit which is down the page and my footer is stuck to the bottom. views/layouts/application.html.erb has <%= render 'layouts/footer' %>
I suppose I could have my three edit.html.ergs not use the defaults above, but seems easier if I could add another condition on the _footer.html.erg. Or some other way. Maybe something about leaving page without submitting?
Based on #tsrandrei comment I tried wrapping the footer in <% if !current_page?(action: 'edit') %> blah-blah <% end %> but then get error No route matches {:action=>"edit", :controller=>"…"} with the controller name being whatever the page is relevant to.
<% if current_page?(action: 'edit') %>
<footer class="footer">
<nav class="navbar navbar-default navbar-fixed-bottom navbar-inverse">
<% if logged_in? %>
<li class="btn btn-primary"> <%= link_to 'Add New Connection', new_year_path %></li>
<li class="btn btn-primary"> <%= link_to 'Add New Person', new_person_path %> </li>
<li class="btn btn-primary"> <%= link_to 'Add New Address/Location', new_location_path %> </li>
<% end %>
</nav>
</footer>
<% end %>
See https://api.rubyonrails.org/classes/ActionView/Helpers/UrlHelper.html#method-i-current_page-3F
You will also have other methods for your views:
controller_path
controller_name
action_name
Also check Rails: How to determine controller/action in view

How do you use pundit for partial authorization

Consider the following block of ruby on rails code:
<% unless current_user %>
<%= card title: 'Things you can do', bodyless: true do %>
<ul class="list-group list-group-flush">
<li class="list-group-item" style="background: transparent"><i class="fa fa-key"></i> MEET OTHERS LIKE YOU</li>
<li class="list-group-item" style="background: transparent"><i class="fa fa-question-circle-o"></i> ASK A QUESTION</li>
<li class="list-group-item" style="background: transparent"><i class="fa fa-users"></i> SHARE YOUR JOURNEY</li>
</u>
<% end %>
<% end %>
The "card" is shown, but only to logged in users.
Can Pundit Authorization policies be used determine which divs/partials/cards are shown to the visitor on a website?
Yes you can, if you defined a policy and then want to show some div/partial just if that policy, then you can do it like this for example
<% if policy(#post).update? %>
<%= link_to "Edit post", edit_post_path(#post) %>
<% end %>

undefined method `each' for nil:NilClass spree app

I am getting the below error when I am trying to login to spree admin at localhost:3000/admin.
undefined method `each' for nil:NilClass
<li class="dropdown ">
<% max_level = Spree::Config[:max_level_in_taxons_menu] || 1 %>
<a class="dropdown-toggle" data-toggle="dropdown" href="#">Shop</a>
<ul class="dropdown-menu">
<% #taxonomies.each do |taxonomy| %>
<% cache [I18n.locale, taxonomy, max_level, #taxon] do %>
<% if taxonomy.name =='Categories' %>
<% taxons = taxonomy.root.children.map do |taxon| %>
<li class="dropdown ">
<%= link_to(taxon.name, seo_url(taxon), class: 'dropdown-toggle', 'data-toggle'=>"dropdown") %>
<ul class="dropdown-menu">
<li>Black</li>
<li>Green</li>
</ul>
</li>
<% end %>
<% end %>
<% end %>
<% end %>
</ul>
</li>
The above code is where it is giving me error. Which I have in header partial. It gives me proper homepage when I go to localhost:3000, but gives an error when I try to login to admin. The header which I want to have is coming properly. But unable to login to admin.
Please help

Hiding a link from anonymous users

I'm using only devise gem for the user authorisation.
<ul class="actions">
<li>
<%= link_to 'New Item', new_item_path, class: 'new' %>
</li>
</ul>
How can I hide the New Item link from anonymous users?
user_signed_in? is predefined method provided by devise to check if user logged in or not.
<ul class="actions">
<% if user_signed_in? %>
<li>
<%= link_to 'New Item', new_item_path, class: 'new' %>
</li>
<% end %>
</ul>

Resources