Numerous times I’ve needed and I’ve seen other people have needed the need to check whether an object belongs to the currently logged in user. I’ve worked out that something like this works:
class User < ActiveRecord::Base
has_many :posts
def owns?(object)
object.user == self
end
end
This works when you have a currently logged in user and call it by using current_user.owns?(@post). Now what if you wanted to do it the other way around? Well it’s really as simple as this:
class Post < ActiveRecord::Base
belongs_to :user
def belongs_to?(other_user)
user == other_user
end
end
Now you can reference that through @post.belongs_to?(other_user).
If you wanted to use either of these in the controller, it would be like this:
class PostsController < ApplicationController
def edit
@post = Post.find(params[:id])
check_ownership
end
def update
@post = Post.find(params[:id])
if current_user.owns?(@post) # or @post.belongs_to?(current_user)
# carry on...
if @post.update_attributes(params[:post])
flash[:success] = "Post updated!"
redirect_to topic_path(@topic)
else
flash[:error] = "Post could not be updated."
render :action => "edit"
end
else
flash[:error] = "You do not own that post."
end
end
private
def check_ownership
if !current_user.owns?(@post) # or @post.belongs_to?(current_user)
flash[:error] = "You do not own that post!"
redirect_back_or_default topic_path(@topic)
end
end
end
Now here we’ve called check_ownership in the edit action which will stop the template from being rendered by calling redirect_back_or_default. We can’t call (as I found out thanks to Blue_Sea) check_ownership in the same way in the update action because the code will still be executed. So we must call the methods we defined in the model, either current_user.owns?(@post) or @post.belongs_to?(current_user).