Trying to use current_user where it is undefined
I have this call in my vote model:
fires :vote_updated, :on => :update,
:actor => :user,
:secondary_subject => :video,
:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && (vote.video.user != current_user)}
In case you aren't familiar, it works with the timeline_fu plugin.
I do not want the call to be fired if the user who owns the voted up video is the current user. That is where this line comes in:
:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && (vote.video.user != current_user)}
However, I do not have access to current_user
here. How do I get around this?
Here's the create method in my votes controller (there actually is no update method):
def create
@video = Video.find(params[:video_id])
@vote = current_user.video_votes.find_or_create_by_video_id(@video.id)
if @vote.value.nil?
if params[:type] =开发者_开发问答= "up"
@vote.value = 1
else
@vote.value = -1
end
elsif (params[:type] == "up" && @vote.value == 1) || (params[:type] == "down" && @vote.value == -1)
@vote.value = 0
elsif ((params[:type] == "up" && @vote.value == -1) || (params[:type] == "down" && @vote.value == 1)) || (@vote.value == 0)
if params[:type] == "up"
@vote.value = 1
else
@vote.value = -1
end
end
if @vote.save
respond_to do |format|
format.html { redirect_to @video }
format.js
end
else
respond_to do |format|
format.html
format.js
end
end
end
I believe the right thing to do would be validating this in controller. I would create a before filter for this case
UPDATE:
Just as a quick example:
before_filter :valid_vote, :only => :update
def update
@vote.update_attributes(params[:vote]) # or whatever
end
..
private
def valid_vote
@vote = Vote.find params[:id]
unless ( @vote.video.user.id != current_user.id )
render :text => 'You can't vote for your own video', :status => 403
end
end
So @vote is being declared and validated before your 'update' action is proccessed. If it's not valid then your 'update' action stays untouched
UPDATE 2 :
not sure how you'll like it, but you could also do as follows:
in your Vote model:
attr_accessor :skip_timeline
then use the concept with before filter, but do @vote.skip_timeline = true
instead of rendering text
then the statement might look as follows:
:if => lambda { |vote| ((vote.value == 1) || (vote.value == -1)) && !vote.skip_timeline }
You could also move ((vote.value == 1) || (vote.value == -1))
to your before filter :
def valid_vote
@vote = Vote.find params[:id]
unless ( [1,-1].include? @vote.value && @vote.video.user.id != current_user.id )
@vote.skip_timeline = true
end
end
and
:if => lambda { |vote| !vote.skip_timeline }
You are getting this error because it's typically not recommended to access current_user (or session information) in your model. I am not all that familiar with the timeline_fu gem, so this answer isn't going to be the greatest answer you may get. I'm merely going to show you how to access current_user from any model.
First go to your application controller. You'll want to make a method that sets the current user. You need to call the method in the before filter.
before_filter :loadCurrentUser
def loadCurrentUser
User.currentUser = current_user
end
Then in your User model, you need to define 'currentUser'.
def self.currentUser
Thread.currentUser[:user]
end
You don't necessarily have to declare the current_user in the application controller, but since it's a gem, I'm not sure if it has an easily accessible controller.
Edit: This way may be prone to problems, but I'm not entirely sure if you were asking how to make current_user available in models, or a completely different workaround so you do not have that problem... and reading the responses of the other answer, I'm thinking it's not what you were asking.
精彩评论