ruby on rails session information grab - ruby-on-rails

When i run in my page this code :
<% user = User.find(session[:userid]) %>
i get the error :
line #1 raised:
Couldn't find User without an ID
although i have in my authentification in my sessions_controller this :
def create
if user = User.authenticate(params[:username],params[:password])
session[:user_id]= user.id
session[:language_id]= user.language_id
User.find(user.id).update_attributes(:last_login => Time.now)
redirect_to root_path , :notice => (I18n.t :"session.login_success")
else
flash.now[:alert] = (I18n.t :"session.error")
render :action => 'new'
end
end
and the session should contain the userid

In your log-in you set session[:user_id], and you try to find session[:userid] (note the spurious underscore). That's why.

Your controller is looking for params session[:user_id], but in your views it is session[:userid] so it will complain that session[:user_id] is nil.

Related

No route matches {:action=>"show", :controller=>"members", :id=>nil}

I set up twitter login system and got the error message above around the codes
redirect_to member_path(session[:user_id]), :notice => "#{auth["info"]["name"]}さんの#{auth["provider"]}アカウントと接続しました。"
in the def callback of the sessions_controller.rb. I wonder why this happened because it never happened when I set up facebook login with omniauth gem.Could you tell me why this occurred and how to solve this?
I checked some elements. A new user was created through twitter login. And I could get "session". But couldn't acquire session[:user_id].
☆member.rb
def self.create_with_omniauth(auth)
create! do |member|
member.provider = auth["provider"]
member.uid = auth["uid"]
member.mail = auth["mail"]
member.image = auth["info"]["image"]
if member.provider == "facebook"
member.name = auth["info"]["name"]
else
member.name = auth["info"]["nickname"]
end
end
end
☆sessions_controller
def callback
#omniauth.auth環境変数を取得
auth = request.env["omniauth.auth"]
#Userモデルを検索
member = Member.find_by_provider_and_uid(auth["provider"], auth["uid"])
if member
# 既存のユーザ情報があった場合ルートに遷移させます
session[:user_id] = member.id
redirect_to member_path(session[:user_id]), :notice => "ログインしました。"
else
# Userモデルに:providerと:uidが無い場合(外部認証していない)、保存してからルートへ遷移させる
Member.create_with_omniauth(auth)
redirect_to member_path(session[:user_id]), :notice => "#{auth["info"]["name"]}さんの#{auth["provider"]}アカウントと接続しました。"
end
end
Your problem is that you try to build a member route which requires id for member. Other words Rails should build routes like /members/:id where id MUST be a number. When you pass session[:id] (which is nil!) to the route helper member_path you get an error.
What to do?
1) (if you use a gem for authentication, for example devise) you can pass to the route helper current_user: memeber_path(current_user)
2) if you have own method which authenticate user you can set session[:user_id] youself.
I suppose that the problem is in else-block. So you can define session[user_id] after a new Member is created. I hope that method Member.create_with_omniauth(auth) return a new member - it means that you need take its id
if member
# 既存のユーザ情報があった場合ルートに遷移させます
session[:user_id] = member.id
redirect_to member_path(session[:user_id]), :notice => "ログインしました。"
else
# Userモデルに:providerと:uidが無い場合(外部認証していない)、保存してからルートへ遷移させる
session[:user_id] = Member.create_with_omniauth(auth).id # <--- UPDATED PART IS HERE
redirect_to member_path(session[:user_id]), :notice => "#{auth["info"]["name"]}さんの#{auth["provider"]}アカウントと接続しました。"
end
PS
And anyway you can avoid to render/redirect to this route if session[:user_id] is nil
redirect_to member_path(session[:user_id]) if session[:user_id]

Ruby on rails pathname considered uninitialized constant in controller

In my Ruby on Rails app, when a user's authentication succeeds, I want to send him/her to a specific home page based on the account they belong to.
I tried adding an 'if' clause in my Sessions controller as follows :
def create
if user = User.authenticate(params[:login], params[:password])
session[:user_id] = user.id
if user.account.name == "X"
redirect_to Xhome_path, :notice => "Logged in successfully"
else
redirect_to home_path, :notice => "Logged in successfully"
end
else
flash.now[:alert] = "Invalid login/password combination"
render :action => 'new'
end
end
Copying the already existing following line in routes.rb :
match '/home' => "users#home", :as => "home"
I added this one :
match '/Xhome' => "users#Xhome", :as => "Xhome"
This does not work and gives the following results :
if a user with user.account.name 'X' logs in, the browser displays the following error message :
NameError in SessionsController#create
uninitialized constant SessionsController::Xhome_path
however, typing the mydomain.com/Xhome URL once this user is authenticated works well and brings the expected Xhome view, which seems to prove that there is no problem on the routes side.
Do you know where this NameError issue can come from ? Why can't I use Xhome_path just as I did with home_path ?
Do a rake routes and check for the available route names and their corresponding path helpers. Check if the path name is actually Xhome_path. If no path name exist, then do
redirect_to '/Xhome', :notice => "Logged in successfully"

