I am using Devise to authenticate users. I need to show/hide data based on global_location_id column in all my tables. The value of current global_location_id will come from current_user.global_location_id. I tried adding a following default scope to one of my models:
class Artifact < ActiveRecord::Base
default_scope where(:global_location_id => current_user.global_location_id)
But it gives following error:
undefined local variable or method `current_user' for #<Class:0x8721840>
To circumvent the unavailability of current_user in models I added following to my application controller
class ApplicationController < ActionController::Base
def set_global_location_id
@global_location_id = current_user.global_location_id
end
And called the method from my controller
class ArtifactsController < ApplicationController
#Check to see if the user is logged in first
before_filter :authenticate_user!
before_filter :set_global_location_id
Changed the default scope in model to add @global_location_id
class Artifact < ActiveRecord::Base
default_scope where(:global_location_id => @global_location_id)
But this does not work either. The @global_location_id is being set properly in application controller. But it is empty in the model. How to make it work.
Unfortunately you aren't going to be able to share an instance variable that's set in the controller with an instance of the model (without some thread hackery). This is actually a good thing though because otherwise it would be acting like a global variable, which would cause you more harm than good.
I'm actually having a hard time understanding why you would want to do it this way because it would add some nasty coupling between the state of the currently logged in user and your model. If you tried to find an Artifact in the console, the current_user does not exist, and that instance variable would not be available, so you would have some serious problems.
This is the point where you step back and ask yourself what you're really trying to do. Is there any reason why you need to make the default_scope implicitly based on the current user's global_location_id? Could you just just create a regular scope and use that in your controller instead?
class Artifact < ActiveRecord::Base
scope :by_global_location_id, lambda {|id| where(:global_location_id => id) }
end
class ArtifactsController < ApplicationController
def index
@artifacts = Artifact.by_global_location_id(current_user.global_location_id)
end
end
One benefit of this approach is that someone reading your code doesn't have to spend a ton of time tracking down how the default_scope is working.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With