railstutorial.org NoMethodError in SessionsController#create - ruby-on-rails-3

undefined method `current_user=' for #<SessionsController:0x1044926b8>
Rails.root: /Users/Bulow/ruby/sample_app
Application Trace | Framework Trace | Full Trace
app/helpers/sessions_helper.rb:4:in `sign_in'
app/controllers/sessions_controller.rb:20:in `create'
Request
Parameters:
{"commit"=>"Sign in",
"session"=>{"password"=>"[FILTERED]",
"email"=>"kennyvonbulow#gmail.com"},
"authenticity_token"=>"/fWZncGEWuhQLIYMxRPXBcBJ37vzLoVrIz1QHU28u6w=",
"utf8"=>"✓"}
Show session dump
Show env dump
Response
Headers:
None
unable to log in simply - and i have no clue how to correct it. been all over the guide back and forth and can't seem to find the error that's causeing this

The online tutorial has the following definitions in sessions_helper.rb
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
self.current_user = user
end
.
.
.
def sign_out
cookies.delete(:remember_token)
self.current_user = nil
end
I changed them to the following and was able to login/logout without any errors.
def sign_in(user)
cookies.permanent.signed[:remember_token] = [user.id, user.salt]
#current_user = user
end
.
.
.
def sign_out
cookies.delete(:remember_token)
#current_user = nil
end
Also, to confirm it's you that's logged in, change the URL localhost:3000/users/(your user ID) to another user ID. It'll show that users info. Click on the profile link at the top and it'll go back to your profile. The app is set up so that this link will got to the logged in user's profile.
Where I found the solution.
http://getsatisfaction.com/railstutorial/topics/undefined_method_current_user_for_sessionscontroller

Related

Sign in redirects to home page instead of staying on same page

I installed devise and it is working properly but the sign in redirect. When user signs in from any page of app, Devise redirects user to home instead of redirecting on same page. I tried implementing How_to solutions of devise but no help.
I wrote in application_controller:
def after_sign_in_path_for(resource)
current_user_path
end
But it gives error:
undefined local variable or method `current_user_path' for #<Devise::SessionsController:0xaeacc34>
When i write:
def after_sign_in_path_for(resource)
current_user_path
end
It gives :
undefined method `user_url'
Whats the solution for this problem? Can any body help in this?
You can use request.referer
def after_sign_in_path_for(resource_or_scope)
request.referer
end
You need to redirect to somewhere else in which scenerio(error or success)? Usually after_sign_in_path_for used after user logged in successfully. SO:
if you haven't override devise default functionality then use below code for navigate control to specific custom page. current_user is also accessible in this action.
def after_sign_in_path_for(resource)
scope = Devise::Mapping.find_scope!(resource)
scope_path = :"#{scope}_root_path"
respond_to?(scope_path, true) ? send(scope_path) : root_url
end
Update:
Another example is as follows:
def after_sign_in_path_for(resource_or_scope)
current_user.admin? ? dashboard_admin_home_index_path : current_user.sign_in_count >= 1 ? "/home/dashboard" : "/#{current_user.role}/dashboard"
end

Getting controller name from a request.referer in Rails

I know I can use request.referrer to get the full referrer URL in Rails, but is there a way to just get the controller name from the URL?
I want to see if the URL of http://myurl.com/profiles/2 includes "profiles"
I know I can use a regex to do it but I wondered if there was a better way.
Keep in mind that request.referrer gives you the url of the request before the current one. That said, here is how you can convert request.referrer to controller/actionn information:
Rails.application.routes.recognize_path(request.referrer)
it should give you something like
{:subdomain => "", :controller => "x", :action => "y"}
Here is my try which works with Rails 3 & 4. This code extracts one parameter on logout and redirects user to customized login page otherwise it redirects to general login page.
You can easily extract :controller this way. Controller part:
def logout
auth_logout_user
path = login_path
begin
refroute = Rails.application.routes.recognize_path(request.referer)
path = subscriber_path(refroute[:sub_id]) if refroute && refroute[:sub_id]
rescue ActionController::RoutingError
#ignore
end
redirect_to path
end
And tests are important as well:
test "logout to subscriber entry page" do
session[:uid] = users(:user1).id
#request.env['HTTP_REFERER'] = "http://host/s/client1/p/xyzabc"
get :logout
assert_redirected_to subscriber_path('client1')
end
test "logout other referer" do
session[:uid] = users(:user1).id
#request.env['HTTP_REFERER'] = "http://anyhost/path/other"
get :logout
assert_redirected_to login_path
end
test "logout with bad referer" do
session[:uid] = users(:user1).id
#request.env['HTTP_REFERER'] = "badhost/path/other"
get :logout
assert_redirected_to login_path
end
Inside the controller, you have the method controller_name which returns you only the name. In your case, it would return "profiles".
You may also use params[:controller] which returns the same string.

Rails Sorcery Bug? Creates Duplicate User Accounts

The example sorcery code shown on github appears to me to create duplicate accounts if it is extended to allow for multiple sign in methods (which is the whole point of oauth). You can see in the snipit here that create_from() will be called if login_from() does not succeed.
GITHUB AT at https://github.com/NoamB/sorcery-example-app/blob/master/app/controllers/oauths_controller.rb
def callback
provider = params[:provider]
begin
if #user = login_from(provider)
redirect_to root_path, :notice => "Logged in from #{provider.titleize}!"
else
begin
#user = create_from(provider)
Investigating the source code for create_from in all cases a new User Account record will be created. This would not be correct, if a User account record already exists.
My question: What sorcery methods should be called on the first facebook connect, if a User account has been created by some means other than facebook. login_from will fail, and create_from will generate a duplicate usser record?
You can use def create_and_validate_from(provider).
It will validate if the users email/username already exist. If its true, that he will store infos into a session and can be rendered into registration form.
And if you wish to add some provider to your account you can use def add_provider_to_user(provider).
Several requests have come through for an answer to this question, so I am providing the answer that Andy Mejia part of my team eventually arrived at for this question. We used the source within sorcery to adapt the following functions:
# Returns the hash that contains the information that was passed back from Facebook.
# It only makes sense to call this method on the callback action.
#
# Example hash:
# {:user_info=>{:id=>"562515238", :name=>"Andrés Mejía-Posada", :first_name=>"Andrés", :last_name=>"Mejía-Posada", :link=>"http://www.facebook.com/andmej", :username=>"andmej", :gender=>"male", :email=>"andmej#gmail.com", :timezone=>-5, :locale=>"en_US", :verified=>true, :updated_time=>"2011-12-31T21:39:24+0000"}, :uid=>"562515238"}
def get_facebook_hash
provider = Rails.application.config.sorcery.facebook
access_token = provider.process_callback(params, session)
hash = provider.get_user_hash
hash.merge!(:access_token => access_token.token)
hash.each { |k, v| v.symbolize_keys! if v.is_a?(Hash) }
end
# Method added to the User Account model class
def update_attributes_from_facebook!(facebook_hash)
self.first_name = facebook_hash[:user_info][:first_name] if self.first_name.blank?
self.last_name = facebook_hash[:user_info][:last_name] if self.last_name.blank?
self.facebook_access_token = facebook_hash[:access_token]
self.email ||= facebook_hash[:user_info][:email]
unless facebook_authentication?
authentications.create!(:provider => "facebook", :uid => facebook_hash[:uid])
end
self.build_facebook_profile if facebook_profile.blank?
save!
self.facebook_profile.delay.fetch_from_facebook! # Get API data
end
To show these code in context, I am also including logic from our controller:
def callback
provider = params[:provider]
old_session = session.clone # The session gets reset when we login, so let's backup the data we need
begin
if #user = login_from(provider) # User had already logged in through Facebook before
restore_session(old_session) # Cleared during login
else
# If there's already an user with this email, just hook this Facebook account into it.
#user = UserAccount.with_insensitive_email(get_facebook_hash[:user_info][:email]).first
# If there's no existing user, let's create a new account from scratch.
#user ||= create_from(provider) # Be careful, validation is turned off because Sorcery is a bitch!
login_without_authentication(#user)
end
#user.update_attributes_from_facebook!(get_facebook_hash)
rescue ::OAuth2::Error => e
p e
puts e.message
puts e.backtrace
redirect_to after_login_url_for(#user), :alert => "Failed to login from #{provider.titleize}!"
return
end
redirect_to after_login_url_for(#user)
end
I hope this solution is helpful to others.
I came across the same problem. While I have not found a direct solution via Sorcery, I did the following which seems to work:
#user = create_from(params[:provider]) do |user|
User.where(:twitter_id => user.twitter_id).first.blank?
end
This teqnique requires that you have twitter_id in the User model. You can also do it the other way around with the Authentication model instead. Such as:
#user = create_from(params[:provider]) do |user|
Authentication.where(:uid => user.twitter_id).first.blank?
end
If the block returns false, then it doesn't create the user. Avoiding any duplicates.
Note, the block for create_from does not work with 0.7.12. It works with 0.7.13.

Rails 3.2 - Application Controller + Devise Current_user Issue

I have two roles defined in my User Model:
User.role == admin
or
User.role == basic
In my Application Controller:
include MobilizedController
In lib/mobilized_controller.rb:
module MobilizedController
extend ActiveSupport::Concern
included do
before_filter :set_basic_request, :if => :basic_logged_in?
end
private
def set_basic_request
request.format = :basic
prepend_view_path "app/views/basic"
end
def basic_logged_in?
current_user.role == 'basic'
end
end
This is all fine when I am logged in, it sets the Mime Type correctly and renders my basic views.
Unfortunately, when I'm not logged in I get:
Undefined method 'role' for nil:NilClass
which I guess means that the current_user is not set, and thus calling nil on it won't work.
Does anyone have any suggestion for this? I need to be able to render the default log in page if a user is not logged in, and then set the Mime Type on login.
Any help?
In your example for basic_logged_in you set current_user.role to basic. It seems like you do not set a role for admin or not-logged in users.
So current_user.role is not set if you are not logged in or login as admin.

Rails 3 Flash with jquery

I use flash to tell the user if they logged in correctly or not, is there a way to put in the jquery code to fade after so many seconds or is there a way to do it with just the flash command?
Here is what im talking about
def login
#title = "Log in to Connect my Friends"
if param_posted?(:user)
#user = User.new(params[:user])
user = User.find_by_screen_name_and_password(#user.screen_name,
#user.password)
if user
user.login!(session)
flash[:notice] = "User #{user.screen_name} logged in!"
redirect_to_forwarding_url
else
#user.clear_password!
flash[:notice] = "Invalid screen name/password combination"
end
end
end
See http://snippets.dzone.com/posts/show/5271 for several examples of how to accomplish this.
Another example here: http://bjhess.com/blog/fading-flash-message/