Call helper function from rails 4 notifications subscribe - ruby-on-rails

I need to save all controller notification to database. I create a /config/initializers/notifications.rb
ActiveSupport::Notifications.subscribe('process_action.action_controller') do |name, start, finish, id, payload|
Action.create(
action_type: name,
user: current_user,
data: payload
)
end
but I get error:
undefined local variable or method `current_user' for main:Object
current_user is a helper it app/helpers/session_helper.rb and it works in entire application.
I need to know user, which made action. How can I call current_user in this context?

current_user is usually set in the application_controller of your
application. If you use a gem like Devise to handle user
authentications for example, they take care of setting such method for
you.
The initializers' code is executed when you launch your application on
your server (local machine or remote server), therefor you understand
that a "current_user" (understand a "logged in" user) simply does not
exists (yet).
Source - is it possible for current_user to be initializer, in rails 3?
Hope this helps!

current_user is a helper it app/helpers/session_helper.rb and it works in entire application.
Let me correct you here.
You can't access current_user in your initializer files. Initializers are run once on application startup, so don't expect accessing current_user like this.

I found solution: append_info_to_payload
class ApplicationController < ActionController::Base
...
def append_info_to_payload(payload)
super
payload[:current_user] = current_user
end
From this answer:
How to add attribute to existing Notifications payload?

Related

memoization in rails using an instance variable

I'm following railstutorial by Michael Hartl. In chapter 8.2.2 he defines a variable #current_user and a method current_user.
app/helpers/sessions_helper.rb looks like this:
module SessionsHelper
# Logs in the given user.
def log_in(user)
session[:user_id] = user.id
end
# Returns the current logged-in user (if any).
def current_user
#current_user ||= User.find_by(id: session[:user_id])
end
end
Hartl defines #current_user an instance variable (of User object I guess); How can #current_user be an instance variable if it is itself an instance of the User class?
This is such a good question. It seems that this arrangement is not something that it was planned for, it simply happened: u need to have a variable that has some kind of memory outside the method (scope), in order to compare if #current_user=#current_user, but at the same time the whole arrangement makes theoretically no sense.
This article was written in 2008 and was proof read from members of the rails core team. This paragraph is very telling of the situation:
http://www.railway.at/articles/2008/09/20/a-guide-to-memoization/
--> "A little note on naming here: Some people seem to prefer prefixing the memoizing variable’s name with an underscore to indicate that it’s not meant to be used as an actual instance variable. To be honest, I don’t think this is really necessary unless you define a whole bunch of instance variables and memoized variables."
The SessionsHelper module is mixed into your controllers, so #current_user will be set as an instance variable of the controller which is handling the current request (Rails creates a new controller instance to handle each request)

Rails -> Devise -> how to access current_user from Module

I'm currently using Rails 3.2.9 with devise 3.0.4
I can access Devise current_user in Controller without any problem.
However, when I'm trying to access current_user in Module as below and receive error.
c_time = DateTime.current.in_time_zone(current_user.local_timezone)
NameError (undefined local variable or method `current_user' for DateCalculator:Module):
It would be great if someone please advise what's the best way to access current_user from Module.
Many Thanks in advance.
Try this one instead of using current_user object
UserSession.find.user
If your module does something specific to current signed in user, your can follow this way
config/initializers/user_specific_time.rb
module Devise
module Controllers
module Helpers
def user_specific_time
c_time = DateTime.current.in_time_zone(current_user.local_timezone)
end
end
end
end
There is a Gem called sentient_user it is a cheeky approach but it does exactly what you need ;) which is to have access to current logged in user, from view | Controller | Model etc
https://rubygems.org/gems/sentient_user

Rails 4.1: access current_user in ActionMailer::Preview

Rails 4.1 has a nice way to preview mailers with ActionMailer::Preview. All of my mailers take a user parameter, and I would like to pass in current_user (from Devise) for the preview.
If I try this, it doesn't work.
class SubscriptionsMailerPreview < ActionMailer::Preview
# Preview this email at http://localhost:3000/rails/mailers/subscriptions_mailer/new
def new
SubscriptionsMailer.new(current_user)
end
end
It returns undefined local variable or method 'current_user' for #<SubscriptionsMailerPreview:0xa6d4ee4>.
I suspect this is because current_user is defined by Devise in ApplicationController, and according to the docs, ActionMailer uses AbstractController::Base. In that case, would storing current_user in a class variable be a bad idea?
Does anyone know how I can use the current_user helper in ActionMailer::Preview?
What would happen if you move your mailer job to the background? How would you get the current user then?
The mailer and its preview should not know about the current_user. The mailer's job is to send the mail to a user it receives. The preview is there to visually demonstrate its behaviour.
Create a new user in your mailer preview, and pass it to the mailer.
def new
user = User.create! # etc...
SubscriptionsMailer.new(user)
end
It doesn't matter who the user is. It matters that it's a user object.
If you want to test that the application will send a mail to the current_user, write a functional test for that.
You are right method defined in Controller won't be available in helper.
These posts can help you:
Where do I put helper methods for ActionMailer views? Access helpers from mailer?
https://www.ruby-forum.com/topic/168949

Rails/devise current_user accessed in model but it's nil

I needed to access the current_user in my another model. I googled and found a few solutions and tried this.
But just one difference: I didn't set the User.current_user in the controller. WHY?
Like in the answer I followed I'm not adding data to my second model from views but by rendering data via a url (with open-uri, it's csv data I'm fetching).
So in my second model I do:
Person.create(username: User.current_user.username)
It gives:
NoMethodError: undefined method `username' for nil:NilClass
which isn't working (which is obvious I guess). In console when I do User.current_user it shows:
1.9.3p448 :002 > User.current_user
=> nil
I think why it isn't working is because I'm accessing the User.current_user directly from model and model cannot get the current_user unless it is given that. (right?)
But this would definitely work if I access it via a login page and set the User.current_user in the controller.
But as I'm directly fetching the data from url, I'm directly making new entries for my Person model in model itself.
So how do I set the User.current_user?
Is there any workaround for this? Edit's for the question's title are required.
current_user is available by default as a helper method within Devise. From the documentation:
# For the current signed-in user, this helper is available:
current_user
The current_user isn't accessed directly via the model, per se, but rather, though the Devise module, which looks up the User object that is logged into the current session, and then returns to current_user.
Thus, the current user isn't accessed via User.current_user (there is no current_user method on User, as the error message is saying). You access it purely by invoking the current_user helper method within a controller or view.
UPDATE:
You're well advised to keep your controller and model layers separate. One way of doing what you've proposed is to create a class function on the Person model wherein you explicitly pass the username of your User object from within your controller:
# in your controller
Person.create_with_username(:username => current_user.username)
# app/models/person.rb
def self.create_with_username(username)
self.create(username)
end

rails model before_update can't access current_user

I would like to update the inspector_id in table Tasks with the employee_id of the current user. But, the model won't let me access current_user.
This is the code I'm trying to use in the Task model.
before_update :update_inspector
protected
def update_inspector
self.inspector_id = current_user.employee
end
I get:
NameError (undefined local variable or method `current_user'
Typically current_user is defined in the application controller. This means that the method is only available inside controllers, not models. The error you are seeing is consistent with that state of affairs. If you need the current_user in the Task model, you'll have to pass it in somewhere.
You could always access the session information that built the current_user variable inside of the model.

Resources