class method
self.with_scope
Ruby on Rails 3.0.20
Since v2.2.3 Last seen in v3.1.12Signature
self.with_scope(method_scoping = {}, action = :merge, &block)
with_scope lets you apply options to inner block incrementally. It takes a hash and the keys must be :find or :create. :find parameter is Relation while :create parameters are an attributes hash.
class Article < ActiveRecord::Base def self.create_with_scope with_scope(:find => where(:blog_id => 1), :create => { :blog_id => 1 }) do find(1) # => SELECT * from articles WHERE blog_id = 1 AND id = 1 a = create(1) a.blog_id # => 1 end end end
In nested scopings, all previous parameters are overwritten by the innermost rule, with the exception of where, includes, and joins operations in Relation, which are merged.
joins operations are uniqued so multiple scopes can join in the same table without table aliasing problems. If you need to join multiple tables, but still want one of the tables to be uniqued, use the array of strings format for your joins.
class Article < ActiveRecord::Base def self.find_with_scope with_scope(:find => where(:blog_id => 1).limit(1), :create => { :blog_id => 1 }) do with_scope(:find => limit(10)) do all # => SELECT * from articles WHERE blog_id = 1 LIMIT 10 end with_scope(:find => where(:author_id => 3)) do all # => SELECT * from articles WHERE blog_id = 1 AND author_id = 3 LIMIT 1 end end end end
You can ignore any previous scopings by using the with_exclusive_scope method.
class Article < ActiveRecord::Base def self.find_with_exclusive_scope with_scope(:find => where(:blog_id => 1).limit(1)) do with_exclusive_scope(:find => limit(10)) do all # => SELECT * from articles LIMIT 10 end end end end
Note: the :find scope also has effect on update and deletion methods, like update_all and delete_all.
Parameters
-
method_scopingopt = {} -
actionopt = :merge -
blockblock
Source
# File activerecord/lib/active_record/base.rb, line 1097
def with_scope(method_scoping = {}, action = :merge, &block)
method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping)
if method_scoping.is_a?(Hash)
# Dup first and second level of hash (method and params).
method_scoping = method_scoping.dup
method_scoping.each do |method, params|
method_scoping[method] = params.dup unless params == true
end
method_scoping.assert_valid_keys([ :find, :create ])
relation = construct_finder_arel(method_scoping[:find] || {})
if current_scoped_methods && current_scoped_methods.create_with_value && method_scoping[:create]
scope_for_create = if action == :merge
current_scoped_methods.create_with_value.merge(method_scoping[:create])
else
method_scoping[:create]
end
relation = relation.create_with(scope_for_create)
else
scope_for_create = method_scoping[:create]
scope_for_create ||= current_scoped_methods.create_with_value if current_scoped_methods
relation = relation.create_with(scope_for_create) if scope_for_create
end
method_scoping = relation
end
method_scoping = current_scoped_methods.merge(method_scoping) if current_scoped_methods && action == :merge
self.scoped_methods << method_scoping
begin
yield
ensure
self.scoped_methods.pop
end
end
Defined in activerecord/lib/active_record/base.rb line 1097
· View on GitHub
· Improve this page
· Find usages on GitHub
Defined in ActiveRecord::Base