Reputation: 5110
You know, I think I have to check current user in the model callbacks (like before_update
). Rather than rely solely on adding where ('something.user_id = ?', 'current_user.id')
in the controllers. I need something like Thread.CurrentPrincipal
in .NET
Is it safe to put reference to current user in User model? I'm sorry I don't really understand how it works under the hood yet.
Or how you do it The Rails way?
Sorry if this a silly question.
Added on 3/27
Oops
To get the right answer you have to ask the right question. And that's not an easy task in itself. How can it be that other people's questions are so obscure and they get their answers and your own question is so clear-cut but nobody understands it? :)
I do not understand where to put security check. That the user will get access only to his own stuff. On the controller level? And then test every action? "should not /view|create|edit|destroy/ other user's stuff"? I thought may be I can put it in the model and have one place to /write|refactor|test/. That's why I asked about how I can get a reference to the current user.
Actually I'm surprised I didn't find anything relevant in Rails Guides or Blogs. Some questions were asked but no authoritative "best practices" besides "don't do it".
After giving some thought I decided to just create in the controller before_filter the scope scoped to the current user and just rely on my own convention (promised to myself that I won't access the model directly). And just test it once per controller. That's not a banking application anyway.
Upvotes: 1
Views: 193
Reputation: 12426
I don't really understand Thread.CurrentPrincipal
, but current_user
generally means the logged in user and that is completely a controller context. It is not available for use inside a model. So a hacky solution would be:
class UseCase < ActiveRecord::Base
after_save :my_callback_method
attr_accessor :current_user
def my_callback_method
# Some operations based on current_user
end
# ...
end
And then in your controller:
#...
use_case = UseCase.find(use_case_id) # Just an example, can be anything
use_case.current_user = current_user
# then this
use_case.save
# or basically
use_case.method_that_triggers_after_save_callback
#...
Warning: I am sure this is bad practise (I have never used it myself). But this will work. Ruby gurus / MVC gurus out there, please comment.
Upvotes: 0
Reputation: 49354
I'm not sure I get your situation. If you want to check if some other model's instance belongs to current user - use associations (I inferred that from "something.user_id = ?").
Else - in ActiveRecord before_update
method is used on a per-instance basis. I.e. you pass current instance to that callback as an argument. Hence:
def before_update(current_user_instance)
current_user_instance.do_something
end
Will yield any user instance as current_user_instance
in the callback. So you can do following:
>> user_1 = User.find(1)
>> user_1.update_attribute(:some_attribute, 'some value')
>> user_2 = User.find(2)
>> user_2.update_attribute(:some_attribute, 'some other value')
This will call do_something
method on separate instances (user_1
and user_2
)
Upvotes: 1