I am doing Michael Hartl's Rails Tutorial Chapter 8. When I try to find a user by remember_token stored in the browser cookie it isn't working. The find_by method returns NIL. I have been trying to debug by looking at the remember token cookie stored on the browser and comparing it to the remember token stored in the user database. They don't match and I don't know why. Here is the code for the Session Helper.
module SessionsHelper
def sign_in(user)
remember_token = User.new_remember_token
cookies.permanent[:remember_token] = remember_token
user.update_attribute(:remember_token, User.encrypt(remember_token))
self.current_user = user
end
def signed_in?
!current_user.nil?
end
def current_user=(user)
#current_user = user
end
def current_user
#remember_token = User.encrypt(cookies[:remember_token])
remember_token = "71e45660fbaa69bad9fb55b912f80122a584f6af"
##current_user ||= User.find_by(remember_token: remember_token)
#current_user ||= User.find_by_remember_token(remember_token)
end
end
I have been tweaking it to try and figure out what is going on. To debug I commented out the normal lines and
set the remember token explicitly with the value I see in the database - then the app works. When I compare the value of the cookie stored in the browser to the value of remember token stored in the database they don't match.
Another thing I noticed is that I can't make a call to User_find_by. I get an error that says it doesn't recognize this method so I commented it out. I can however call to User.find_by_remember_token. It is possible that I have the wrong version of something installed?
I have tried resetting the database - but I can see it and it looks like it has all the right columns.
Here is the _header.html.erb code:
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="navbar-inner">
<div class="container">
<%= link_to "sample app", root_path, id: "logo" %>
<nav>
<ul class="nav pull-right">
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<% if signed_in? %>
<li><%= link_to "Users", '#' %></li>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", '#' %></li>
<li class="divider"></li>
<li>
<%= link_to "Sign out", signout_path, method: "delete" %>
</li>
</ul>
</li>
<% else %>
<li><%= link_to "Sign in", signin_path %></li>
<% end %>
</ul>
</nav>
</div>
</div>
</header>
It looks like the problem could be line 20 in your SessionsHelper. Should be:
#current_user ||= User.find_by(remember_token: remember_token)
Instead of passing the remember token into the User.find_by() method you're attempting to call a method find_by_remember_token, which doesn't exist.
first of all, User_find_by() isn't a method. it's User.find() or User.find_by_columnName() where columnname is the column in your database that you want to search.
also, you have to make sure your User model is defined correctly. i'm assuming you followed all the instructions til that point so you have the new_remember_token and encrypt methods and you have the create_remember_token private method? also make sure you have the before_create filter.
Related
In my apps navbar, I have the following code:
apps/views/layout/application.html.erb:
<ul class="nav navbar-nav navbar-right">
<% if user_signed_in? %>
<%if current_user.userinfo(&:info_complete) %>
<li><%= link_to "My profile", userinfo_path(current_user.userinfo.id) %></li>
<% elsif current_user.employer(&:info_complete)%>
<li><%= link_to "My profile", employer_path(current_user.employer.id) %></li>
<%else%>
<li><%= link_to "Complete Profile", application_studoremp_path %></li>
<%end%>
<li><%= link_to "Sign Out", destroy_user_session_path, method: :delete %></li>
<% else %>
<li><%= link_to "Log In", new_user_session_path %></li>
<li><%= link_to "Sign Up", new_user_registration_path %></li>
<% end %>
</ul>
When a user signs up, they will be directed to a page to choose if they want to continue as an employer or student, then they will be directed to a page to fill out userinfo if they choose student, or fill out the employer info if they choose employer. So between signing up and filling out one of the forms, the user will not have "userinfo.id" OR "employer.id". That's why I redirect them to "application_studoremp_path". But the app throws an error saying userinfo.id is not found. Obviously it's not found because it's not created yet, that's why there is an "else" part. Why is the logic not working? :info_complete is a function in both the userinfo model and the employer model checking if the information has been filled out. Everything works fine if the user is already existing (If the userinfo.id or employer.id already exists).
This is the error:
My userinfo.rb model:
class Userinfo < ActiveRecord::Base
belongs_to :user
def info_complete?
name? && email? && college? && gpa? && major?
end
It seems the issue is in your function info_complete that is not returning the right value.
I would suggest you try some test on it, and I guess that when you wanna reference a variable from your model, you should use ":", like this:
def info_complete
:name? && :age?
end
You are using method incorrectly.
The notation method(&:other) is a shorthand for method {|i| i.other}. What is happening here is prefix & is the same as calling to_proc method on object prefixed.
Now, userinfo is a getter, and you can pass it a block (of course) but it will be ignored, it is just a getter.
So all you actually do is check whether userinfo is not nil (or false). You also can tell, because (&:info_complete) does not even fire a NoMethodError (and it should, because there is no info_complete, there is info_complete?).
What you should do is to just use userinfo.info_complete? And if you are concerned user_info could be nil, do it with safe navigation operator: userinfo&.info_complete?
Further reading: Ampersand operator
Safe navigation operator
I am following the railstutorial and now got into the point where header will change dynamically depending on whether the user is logged in or not, using a conditional dropdown as shown below
<header class="navbar navbar-fixed-top navbar-inverse">
<div class="container">
<%= link_to "sample app", root_path, id: "logo" %>
<nav>
<ul class="nav navbar-nav navbar-right">
<li><%= link_to "Home", root_path %></li>
<li><%= link_to "Help", help_path %></li>
<% if logged_in? %>
<li><%= link_to "Users", '#' %></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
Account <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Profile", current_user %></li>
<li><%= link_to "Settings", '#' %></li>
<li class="divider"></li>
<li>
<%= link_to "Log out", logout_path, method: "delete" %>
</li>
</ul>
</li>
<% else %>
<li><%= link_to "Log in", login_path %></li>
<% end %>
</ul>
</nav>
And here is the logged_in? method defined in the helper
module SessionsHelper
# Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
# Returns the current logged-in user (if any).
def current_user
#current_user ||= User.find_by(id: session[:user_id])
end
# Returns true if the user is logged in, false otherwise.
def logged_in?
!current_user.nil?
end
end
For some reason this is not working, although I have copied the tutorial exactly. I am not sure if the line (if_logged_in?) is not being called or it is called but returns false. The else block gets executed by the way
I was wondering if there is anyway I can check if the method defined in the helper (logged_in?) is working and gets called correctly? Something like printing an output from the method itself?
A quick way to check whether that method's being called, and what's happening in it, is to throw a debug statement in there, like so:
def logged_in?
Rails.logger.debug("\n\n *** logged_in? #{current_user}")
!current_user.nil?
end
You load the page and then look at your development log and see if that line is there, and whether the user exists.
For more details about debugging, see http://guides.rubyonrails.org/debugging_rails_applications.html.
Hope that helps.
I have an application under development in Rails 3.2.13 with devise, omniauth and cancan. It all worked perfectly until I started to implement authorisation with cancan. It is even more interesting that cancan itself works like charm but generates an error in editing the user profile provided by devise. If cancan does that at all, I'm really not sure.
The error message is:
No route matches {:controller=>"devise/posts"}
I have a posts controller, but that's not linked to devise by any means. This is the strangest part in the story.
I successfully localised the spot that generates it but I can't figure out what the cause of the problem is and how to fix it. So I have a menu shown only to admins in my application.html.erb , this is the source:
<% if (user_signed_in? && (current_user.role?("sysadmin") || current_user.role?("postadmin") || current_user.role?("testadmin"))) %>
<ul class="nav navbar-nav nav-pills">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" style="color: crimson;">
<span class="glyphicon glyphicon-cog"></span> Administration <b class="caret"></b></a>
<ul class="dropdown-menu">
<% if (current_user.role?("sysadmin") || current_user.role?("postadmin")) then %>
<li><%= link_to 'Posts', :controller => :posts, :action => :index %></li>
<% end %>
<% if (current_user.role?("sysadmin") || current_user.role?("testadmin")) then %>
<li><%= link_to 'Itests', :controller => :itests, :action => :index %></li>
<% end %>
</ul>
</li>
</ul>
<% end %>
What's really interesting is that if I delete the <ul>...</ul> block so to leave nothing but a naked if ... end block, it works. Also, it works for users not having any of the three admin roles.
But in the <ul>...</ul> block there's nothing else but HTML, Bootstrap styling and some inline ruby links to some other controllers.
How does this breaks the "edit profile" feature of devise?
Check out this question: Rails No route matches {:controller=>"devise/products"}
Basically you're in device namespace and you have to use path helpers:
<%= link_to 'Posts', posts_path %>
or:
<%= link_to 'Posts', :controller => '/posts', :action => :index %>
I saw a few postings related to this topic, but the given solutions did not really clarify things for me ...
So, I am working on a rails (version 3.2.2) application that followed the setup from Michael Hartl's Ruby on Rails tutorial. The application has a signout link, which worked well until recently, when it started giving me the error 'No route matches [GET] "/signout"'.
These are the relevant pieces:
routes.rb
match '/signout' => 'sessions#destroy', :via => :delete
sessions_controller.rb
def destroy
sign_out
redirect_to root_path
end
sessions_helper.rb
def sign_out
current_user = nil
cookies.delete(:remember_token)
end
_header.html.erb
<li>
<%= link_to "Sign out", signout_path, :method => :delete %>
</li>
All it takes for the signout to start working again is the removal of ":via => :delete" from the routes file. Is this the right approach or is there a better one? Also, why did the link stop working without any rails update?
Thank you,
Alexandra
On request, I added the full code for the _header.html.erb:
full _header.html.erb
<!-- ***** Initialized: Listing 5.24 ***** -->
<!-- ***** Updated: Listing 8.24 ***** -->
<!-- ***** Updated: Listing 9.7 ***** -->
<!-- ***** Begin: Listing 9.28 ***** -->
<header>
<header class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<% if signed_in? %>
<%= link_to "project manager", about_path, id: "logo" %>
<% else %>
<%= link_to "project manager", root_path, id: "logo" %>
<% end %>
<nav>
<ul class="nav pull-right">
<!--li><%= link_to "Home", root_path %></li-->
<% if signed_in? %>
<% if Rails.env.development? %>
<li><%= link_to "Overview", overview_path %></li>
<% end %>
<% if Rails.env.development? %>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> Projects <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Status", projects_path %></li>
<li><%= link_to "Dev View", dev_projects_path %></li>
</ul>
</li>
<% else %>
<li><%= link_to "Projects", projects_path %></li>
<% end %>
<% if Rails.env.development? %>
<li><%= link_to "Teams", teams_path %></li>
<% end %>
<% if Rails.env.development? %>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> Tasks <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Status", tasks_status_path %></li>
<li><%= link_to "Tree", tasks_tree_path %></li>
<li><%= link_to "Dev View", dev_tasks_path %></li>
</ul>
</li>
<% else %>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> Tasks <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Status View", tasks_status_path %></li>
<li><%= link_to "Tree View", tasks_tree_path %></li>
</ul>
</li>
<% end %>
<% if Rails.env.development? %>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> Reports <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Project Progress", analysis_path %></li>
<li><%= link_to "Revision History", history_path %></li>
</ul>
</li>
<% else %>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> Reports <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><%= link_to "Revision History", history_path %></li>
</ul>
</li>
<% end %>
<% if Rails.env.development? %>
<li><%= link_to "Help", help_path %></li>
<% end %>
<li id="fat-menu" class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> Account <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<% if current_user.admin? %>
<li><%= link_to "Admin", users_path %></li>
<% end %>
<% if Rails.env.development? %>
<li><%= link_to "Profile", current_user %></li>
<% end %>
<li><%= link_to "Settings", edit_user_path(current_user) %></li>
<li class="divider"></li>
<li>
<%= link_to "Sign out", signout_path, :method => :delete %>
</li>
</ul>
</li>
<% else %>
<li><%= link_to "Sign in", signin_path %></li>
<% end %>
</ul>
</nav>
</div>
</div>
</header>
<!-- ***** End: Listing 9.28 ***** -->
This thread is a bit old, but I thought I'd share a solution anyway as more people might be having the same problem.
Here is some background information on how this works before we get into the actual troubleshooting:
Notice that the Sign Out link looks as follows:
<%= link_to "Sign out", signout_path, :method "delete" %>
If you look at the source code generated by this tag, you will see this:
Sign out
Notice the part that says data-method="delete". With straight HTML, this won't work. If you click the link, your browser will simply ignore the DELETE instruction and instead submit a GET request to your server (this is what you are currently seeing in your log). To get your browser to submit a DELETE request, you will need to use some JavaScript magic. This is where the jquery_ujs.js file comes in (you will most likely be able to see a link to this file by Viewing Source in your browser; it should be in the header, close to, or included within the application.js file). If you look inside the jquery_ujs.js file, towards the middle of the file, you will see the following code:
// Handles "data-method" on links such as:
// Delete
In other words, the code above makes sure that your browser actually does submit a DELETE request (we don't have to get into the details of the actual code here).
Given this background information, there are two possible reasons why you are getting your error.
You are simply missing the jquery_ujs.js file
Other JavaScript code you have written or included is interfering with the desired
behavior of the jquery_ujs.js file
To troubleshoot, do as follows:
For 1) Load the page that contains your Sign Out link and select View Source from your browser. Make sure that the file jquery_ujs.js is in the header (or concatenated with the rest of your JS files into the application.js file, depending on your application settings)
For 2) In application.js, remove the //=require_tree . directive. Reload your page, and click the Sign Out link. If the Sign Out link is hidden under a menu that only works with your JavaScript installed, then just put a duplicate of the Sign Out link somewhere else on your page where it is accessible without JavaScript. Now try clicking on the link - it should hopefully work. If you are no longer getting the routing error, you know that this was the cause for your problem. The easiest way to troubleshoot this is to add back the //=require_tree . directive, but then to remove all your JavaScript files except the application.js file from the folder where they reside, and then to add back each file one by one, while you try the Sign Out link, until it no longer works. This will allow you to identify the troublemaker JavaScript file. Once you have identified this file, try removing all code (upon which the link should work again) and then adding back pieces of the code until it no longer works - voila, you have now identified the root of the problem! Please feel free to report back what it was. My guess is that it could be either a straight up error, a return false; statement, or a stopPropagation(); statement.
Hopefully this will work! Good luck.
Since the answers that I received in September 2012 did not solve my problem, I just ended up removing ":via => :delete" from the routes file, which made the signout link work again.
After reading eriklinde's answer, I went back to my code to see if his answer would help. The jquery_ujs.js file was not missing. So, I started looking into the second possible reason that was suggested. Nevertheless, when I went to the routes.rb file and added "via: :delete" to have a line reading "match '/signout', :to => 'sessions#destroy', via: :delete", the signout functionality continued working without a problem. Since "via: :delete" is different than ":via => :delete", which I previously removed, maybe this was causing the problem?
I think the solution is here:
Rails 3 link_to (:method => :delete) not working
Are you missing <%= javascript_include_tag :all %> in your page? It should go in your layout file.
I had this same problem and fixed it by rearranging the order of the requirements in the application.js file. Mine were ordered as such:
//= require jquery_ujs
//= require jquery
//= require bootstrap
//= require_tree .
and are now ordered like this
//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .
I literally did nothing else.
try changing the _header.html.erb partial to
<li>
<%= link_to "Sign out", signout_path, :method "delete" %>
</li>
Actually you are probably missing the cross site forgery protection tags. Which would explain the inability to delete via the delete method. Not sure why it was working before.
Add this to your layout file in the head section
for haml
= csrf_meta_tags
for erb
<%= csrf_meta_tags %>
My guess would be that somehow you don't have jQuery UJS installed / active.
One of the key features listed here is "make non-GET requests from hyperlinks." Try adding gem 'jquery-rails' to your gemfile, run bundle install from the command line, restart your server, and see if it works!
This should be in your application.js file (with no lines above it that don't start with //!)
//= require jquery
//= require jquery_ujs
try this :
just add into you application.js
//= require jquery_ujs
First post here on SO. I am relatively new to Ruby on Rails and I have been reading through Michael Hartl's book, "Ruby on Rails Tutorial - Learn by Example". However, I have the following problems when running my application that I would be gracious to get solved.
1) When trying to run my application in 'production' mode, I have updated the file 'config/environments.rb' as follows:
# force Rails into production mode when
# you don't control web/app server and can't set it the proper way
ENV['RAILS_ENV'] ||= 'production'
However, when I run the application, I can still see the debugger facility present from the file 'app/views/layouts/application.html.erb'
<!-- Debug applies only to 'development' environment -->
<%= debug(params) if Rails.env.development? -%>
<!-- as determined by "if Rails.env.development?" -->
This leads me to believe that I am still running the application in development mode.
2) For those that have already asked questions about the signin_path problem, I still cannot see a solution that fixes it for me. I am able to sign up users, then automatically redirect them to their profile space. However, the navigation menu does not change accordingly:
<nav class="round">
<ul>
<li><%= link_to "Home", root_path -%></li>
<li><%= link_to "Support", support_path -%></li>
<% if signed_in? %>
<li><%= link_to "Users", users_path -%></li>
<li><%= link_to "Profile", current_user -%></li>
<li><%= link_to "Settings", edit_user_path(current_user) -%></li>
<li><%= link_to "Sign out", signout_path, :method => :delete -%></li>
<% else %>
<li><%= link_to "Sign in", signin_path -%></li>
<% end %>
Here is the code from the 'app/helpers/sessions_helper.rb' file:
def current_user # GET current_user
#current_user ||= user_from_remember_token
end
def signed_in?
!self.current_user.nil?
end
.
.
.
private
def user_from_remember_token
User.authenticate_with_salt(*remember_token)
end
def remember_token
cookies.signed[:remember_token] || [nil, nil]
end
Any help with this is most welcome. I am currently trying to host my application Heroku, but not getting the support I need unfortunately.
Cheers.
check the link if the question is related to heroku server . And if you want to run on local , rails s -p3001 -e production may work
It seems like your signed_in? helper returns not what you want. So at first debug what signed_in? returns like this:
<%= signed_in? %>
or you can raise error with signed_in? as a message.
Also it seems like you forget current_user setter method, which should be called after session is created. You need to have three methods like these:
def current_user
#current_user ||= User.find_by_id(session[:user_id])
end
def user_signed_in?
!!current_user
end
def current_user=(user)
#current_user = user
session[:user_id] = if #current_user ? current_user.id : nil
end
I recommend you to move this methods to ApplicationController as protected methods.
And one last advice:
!self.current_user.nil?
looks really bad. Try to avoid using bang!, this should work for you:
self.current_user