How can we access current_model (Devise:Here model can be User,Account etc.) method inside AR model?

Hello Guys,

I faced a situation in Rails that I need current_user method inside model. There is a condition that I do not have any column that is associated

with current_user in model. I do not want to declare virtual attribute in each activerecord model also do not want to set it in global variable. How can I achieve this?

Your help will be highly appreciated.

Thanks.

Current user is a session concept, are you sure you are doing things in the correct place?

Maybe you are doing something in a active record hook that should be a method called by the controller…

It would help if you can share the actual code, maybe we can get a better idea of what you want to achieve.

Devise is written to be model name agnostic. They use the reference name `resource` internally to mean User, Admin, ChiefPoobah, Peasant -- whatever you choose to call your user model. If you're not hacking on Devise, then you may need to look for a similar abstraction in what you are working on. More details would help us help you...

Walter

Here is the code snippet.

class Attendance < ApplicationRecord

ATTENDANCE_EDITABLE_VALIDITY = 7

before_save :is_editable?

belongs_to :attendance_detail

def is_editable?

errors.add(:attendance, ‘modification is not allowed.’) if attendance_detail.created_at.present? && (Time.zone.now.to_date - attendance_detail.created_at.to_date).to_i >= ATTENDANCE_EDITABLE_VALIDITY unless current_user.super_admin? || current_user.admin?

errors.empty?

end

end

``

I have lots of conditional callbacks based on current_user in AR.

I do not want to move these conditions in controller. As there are lot of other conditions that are user permission specific.

Okay. You're not going to be able to access current_user in a model like this. There's just no notion of who is using the app in the Model context. In a controller or view, yes, you can do this (although I would recommend you use CanCanCan or Pundit to abstract the authorization away into its own domain).

You want to think about this from the perspective of can_edit? rather than is_editable?. The former works on a user, which the controller or view would know about. The latter is specific to the instance of the model -- has it had the "publish" checkbox clicked? has an admin approved it? etc.

I suspect you will keep your is_editable? method (without the user-specific stuff) and then add on to that with a can_edit? method that may in fact also invoke the is_editable? method from its target.

Walter

**Okay. You’re not going to be able to access current_user in a model like this. There’s just no notion of who is using the app in the Model context. In a controller or view, yes, you can do this (although I would recommend you use CanCanCan or Pundit to abstract the authorization away into its own domain). **

- There are two type of users updating this record. One with admin permission and another with area_admin. But in case of area admin I also need to check that record should not be older than 7 days. I am already using pundit for authorization.
**You want to think about this from the perspective of can_edit? rather than is_editable?. The former works on a user, which the controller or view would know about. The latter is specific to the instance of the model – has it had the “publish” checkbox clicked? has an admin approved it? etc. **
I suspect you will keep your is_editable? method (without the user-specific stuff) and then add on to that with a can_edit? method that may in fact also invoke the is_editable? method from its target.

- It means I need to remove before_save callback and simply keep is_editable method and invoke it on target object with can_edit? in controller? Right?

Okay. You're not going to be able to access current_user in a model like this. There's just no notion of who is using the app in the Model context. In a controller or view, yes, you can do this (although I would recommend you use CanCanCan or Pundit to abstract the authorization away into its own domain).

- There are two type of users updating this record. One with admin permission and another with area_admin. But in case of area admin I also need to check that record should not be older than 7 days. I am already using pundit for authorization.

You want to think about this from the perspective of can_edit? rather than is_editable?. The former works on a user, which the controller or view would know about. The latter is specific to the instance of the model -- has it had the "publish" checkbox clicked? has an admin approved it? etc.

I suspect you will keep your is_editable? method (without the user-specific stuff) and then add on to that with a can_edit? method that may in fact also invoke the is_editable? method from its target.

- It means I need to remove before_save callback and simply keep is_editable method and invoke it on target object with can_edit? in controller? Right?

That could work. Another way to do this is to loop it into a validation. can_edit? could govern whether the edit button appears in the view, but if you added it to the validations, then it could also keep you from saving a record you shouldn't if you somehow manage to get the form to load (by hacking the path).

Walter

Thanks Walter for the help.