Reputation: 4062
I am rewriting one of my Rails applications in Rails 4 using Ruby 2. My original one used the 3.2 version of Michael Hartl's Ruby on Rails Tutorial. I am copying the 3.2 version of my application to my new Rails 4 version. It appears that current_user is not being set properly. Every route using current_user aborts with a missing id and locale even though the record is accessed properly and a User is logged in and the locale is set. On my landing page which does not include routes using current_user I can change the locale and the correct text and images display for the selected locale. Unfortunately the header partial for the main site includes an edit_user_path(current_user) reference which means I cannot display any pages on my website except the landing page and another section of the website not related to a user.
Here is an example when I am trying to display the show action. I get similar errors anytime I attempt to access a route which references current_user.
No route matches {:controller=>"users", :action=>"show", :locale=>#<User id: 3, first_name: "first_name", last_name: "last_name", username: "username", email: "[email protected]", password_digest: "$2a$10$y73jlk0hQYKLClmXQI5iHe/fqXO66hJD3muWjDg5ziCD...", city: "MyCity", state_id: 3521, country_id: 233, remember_token: "8cce0e523a879e179dd5b23df04acc8d1cf3108e", password_reset_token: "nU1FbWD2nuXx23jnOmOkAQ", password_reset_sent_at: "2013-10-20 22:36:44", bio: "Here is my bio info...", active_user: "3", age_group: "3", gender: "F", admin: true, visible: true, created_at: "2012-08-28 19:43:27", updated_at: "2013-10-21 22:36:43", state_province: "MyState", broadcaster: true, language_id: 1, admin_localize: false, sos_student: false, send_newsletter: false, special_newsletter: true, temp_broadcaster: false, media_creator_id: 46, bad_email: false, banned: false, notify_resp_me: true, saved_micropost_id: 1, saved_topic_id: 56, saved_discussion_id: 1, notify_reply_me: true, on_profile_page: false, notify_new_disc: true>, :id=>nil, :format=>nil} missing required keys: [:locale, :id]
It appears that current_user is nil. I think my remember_token logic may be the culprit. I have looked at sessions_helper.rb for the past few hours but cannot figure out what I have done wrong.
Here is my sessions_helper.rb code. Note: In my login(user) method I allow a User to decide if they want to permanently save their cookie or just use it for their session. The tutorial does a permanent cookie where the person has to log out for the cookie to be deleted.
def current_user
remember_token = User.encrypt(cookies[:remember_token])
@current_user ||= User.find_by(remember_token: remember_token)
end
def current_user?(user)
user == current_user
end
def login(user)
remember_token = User.new_token
if params[:remember_me]
cookies.permanent[:remember_token] = remember_token
else
cookies[:remember_token] = remember_token
end
user.update_attribute(:remember_token, User.encrypt(remember_token))
self.current_user = user
end
def logged_in?
!current_user.nil?
end
def logged_in_user
unless logged_in?
store_location
redirect_to login_path, notice: "#{t :must_login}"
end
end
def logout
self.current_user = nil
cookies.delete(:remember_token)
flash[:success] = "#{t :logout}"
end
def current_user=(user)
@current_user = user
end
def redirect_back_or(default)
redirect_to(session[:return_to] || default)
session.delete(:return_to)
end
def store_location
session[:return_to] = request.url if request.get?
end
Here is my sessions_controller.rb logic. Note: I allow people to log in using an email address or a username. The logic is based on the Tutorial. However I display another path instead of redirecting to @user. That difference does not change the end results.
def create
user = User.find_by_email(params[:session][:email_user])
if user && user.authenticate(params[:session][:password])
if user.active_user == "1"
flash[:error] = "#{t :flash_sessions_error1}"
else
flash[:success] = "#{t :flash_sessions_success}"
login user
end
redirect_back_or home_path
else
user = User.find_by_username(params[:session][:email_user])
if user && user.authenticate(params[:session][:password])
if user.active_user == "1"
flash[:error] = "#{t :flash_sessions_error1}"
else
flash[:success] = "#{t :flash_sessions_success}"
login user
end
redirect_back_or home_path
else
flash.now[:error] = "#{t :flash_sessions_error2}"
render "new"
end
end
end
Here is my code in user.rb.
before_create :create_remember_token
def User.encrypt(token)
Digest::SHA1.hexdigest(token.to_s)
end
def User.new_token
SecureRandom.urlsafe_base64
end
private
def create_remember_token
self.remember_token = User.encrypt(User.new_token)
end
Here is my show action in users_controller.rb.
def show
@user = User.find(params[:id])
@microposts = @user.microposts.order("created_at DESC").first(20)
@discussions = @user.discussions.order("created_at DESC").first(20)
end
Here is my rake routes output for all routes for users:
following_user GET /:locale/users/:id/following(.:format) users#following {:locale=>/en|es|fr|pt/}
followers_user GET /:locale/users/:id/followers(.:format) users#followers {:locale=>/en|es|fr|pt/}
users GET /:locale/users(.:format) users#index {:locale=>/en|es|fr|pt/}
POST /:locale/users(.:format) users#create {:locale=>/en|es|fr|pt/}
new_user GET /:locale/users/new(.:format) users#new {:locale=>/en|es|fr|pt/}
edit_user GET /:locale/users/:id/edit(.:format) users#edit {:locale=>/en|es|fr|pt/}
user GET /:locale/users/:id(.:format) users#show {:locale=>/en|es|fr|pt/}
PATCH /:locale/users/:id(.:format) users#update {:locale=>/en|es|fr|pt/}
PUT /:locale/users/:id(.:format) users#update {:locale=>/en|es|fr|pt/}
DELETE /:locale/users/:id(.:format) users#destroy {:locale=>/en|es|fr|pt/}
I will keep looking at this but for now I'm not seeing what I am doing wrong.
Any help would be appreciated.
Upvotes: 0
Views: 559
Reputation: 4062
I took another look at my log this morning. I confirmed again that the logic was getting the correct record. I thought that current_user was not set properly because the end of the error said that both the id and locale were missing. Since the correct record was in the log I decided to add locale: I18n.locale.to_s to one of my paths like this.
edit_user_path(current_user, locale: I18n.locale.to_s)
After adding the locale to by routes the logic worked. Another thing was related to a default for default_url_options that worked in Rails 3 that does not work in Rails 4.
Rails.application.routes.default_url_options[:locale]= I18n.locale
The I18n code worked as I had it coded in Rails 3. I found that with the links where I did not add the locale clause also worked. Hope this will help other people.
Upvotes: 1