How to Chain Scopes in Rails: Syntax and Examples
In Rails, you can chain scopes by calling multiple
scope methods one after another on an ActiveRecord model. Each scope returns a relation, allowing you to combine conditions like Model.scope1.scope2 to build complex queries cleanly.Syntax
Scopes in Rails are defined as class methods returning an ActiveRecord::Relation. You chain scopes by calling them one after another on a model, each narrowing down the query.
scope :name, -> { where(condition) }defines a scope.- Chaining example:
Model.scope1.scope2applies both conditions. - Each scope returns a relation, so chaining combines them with AND logic.
ruby
class Product < ApplicationRecord scope :available, -> { where(available: true) } scope :priced_over, ->(amount) { where('price > ?', amount) } end # Chaining scopes Product.available.priced_over(100)
Output
Returns all products where available is true AND price is greater than 100
Example
This example shows how to define two scopes and chain them to filter products that are available and cost more than a given price.
ruby
class Product < ApplicationRecord scope :available, -> { where(available: true) } scope :priced_over, ->(amount) { where('price > ?', amount) } end # Usage in Rails console or controller products = Product.available.priced_over(50) products.each do |product| puts "#{product.name} - $#{product.price}" end
Output
Outputs product names and prices for products that are available and priced over 50
Common Pitfalls
Common mistakes when chaining scopes include:
- Defining scopes that do not return a relation, breaking the chain.
- Using scopes that execute queries immediately instead of returning relations.
- Forgetting to pass parameters correctly in scopes.
Always ensure scopes return an ActiveRecord::Relation to keep chaining possible.
ruby
class Product < ApplicationRecord
# Wrong: returns array, breaks chaining
scope :wrong_scope, -> { all.to_a }
# Right: returns relation
scope :correct_scope, -> { all }
end
# Wrong chaining example (raises error)
# Product.wrong_scope.available
# Correct chaining example
Product.correct_scope.availableOutput
The wrong_scope breaks chaining because it returns an array, while correct_scope allows chaining
Quick Reference
| Concept | Description | Example |
|---|---|---|
| Define scope | Create reusable query parts | scope :active, -> { where(active: true) } |
| Chain scopes | Combine multiple scopes | Model.active.recent |
| Return relation | Scopes must return ActiveRecord::Relation | scope :recent, -> { order(created_at: :desc) } |
| Pass parameters | Scopes can accept arguments | scope :priced_over, ->(price) { where('price > ?', price) } |
Key Takeaways
Scopes return ActiveRecord::Relation objects that can be chained to build complex queries.
Always define scopes to return relations, not arrays or other objects.
Chain scopes by calling them one after another on the model, e.g., Model.scope1.scope2.
Scopes can accept parameters to make queries dynamic and reusable.
Chaining scopes combines their conditions with AND logic in the final query.