class method
self.with_scope
Ruby on Rails 2.3.18
Since v2.2.3 Last seen in v3.1.12Signature
self.with_scope(method_scoping = {}, action = :merge, &block)
Scope parameters to method calls within the block. Takes a hash of method_name => parameters hash. method_name may be :find or :create. :find parameters may include the :conditions, :joins, :include, :offset, :limit, and :readonly options. :create parameters are an attributes hash.
class Article < ActiveRecord::Base def self.create_with_scope with_scope(:find => { :conditions => "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 :conditions, :include, and :joins options in :find, which are merged.
:joins options 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 => { :conditions => "blog_id = 1", :limit => 1 }, :create => { :blog_id => 1 }) do
with_scope(:find => { :limit => 10 })
find(:all) # => SELECT * from articles WHERE blog_id = 1 LIMIT 10
end
with_scope(:find => { :conditions => "author_id = 3" })
find(: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 => { :conditions => "blog_id = 1", :limit => 1 }) do
with_exclusive_scope(:find => { :limit => 10 })
find(: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 2132
def with_scope(method_scoping = {}, action = :merge, &block)
method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping)
# Dup first and second level of hash (method and params).
method_scoping = method_scoping.inject({}) do |hash, (method, params)|
hash[method] = (params == true) ? params : params.dup
hash
end
method_scoping.assert_valid_keys([ :find, :create ])
if f = method_scoping[:find]
f.assert_valid_keys(VALID_FIND_OPTIONS)
set_readonly_option! f
end
# Merge scopings
if [:merge, :reverse_merge].include?(action) && current_scoped_methods
method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)|
case hash[method]
when Hash
if method == :find
(hash[method].keys + params.keys).uniq.each do |key|
merge = hash[method][key] && params[key] # merge if both scopes have the same key
if key == :conditions && merge
if params[key].is_a?(Hash) && hash[method][key].is_a?(Hash)
hash[method][key] = merge_conditions(hash[method][key].deep_merge(params[key]))
else
hash[method][key] = merge_conditions(params[key], hash[method][key])
end
elsif key == :include && merge
hash[method][key] = merge_includes(hash[method][key], params[key]).uniq
elsif key == :joins && merge
hash[method][key] = merge_joins(params[key], hash[method][key])
else
hash[method][key] = hash[method][key] || params[key]
end
end
else
if action == :reverse_merge
hash[method] = hash[method].merge(params)
else
hash[method] = params.merge(hash[method])
end
end
else
hash[method] = params
end
hash
end
end
self.scoped_methods << method_scoping
begin
yield
ensure
self.scoped_methods.pop
end
end
Defined in activerecord/lib/active_record/base.rb line 2132
· View on GitHub
· Improve this page
· Find usages on GitHub
Defined in ActiveRecord::Base