Rails - attribute is not saved

I have this code:
if request.post? and #user.save
#contact.user_id = #user.id
#contact.save
flash[:notice] = l(:e_user_saved)
redirect_to :action => 'list'
end
But when rails saves the contact, the user_id remains null.
When I debug I see that it assigns the value, but when it saves it saves null. Why???
contact.save probably failed. You're not checking the return value, so you don't know.
Check the contact.errors hash to see what went wrong.
You should probably have contact.save in an if block:
if #contact.save
flash[:notice] = l(:e_user_saved)
redirect_to :action => 'list'
else
# some error handling
# and redirect somewhere else
end

Template is missing in action

I wrote a "follow" method in UsersController
def start_following
#user = current_user
#user_to_follow = User.find(params[:id])
unless #user_to_follow == #user
#follow_link = #user.follow_link.create(:follow_you_id => #user_to_follow.id, :user_id => #user.id)
#user.save
flash[:start_following] = "You started following" + #user_to_follow.name
else
flash[:cant_follow] = "You cannot follow yourself"
end
end
Pretty simple. And In the view, I have
<%= link_to 'Follow', follow_user_path(#user) %>
In routes,
resources :users do
member do
get 'follow' => "users#start_following", :as => 'follow'
When I click on the link, it complains: Missing template users/start_following
So, how do I make it just stay on the same page after the action?
The view page that I want to stay on is Show view of the user is to be followed.
ex: users/{user_id}. Is simply redirecting not a solution? I thought adding redirect_to {somewhere} would get rid of the error, but it didn't.
I would redirect to the user in question. If you are using the standard resourceful routes then you can just do
redirect_to(#user_to_follow)
As an aside it's generally considered bad practice to have GET requests that make changes - people normally use put/patch/post/delete requests for those. You can fall afoul of browsers pre-fetching links without the user actually clicking on them.
try:
redirect_to :back, :notice => "successfully followed someone..."
Yes redirect_to solves your problem, I suspect you forgot to add it to both branches of the unless
The code would look like this:
def start_following
#user = current_user
#user_to_follow = User.find(params[:id])
unless #user_to_follow == #user
#follow_link = #user.follow_link.create(:follow_you_id => #user_to_follow.id, :user_id => #user.id)
#user.save
flash[:start_following] = "You started following" + #user_to_follow.name
else
flash[:cant_follow] = "You cannot follow yourself"
end
redirect_to #user_to_follow
end

How to avoid the error on nil object

Record id 116 doesn't exist so it should return nil to #conversation.
I tried to make it redirect when it gets nil, but it still shows the error when I access example.com/messages/show?id=116 .
The error is
undefined method `is_participant?' for nil:NilClass
I definitely see 'is_participant' method existing in
/usr/local/lib/ruby/gems/1.9.1/gems/mailboxer-0.7.0/app/models/conversation.rb
messages_controller.rb
def show
#conversation = Conversation.find_by_id(params[:id])
unless #conversation.is_participant?(current_user)
flash[:alert] = "You do not have permission to view that conversation."
redirect_to :controller => 'messages', :action => 'received'
end
#messages = Message.find_by_id(params[:id])
current_user.read(#conversation)
end
You need to check that #conversation is not nil before you call a method on it. Try
unless #conversation.present? && #conversation.is_participant?(current_user)
You can check for presence of a value or rescue for that error.
def show
#conversation = Conversation.find_by_id(params[:id])
redirect_to somewhere_path if #conversation.nil?
unless #conversation.is_participant?(current_user)
flash[:alert] = "You do not have permission to view that conversation."
redirect_to :controller => 'messages', :action => 'received'
end
#messages = Message.find_by_id(params[:id])
current_user.read(#conversation)
end
or the Rescue!
def show
#conversation = Conversation.find_by_id(params[:id])
unless #conversation.is_participant?(current_user)
flash[:alert] = "You do not have permission to view that conversation."
redirect_to :controller => 'messages', :action => 'received'
end
#messages = Message.find_by_id(params[:id])
current_user.read(#conversation)
rescue NoMethodError
redirect_to somewhere_path
end
Notice that the rescue way is not very friendly, since it can rescue other error and making you have a pain to debug some errors. For example if current_user has no method named read, it would throw and error that would be catch there and you wouldn't notice it came from there.
Christoph Petschnig answer is right, just wanted to mention there is a nice shorthand for
unless #conversation.present? && #conversation.is_participant?(current_user)
which is
unless #conversation.try(:is_participant? , current_user)
try will return nil is #conversation is nil which eventually evaluates to false in the if statement.

Resources