Posted over 7 years ago. Visible to the public. Repeats.

Merging two arbitrary ActiveRecord scopes

Rails 3+ allows you to join two scopes from arbitrary sources by calling the merge method:

scope1 = User.where(:email => '') scope2 = User.where(:first_name => 'hans') merged_scope = scope1.merge(scope2)

merged_scope.to_a will now trigger a query for the combined scope chain:

SELECT `users`.* FROM `users` WHERE `users`.`email` = '' AND `users`.`first_name` = 'hans'

If you are joining two models, you can also merge scopes for different models.

Also note that #merge has a bug in Rails 3.x where merging two scopes with conditions on the same column will discard all by the last condition. This bug is fixed in our forks.

This is nice for resource_controller and Consul

If you are using resource_controller with Consul, merging allows you to further filter your controller's end_of_association_chain by a Consul power. This is useful when you have a nested controller and want to take advantage of the implicit end_of_association_chain, but still want to authorize access:

class DocumentsController < ApplicationController resource_controller belongs_to :deal private def end_of_association_chain super.merge(current_power.documents) end end

If you now go to /deals/5/documents you can only access documents which both belong to the deal with the id 5, and are accessible according to your power.

Growing Rails Applications in Practice
Check out our new e-book:
Learn to structure large Ruby on Rails codebases with the tools you already know and love.

Owner of this card:

Henning Koch
Last edit:
about 1 month ago
by Dominik Schöler
chain, rails, relation
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Henning Koch to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more