When to use association extensions vs named scopes?
Association extensions are very useful for creating custom methods for creating, updating, etc (not necessarily finding).
Because you have access to the proxy_owner, proxy_reflection, proxy_target, you have a nice hook into the relationship.
Check out the Association Extension section of the Rails docs:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
Rails 4: how to use named scope with has_many associations
I believe it should read like this in Rails 4:
scope :live, -> { where(is_deleted: 0, sent_to_api: 1) }
The rails 4 docs and all examples in it show you passing in a callable object to the scope to ensure it gets called each time. If it doesn't work like this try implementing it as a class method and see how that works out for you.
http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html
How do you scope ActiveRecord associations in Rails 3?
I suggest you take a look at "Named scopes are dead"
The author explains there how powerful Arel is :)
I hope it'll help.
EDIT #1 March 2014
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:
- Create a scope, and expose it thru a method in your model. That method would be the one you expose to the controller;
- If you never expose your models to your controllers (so you have some kind of service layer on top of them), then you're fine. The anti-corruption layer is your service and it can access your model's scope without worrying too much about how scopes are implemented.
When to and when not to use lambda for named scopes?
In Rails 4
Always use lambda. The second syntax is incorrect in Rails 4 and will throw an error (undefined method 'call' for ActiveRecord::Relation)
# activerecord/lib/active_record/scoping/named.rb
scope = all.scoping { body.call(*args) }
In Rails 3
scope
method behaves same way in both cases - it created a new class method called credits
. Difference is that when given a lambda, it evaluates this lambda every time this new method is called to get the scope, while when given relation, it just uses what has been passed.
# activerecord/lib/active_record/named_scope.rb
options = scope_options.respond_to?(:call) ? scope_options.call(*args) : scope_options
In this case, lambda always return exactly same relation, so no difference will be noted.
Lambda notation is used usually to pass arguments to the scope:
scope :before, lambda {|date| where.created_at < date}
Which then can be used like:
Model.before(1.day.ago)
This is naturally impossible to write without the lambda.
Rails Scoped has many through has many with scope
You need to actually define a second association:
class Project < ApplicationRecord
has_many :issues
has_many :open_issues,
-> { where(status: 'open') },
class_name: 'Issue'
has_many :assignees, through: :open_issues
end
A has_many through:
association just takes the name of another association that it joins through. You cannot define an association that goes through an association extension which you are incorrectly referring to as a scope.
A scope is really just a class method which can be called on any relation (since it proxies to the class) while association extensions can only be called on association proxies.
If you want to actually create a scoped association, you need to pass a callable such as a lambda.
has_many :open_issues,
-> { where(status: 'open') },
class_name: 'Issue'
This really just applies a set of filters directly to the association itself.
something.xs.ys.for(z).bs
Is not actually compatible with how associations actually work in Rails. Associations are not callable on relations or association proxy objects - only on records themselves.
Use scope of a belongs_to association to scope in the first model - Ruby on Rails
If you are just looking to merge in the scope then
class Child < ApplicationRecord
belongs_to :parent
scope :with_great_parent, -> (min_grade) {joins(:parent).merge(Parent.great(min_grade))}
end
should handle this for you. The SQL generated will be similar to
SELECT *
FROM children
INNER JOIN parents ON children.parent_id = parents.id
WHERE
parents.grade > --Whatever value you pass as min_grade
See ActiveRecord::SpawnMethods#merge
for more information
Injecting a scope through an association extension in Rails 2.3.17
I ended up not finding a way to work around this. In the end I had to avoid the bug in the specific situation in which it occurred. Fortunately it was only in a couple of places in the app.
Rails named scope not working on association
Rails scopes are just class methods. Internally Active Record converts a scope into a class method. So, when you define this scope:
scope :payment_methods_for_seller, ->(seller) { joins(:seller_buyer_payment_methods).where(:seller => seller) }
You can consider this payment_methods_for_seller
method as a class method of Buyer
class. That's why you get this error:
NoMethodError: undefined method `payment_methods_for_seller' for Buyer:0x000001028e6d88
when you called the class method on an object of the Buyer
class:
a_buyer.payment_methods_for_seller a_seller
You can't call a scope/class method on an object of the class. You can call it on the class itself:
Buyer.payment_methods_for_seller
The 2nd example works because in that case you defined the payment_methods_for_seller
method as an instance method of the Buyer
class.
Hope this clears your confusion.
Instead of using scopes you can get the relevant records through the seller_buyer_methods association:
a_buyer.seller_buyer_payment_methods.where( :seller => a_seller )
Here is a nice blog post on Active Record scopes vs class methods which will give you some more interesting information on this topic.
Related Topics
Why Does Ruby Release Memory Only Sometimes
How to Set Correct Ruby Version in Gem Environment
When to Use Association Extensions VS Named Scopes
How to Write Down the Rspec to Test Rescue Block
Rails: Parameterfilter::Compiled_Filter Tries to Dup Symbol
Find Keep Duplicates in Ruby Hashes
Ncurses to External Shell and Back Messing with Keys
How to Start Ruby 1.9 Without Rubygems
Detect When a Devise Session Expires
Ruby: Why Does '#Hash' Need to Overridden Whenever '#Eql' Is Overridden
Sort an Array in Ruby Ignoring Articles ("The", "A", "An")
Validate Japanese Character in Active Record Callback
Using Local Variables in Define_Method
Exec Onlyif Registry Value Is Not Present
Changing Http Status Message Using Sinatra