devise and current_user - ruby

i have a question about devise system.
my last ruby project was done with nifty:authnentication. With nifty, i can manage session for current_user and other information from '"controller_authentication.rb"'. But now, i want to add a new current_* information.
I want to know where i can find current_user method? where is it defined?
with nifty i used something like
#current_company ||= Company.find(session[:company_id]) if session[:company_id]
thanks.

current_user is defined as a helper in devise source code. When you install devise on your project, it gets activated too.

current_user is defined dynamically in Devise. Since your user model could actually be a different model, the method uses your model name for 'mapping' when it defines the current_whatever helper method:
def current_#{mapping}
#current_#{mapping} ||= warden.authenticate(:scope => :#{mapping})
end
https://github.com/plataformatec/devise/blob/master/lib/devise/controllers/helpers.rb#L123

Related

How can I use current_user and cookies in a class thats written in a controller's concern module?

module DummyModule
extend ActiveSupport::Concern
included do
class DummyClass
#I would like to use current_user and cookies here without initialising the class with any arguments!
end
end
end
I know it is possible by initialising this class with arguments outside of the class DummyClass.new(current_user, cookies) but is there any other prettier way to do it?
There is no magic way to do that.
session and current_user are methods that are only available in the context of a controller. When you want to use them in a model then you have to pass them to the model.
Or you have to assign them to something that is available in the context of the model. Thread.current or CurrentAttributes might be an option – as Josh already pointed out. But keep in mind these both ways have downsides too.
The clearest and safest way is to just pass them to the model in its initialize method.

Call a method that is in my helper on rails 5

I have this helper for a session in rails 5 and it's calling to the user table and then session table, that's because I have it related in my database, the code is the following one:
module SessionsHelper
def generate_user_session
session_build = user.sessions.build
session_build.generate_access_token
session_build.save!
end
end
The problem is when I called the method in a controller it appears this error:
undefined local variable or method 'user'
I know this error is due to I'm not referring well to my helper in my controller, the question is...
How is the correct form I can call a method from a helper in my controller?
Note: Consider that in my helper I'm calling to my table user that is also calling the table sessions.
You are trying to access a variable (user) that's only available on your controller. You may try to set and use #user as instance_variable.
But as tadman write, you shouldn't use helper to controller propose.
If it is for session proposes you could use a concern or create a new Class to deal with this.

Caching ActiveRecord model instance methods

Say I have a user model. It has an instance method called status. Status is not an association. It doesn't follow any active record pattern because it's a database already in production.
class User < ActiveRecord::Base
def status
Connection.where(machine_user_id: self.id).last
end
end
So I do this.
#users = User.all
First of all I can't eager load the status method.
#users.includes(:status).load
Second of all I can't cache that method within the array of users.
Rails.cache.write("user", #users)
The status method never gets called until the view layer it seems like.
What is the recommended way of caching this method.
Maybe this instance method is not what I want to do. I've looked at scope but it doesn't look like what I want to do.
Maybe I just need an association? Then I get the includes and I can cache.
But can associations handle complex logic. In this case the instance method is a simple query. What if I have complex logic in that instance method?
Thanks for any help.
Have You tried to encapsulate this logic inside some plain Ruby object like this (I wouldn't use this for very large sets though):
class UserStatuses
def self.users_and_statuses
Rails.cache.fetch "users_statuses", :expires_in => 30.minutes do
User.all.inject({}) {|hsh, u| hsh[u.id] = u.status; hsh }
end
end
end
After that You can use some helper method to access cached version
class User < ActiverRecord::Base
def cached_status
UserStatuses.users_and_statuses[id]
end
end
It doesn't solve Your eager loading problem, Rails doesn't have any cache warming up techniques built in. But by extracting like this, it's easily done by running rake task in Cron.
Also in this case I don't see any problems with using association. Rails associations allows You to submit different options including foreign and primary keys.

Understanding CanCan initialize method

I'm having a hard time understanding how CanCan works. I have the following model
class Ability
include CanCan::Ability
def initialize(user)
if user && user.email == "jason#gmail.com"
can :access, :rails_admin # only allow admin users to access Rails Admin
can :dashboard # allow access to dashboard
end
end
end
When it comes to my rails_admin file in the initializers folder
RailsAdmin.config do |config|
config.authorize_with :cancan
config.main_app_name = ['Pr', 'Admin']
config.current_user_method { } # auto-generated
end
I want to have one user to access the admins dashboard with the email "jason#gmail.com", but how does CanCan know who is currently signed in at the time? Does it rely on a helper method I'm missing?
CanCan uses a current_ability method to supply the ability, and in that it uses current_user. I know at least Devise has this method, other auth frameworks must commonly supply it too, not sure.

How to access Warden current user in business logic in Rails3

I am using Rails Warden plugin. It defines a helper method 'user' that returns current user. See the link for the source code.
Now I have an business logic object that does not have any reference to the controller. But I would like to get the current user. Is there any way of accessing this?
I have tried
ActionController::Base.helpers.user
or even
RailsWarden::Mixins::HelperMethods.user
with no luck. Thanks.
Now I have an business logic object
that does not have any reference to
the controller. But I would like to
get the current user. Is there any way
of accessing this?
So why can't you just pass the current user to those methods?
Additionally you can mix them in.
I strongly discourage you to write the static helpers (it is not Java, it is Ruby!).
Instead, where you need those helpers include them as a module:
module SuperLogic
def calculate_stuff(current_user=nil)
(current_user || user || self).bills.sum
end
edn
Then include this where you need it:
# user model
class User
include SuperLogic
#it will get the `calculate_stuff` method
end
# controller
include SuperLogic
# so you can use it as one of
calculate_stuff user
calculate_stuff
and so on...
additionally where you access your business logic, you can just create an instance of the class instead of "static" methods (in ruby they are "class" methods):
# controller
def calculate
#result = BusinessLogic.new(user).calculate_stuff
end
This is probably the easiest thing you can do.
Really, you don't need to access whole HTTP context in your business objects (I'm not even talking about testing it).
The way I think of business logic, it's something that sits between the controller and the model. I think it would be ok to pass an instance of the request to the logic methods, and since you're using warden, you can get the user from 'request.env['warden'].user'.
I haven't encountered a good reason not to have logic methods be static (self.) methods of a module. Maybe Dmytrii's suggestion works for you, but I prefer to 'require' than to dynamically include one-off logic bits.

Resources