诗歌rails之with_scope(method_scoping = {}, action = :merge) {|| ...}

with_scope后面可以跟一个hash {方法名=>参数hash},方法名可以是:find和:create,:find的参数hash包含:conditions, :joins, :include, :offset,:limit, and :readonly options. :create后的参数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

嵌套时:conditions, :include,:joins 会被merge

  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

也可以使用with_exclusive_scope 忽略之前的所以范围定义

  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.

with_scope源码:
      # File vendor/rails/activerecord/lib/active_record/base.rb, line 2089
2089:         def with_scope(method_scoping = {}, action = :merge, &block)
2090:           method_scoping = method_scoping.method_scoping if method_scoping.respond_to?(:method_scoping)
2091: 
2092:           # Dup first and second level of hash (method and params).
2093:           method_scoping = method_scoping.inject({}) do |hash, (method, params)|
2094:             hash[method] = (params == true) ? params : params.dup
2095:             hash
2096:           end
2097: 
2098:           method_scoping.assert_valid_keys([ :find, :create ])
2099: 
2100:           if f = method_scoping[:find]
2101:             f.assert_valid_keys(VALID_FIND_OPTIONS)
2102:             set_readonly_option! f
2103:           end
2104: 
2105:           # Merge scopings
2106:           if [:merge, :reverse_merge].include?(action) && current_scoped_methods
2107:             method_scoping = current_scoped_methods.inject(method_scoping) do |hash, (method, params)|
2108:               case hash[method]
2109:                 when Hash
2110:                   if method == :find
2111:                     (hash[method].keys + params.keys).uniq.each do |key|
2112:                       merge = hash[method][key] && params[key] # merge if both scopes have the same key
2113:                       if key == :conditions && merge
2114:                         if params[key].is_a?(Hash) && hash[method][key].is_a?(Hash)
2115:                           hash[method][key] = merge_conditions(hash[method][key].deep_merge(params[key]))
2116:                         else
2117:                           hash[method][key] = merge_conditions(params[key], hash[method][key])
2118:                         end
2119:                       elsif key == :include && merge
2120:                         hash[method][key] = merge_includes(hash[method][key], params[key]).uniq
2121:                       elsif key == :joins && merge
2122:                         hash[method][key] = merge_joins(params[key], hash[method][key])
2123:                       else
2124:                         hash[method][key] = hash[method][key] || params[key]
2125:                       end
2126:                     end
2127:                   else
2128:                     if action == :reverse_merge
2129:                       hash[method] = hash[method].merge(params)
2130:                     else
2131:                       hash[method] = params.merge(hash[method])
2132:                     end
2133:                   end
2134:                 else
2135:                   hash[method] = params
2136:               end
2137:               hash
2138:             end
2139:           end
2140: 
2141:           self.scoped_methods << method_scoping
2142:           begin
2143:             yield
2144:           ensure
2145:             self.scoped_methods.pop
2146:           end
2147:         end
posted @ 2009-07-07 11:18  麦飞  阅读(837)  评论(0编辑  收藏  举报