class method self.with_scope

Ruby on Rails 2.3.18

Since v2.2.3 Last seen in v3.1.12

Available in: v2.2.3 v2.3.18 v3.0.20 v3.1.12

Signature

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_scoping opt = {}
action opt = :merge
block block
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

Type at least 2 characters to search.

↑↓ navigate · open · esc close