A Sense of Belonging
Friday, August 29th, 2008Numerous 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).
