rails model before_update can't access current_user - ruby-on-rails

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.

Related

Call helper function from rails 4 notifications subscribe

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?

How to use "current_user" with devise in Rails?

The code in question is in the create action of the Article controller.
I want each new article created to belong to the currently signed in User.
I checked that there is a user_id column in the Articles table and the correct association statements are in both models.
When I try and submit the form for a new Article, I get this error:
undefined method 'article' for nil:NilClass
in reference to this line of code:
#article = #current_user.article.new(article_params)
Am I using current_user incorrectly? How would one go about making the new item belong to the currently signed in user?
You should use current_user method:
#article = current_user.articles.new(article_params)
#current_user instance variable isn't set (thus it evaluates to nil) until current_user is called.
current_user is basically a convenience method/variable which takes the user id from the session hash and grabs that user (which is the current user that is active on that specific request)
so, when you want to have something only on the current user, just called current_user
however, there are some things you should watch out
make sure that the current user is logged in.
so make sure that when calling current_user.article.new(params) that current_user isn't nil, or it will throw an exception
when you want something to be only on that specific logged in user make sure to do as you did in the question
such as:
current_user.articles instead of Article.where(user_id: ...)
this will help you avoid problems in the future, and it may be faster in some situations
and 3. I think it should be current_user.articles.new(...)
It should be current_user, not #current_user.
current_user is a method, not an instance-variable.

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

ActiveRecord callback access to session data

I am trying to add current user information to record using ActiveRecord callback, but I don't see way how to do that.
I tried Thread.current[:user], but in results I see that thread value is accessed from another user sessions.
I am using Passanger in production, but in the same time I am using acts_as_audited who get user value correctly.
Whats the best/safest way how to do that?
The current user is not accessible from within an ActiveRecord model. This is due to the separation of concerns in Rails--the current user and the session are concepts that pertain to the realm of the controller.
You need to get the relevant data and pass it into the model in order for your callback to work. One way to do this is with an accessor method:
# model
attr_accessor :current_user
def my_callback
# do something with current_user
self.some_attribute = current_user
end
# controller
#model = MyModel.find(params[:id])
#model.current_user = current_user # assuming you have a controller method that does this
#model.save!
You should rename the current_user accessor to be meaningful: eg. if you are tracking the author of a blog post, call it author or responsible_user or some such, since current_user means nothing once the model is saved.

newbie: how to pass User to Asset model for custom method?

Trying to use current_user.id (devise) inside my asset model, only current_user.id isn't available. How do I make current_user.id available in my Asset model? ( passing user to asset model somehow?)
after_save :set_photo
def set_photo
user = User.find_by_id(1)
# user = User.find_by_id(current_user.id) <-- should be this
user.has_photo = true
user.save
end
You cannot use current_user in a callback chain within your model scope. This is because current_user is a property of the request-response cycle. Also, having to use current_user in your model almost certainly means your database design is inadequate or wrong.
For e.g. in your case, why are you trying to update an attribute of a User when Asset is updated? That is a certain code smell unless they are related.
A couple of things you can try:
Correct the DB design problem - Define an association between Asset and User. You can then do #asset.user = current_user (or something to this effect) in your controllers.
Ugly, brute force method: Do not depend on callbacks and explicitly call your method in your controllers.

Resources