0

How can I access a controller's instance variable inside of a model?

In this example, I want to access the instance variable @user inside of the model.

Post Controller

class PostController < ApplicationController
  def destroy
    @user = User.find(params[:user_id])
    post = Post.find(params[:id])
  end
end

Post Model

class Post < ActiveRecord::Base
  belongs_to :user

  before_destroy :check_if_owned_by_user
    if self.user != @user
      return false
    end
  end
end
Don P
  • 60,113
  • 114
  • 300
  • 432
  • possible duplicate of [Ruby on Rails - Access controller variable from model](http://stackoverflow.com/questions/2419120/ruby-on-rails-access-controller-variable-from-model) – Pavan Jul 19 '15 at 10:01

2 Answers2

0

you cannot access @user in the post model. the callbacks do not accept parameters as they triggered automatically. you have to explicitly call the method from the controller. like this.

class PostController < ApplicationController
  def destroy
    @user = User.find(params[:user_id])
    post = Post.find(params[:id])
    if post.check_if_owned_by_user(@user)
      #delete it
    end
  end
end

class Post < ActiveRecord::Base
  belongs_to :user

  def check_if_owned_by_user(user)
    self.user == user
  end
end
Athar
  • 3,258
  • 1
  • 11
  • 16
  • seems dangerous to rely on every controller to remember to include that condition - I'd much rather keep it in the model if possible – Don P Jul 19 '15 at 09:57
  • you may need to change logic to allow deletion for only those users who have the access to do it. that also includes condition. but according to my knowledge i dont think you can pass parameter to callbacks... – Athar Jul 19 '15 at 10:00
  • I would implement it as a before_action to the PostsController. – Lanny Bose Jul 20 '15 at 21:26
0

Checking whether the current user is allowed to delete an object is an authorization concern, and should be handled within your authorization method(eg. cancan).

If you must handle it manually, consider using a service object to achieve the same. Callbacks are messy things once they accumulate.

class DestroyPost
  def initialize post, user
    @post = post
    @user = user
  end

  def call
    return false unless @post.user = @user
    @post.destroy
  end
end

You'd call DestroyPost.new(@post, @user).call in the controller instead of @post.destroy

fylooi
  • 3,840
  • 14
  • 24