How get Devise's current_user method in Rails Engine - ruby-on-rails

I have a Rails application that's using the Devise gem, and I'm creating a Rails Engine to mount in this app.
mount Comments::Engine => '/talk', :as => 'comments'
Within the Engine, I want to get the current_user instance from main application.
In {main_app}/initializers/comments.rb
Comments.user_class = "User"
Comments.current_user = "current_user" #current_user is Devise method(works fine in app)
In {engine}/lib/comments.rb
require "comments/engine"
module Comments
mattr_accessor :user_class, :current_user
def self.user_class
##user_class.constantize
end
def self.current_user
send(##current_user)
end
end
When I call Comments.current_user, I get the error "wrong constant name current_user".
What am I doing wrong?

Seams I'm solved problem.
I'd call current_user within Comments model and it didn't work.
However getting current_user from controller, works fine.
But this is not elegant way (.

Related

undefined local variable or method `current_user' cancancan

I'm working on a login/logout system. Instead of using devise, I created an active records User model and use sessions to remember if a user is logged in. Everything was working fine until I added these lines in the application_controller.rb to have a layout before login and one after.
layout :set_layout
def set_layout
if session[:current_user_id]
'afterlogin'
else
'application'
end
end
Now, after I log in and cancancan is being used somewhere in a html page I get undefined local variable or method 'current_user'. I think that I have to add a current_user method but I'm not exactly where and how to define it.
Edit: I already had something similar in another class that is being used by login:
class Admin::ApplicationController < ApplicationController
before_action :authorize
def authorize
begin
#current_user ||= User.find(session[:current_user_id]) if session[:current_user_id]
rescue ActiveRecord::RecordNotFound
session.destroy
redirect_to '/login',alert: 'Please login'
end
end
end
Should I modify this after I add that method ?
CanCanCan expects a current_user method to exist in the controller.
First, set up some authentication (such as Authlogic or Devise).
See Changing Defaults if you need different behavior.
I would suggest you to install Devise so that it comes with a complimentary current_user method.
FYI: https://github.com/plataformatec/devise
UPDATE
when a user logins successfully, you can store the user's id in session.
session[:current_user_id]=user.id
so that, in your applicationcontroller, you can do
def current_user
#current_user ||= session[:current_user_id] && User.find_by_id(session[:current_user_id])
end
helper_method :current_user

CanCan - "user" parameter is nil - Rails 4

I am using Rails 4.0.1 and ruby 2.1.1. I am trying to integrate cancan with rails_admin. My application_controller.rb looks like this
helper_method :current_user
private
def current_user
#current_user ||= User.find_by(email: session[:user_id]) if session[:user_id]
end
My current_user helper method is working fine from rest of the application. My ability.rb looks like this
class Ablity
include CanCan::Ability
def initialize(user)
if user
can :access, :rails_admin
end
end
end
Control is not going inside the if condition at all, which means the "user" parameter is "nil". When I try to access rails_admin I get a CanCan::AccessDenied exception. Where am I going wrong?
Edit : I am not using devise for authentication
Update : I've replaced cancan with cancancan version 1.8. Still not working
Solved. In config/initializers/rails_admin.rb we have to specify the current_user_method as
config.current_user_method { current_user } # refers to the current_user helper method in my case
Now everything is working perfectly. I am surprised why this isn't specified anywhere in the documentation.

Rails rspect helper method not found

Simple question.
I have a method in my ApplicationHelper that calls my SessionsHelper to load the current_user
i.e.
module ApplicationHelper
def some_helper_method
if current_user.respond_to? :some_method
#does stuff
end
end
end
module SessionsHelper
def current_user=(user)
#current_user = user
end
def current_user
#current_user ||= User.find(...)
end
This works fine in my running application. However when running from Rspect the ApplicationHelper method cannot find current_user method. In the running app I know the method is available by some rails automagic class loading. But not sure what the best way is to make this work in Rspec.
There are multiple ways to handle this issue, but let me give you some background first.
You can configure rails to tell it what kind of helpers you are going to expose to your controllers and within your views with include_all_helpers.
In the old days you had a call to helper :all in your ApplicationController.
So that's how those methods get exposed.
Back to your question:
Solution numero uno: helper.stub(current_user: build(:user))
Solution numero due: helper.extend UserHandling
Prego

How to let the Application controller know that a user has signed in (users are handled with devise)

I'm using Devise to handle users in a shopping application. What I want to do is create a new cart each time a user signs in (and ideally, destroy the same cart each time a user signs out, but I'll just stick to that first part for this question).
So far, I've looked at this question: Devise call backs
And I came up with this:
class ApplicationController < ActionController::Base
helper :all
protect_from_forgery
before_filter :fetch_categories
.
.
.
Warden::Manager.after_authentication do
session[:cart_id] ||= Cart.create!.id
end
end
...But clearly this isn't correct, because I'm getting this error:
NameError in Devise::SessionsController#create
undefined local variable or method `session' for ApplicationController:Class
Is there some other way I can tell the application controller to respond to a user sign in, or should I be putting this code elsewhere (other than the application controller)? Thanks for any help.
Glancing at the docs, it looks like you can do something like this:
Warden::Manager.after_authentication do |user, auth, opts|
auth.session[:cart_id] ||= Cart.create!.id
end
Simpally write a before filter
In application controller
before_filter :set_current_user
def set_current_user
Authorization.current_user = current_user
end
and
you can check throughout application
using
` if !current_user.nil?
end`

Rails Authorization Plugin Error

I'm trying to get the permit method to work using the rails-authorization-plugin and authlogic, and I keep running into this error:
When I try:
class ApplicationController < ActionController::Base
...
before_filter permit 'admin'
...
I get this:
Authorization::CannotObtainUserObject in HomeController#index
Couldn't find #current_user or #user, and nothing appropriate found in hash
Now I do have my current_user method setup, and it works, because I used it just about everywhere else in my app:
class ApplicationController < ActionController::Base
...
helper_method :current_user
private
def current_user_session
return #current_user_session if defined?(#current_user_session)
#current_user_session = UserSession.find
end
def current_user
return #current_user if defined?(#current_user)
#current_user = current_user_session && current_user_session.record
end
...
I also know that I have users with the appropriate roles in my database, because this method works:
def require_admin
unless current_user.is_admin? || current_user.is_root?
flash[:warning] = 'You are not an administrator and cannot access this page.'
redirect_to root_path
end
end
I can make everything work if I just check on the user level using this:
before_filter :require_admin, :only => 'index'
... but shouldn't I be able to the same thing effectively with permit and permit??
Any help would be much appreciated. Let me know if you need to see more code and I'll be happy to post it. There really is nothing on Google that I can make heads-or-tails of regarding getting these two systems to work with each other.
Okay, I think I figured it out.
As Jared correctly pointed out, the proper usage is
permit 'admin'
(Not as part of a before_filter).
HOWEVER...
... the default :get_user_method is set to #current_user, which is what the acts_as_authenticated plugin uses. I, as noted earlier, am using AuthLogic, in where I have the method defined as current_user (without the pound sign).
So, I had tried the following:
permit 'admin', :get_user_method => current_user
Only to be greeted by a nice error message explaining that I had no such variable or method. What I was missing, however, is that the hash option takes a string, not a direct call to the method!! (stupid mistake, I know!)
So
permit 'admin', :get_user_method => 'current_user'
... seems to work for me.
I love Ruby and Rails, but sometimes its simplicity can be a curse of its own; I always get owned by the simple things. :)
You are using the plugin incorrectly. It should not be placed in a before filter.
On the global level, you simply declare:
permit 'admin'
That's it.
All of your actions will look for a current_user or #user object and redirect to the login page if not.
On a per-action level, you use it as a block:
def index
permit 'admin' do
#some_models = SomeModel.all
end
end

Resources