I have a Rails 3 project. With Rails 3 came Arel and the ability to reuse one scope to build another. I am wondering if there is a way to use scopes when defining a relationship (e.g. a "has_many").
I have records which have permission columns. I would like to build a default_scope that takes my permission columns into consideration so that records (even those accessed through a relationship) are filtered.
Presently, in Rails 3, default_scope (including patches I've found) don't provide a workable means of passing a proc (which I need for late variable binding). Is it possible to define a has_many into which a named scope can be passed?
The idea of reusing a named scope would look like:
Orders.scope :my_orders, lambda{where(:user_id => User.current_user.id)} has_many :orders, :scope => Orders.my_orders
Or implicitly coding that named scope in the relationship would look like:
has_many :orders, :scope => lambda{where(:user_id => User.current_user.id)}
I'm simply trying to apply default_scope with late binding. I would prefer to use an Arel approach (if there is one), but would use any workable option.
Since I am referring to the current user, I cannot rely on conditions that aren't evaluated at the last possible moment, such as:
has_many :orders, :conditions => ["user_id = ?", User.current_user.id]
Scopes are used to assign complex ActiveRecord queries into customized methods using Ruby on Rails. Inside your models, you can define a scope as a new method that returns a lambda function for calling queries you're probably used to using inside your controllers.
They essentially do the same thing, the only difference is what side of the relationship you are on. If a User has a Profile , then in the User class you'd have has_one :profile and in the Profile class you'd have belongs_to :user .
Active Record is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database.
I suggest you take a look at "Named scopes are dead"
The author explains there how powerful Arel is :)
I hope it'll help.
As some comments state, the difference is now a matter of personal taste.
However, I still personally recommend to avoid exposing Arel's scope to an upper layer (being a controller or anything else that access the models directly), and doing so would require:
How about association extensions?
class Item < ActiveRecord::Base has_many :orders do def for_user(user_id) where(user_id: user_id) end end end Item.first.orders.for_user(current_user)
UPDATE: I'd like to point out the advantage to association extensions as opposed to class methods or scopes is that you have access to the internals of the association proxy:
proxy_association.owner returns the object that the association is a part of. proxy_association.reflection returns the reflection object that describes the association. proxy_association.target returns the associated object for belongs_to or has_one, or the collection of associated objects for has_many or has_and_belongs_to_many.
More details here: http://guides.rubyonrails.org/association_basics.html#association-extensions
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