Reputation: 4565
I'm using devise for authentification, so I have a current_user in every controller. My models are:
class User < ActiveRecord::Base
has_many_and_belongs_to :posts
end
class Posts < ActiveRecord::Base
has_many_and_belongs_to :users
end
class PostsController < ApplicationController
before_filter :authenticate_user!
def show
@post = Post.find(params:id)
# need to check if @post belongs to current_user here
# ...
end
def edit
@post = Post.find(params:id)
# need to check if @post belongs to current_user here
# ...
end
end
Some of the actions in PostsController (for instance show and edit) need to check if the Post fetched from the DB belongs to the current_user. If it doesn't, I want to show a 404 error and end the execution (just after the find call).
Obviously I would like to stay DRY, so I don't want to write the same code in every action.
I've tried to write a private method in PostsController, however from a private method I cannot redirect to a 404 and then interrupt the execution immediately.
A before_filter won't work since I would be executed before each action, and I need the @post object which is being fetched inside each action.
Finally I don't want to use additional gems like CanCan.
Upvotes: 1
Views: 2767
Reputation: 7733
controller code
class PostsController < ApplicationController
before_filter :authenticate_user!
before filter :load_post, :only => [:edit, :update, :show]
private
def load_post
@post = current_user.posts.find_by_id(params[:id)
@post ||= invalid_url! # defined in app controller
end
end
Upvotes: 0
Reputation: 9529
How about writing a private method that returns a boolean and redirecting in your main method based off of the return value?
class PostsController < ApplicationController
before_filter :authenticate_user!
def show
redirect_to 404 if !check_my_stuff?
# need to check if @post belongs to current_user here
# ...
end
def edit
redirect_to 404 if !check_my_stuff?
# need to check if @post belongs to current_user here
# ...
end
private
def check_my_stuff?
@post = Post.find_by_id(params:id)
(@post.user == current_user) ? true : false
end
end
Upvotes: 0
Reputation: 2160
I have not tested this, but you should be able to do something like this:
class Post < ActiveRecord::Base
has_many_and_belongs_to :posts
scope :for_user, lambda { |user| joins(:users).where("user_id = ?", user.id)
end
Then in your controller:
Post.for_user(user).find(params[:id])
That way the logic is not repeated and it's reusable.
Upvotes: 2