something about with_scope

阅读更多

今天看了一点关于with_scope的知识,有点感觉,写点东西

with_scope 与 named_scope 没有关系,named_scope 是依赖于with_scope工作的。

1、with_scope

with_scope是给一个model添加一个scope来扩展功能

def self.all_male
  with_scope(:find => {:conditions => "gender = 'm'"}) do
    all_active
  end
end

def self.all_active
  with_scope(:find => {:conditions => "status = 'active'"}) do
    find(:first)
  end
end

# User.all_active
# SELECT * FROM "users" WHERE (status = 'active') LIMIT 1

# User.all_male
# SELECT * FROM "users" WHERE ((gender = 'm') AND (status = 'active')) LIMIT 1

 named_scope就是运用with_scope的这种特性来将多个name_scope形成一个query

2、学习编写自己的named_scope

module ActiveRecord
  module MynamedScope
    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods
      def mynamed_scope(name,options = {})
        puts "name is #{name}"
      end
    end

  end
end
ActiveRecord::Base.send(:include, ActiveRecord::MynamedScope)


class User < ActiveRecord::Base
  mynamed_scope :active, :conditions => {:status =>  'active'}
  mynamed_scope :male, :conditions => {:gender => 'm'}
end

 我们就可以通过

 

User.active
User.male
User.active.male
User.male.active

 得到正确的返回结果。

最后结果

module ActiveRecord
  module MynamedScope
    def self.included(base)
      base.extend ClassMethods
    end

    module ClassMethods

      def myscopes
        read_inheritable_attribute(:myscopes) || write_inheritable_attribute(:myscopes, {})
      end

      def mynamed_scope(name,options = {})
        name = name.to_sym
        myscopes[name] = lambda { |proxy_scope| Scope.new(proxy_scope,options) }

        (class << self; self end).instance_eval do
          define_method name do
            myscopes[name].call(self) 
          end
        end
      end

      class Scope
        attr_reader :proxy_scope, :proxy_options
        delegate :with_scope,  :to => :proxy_scope                
        def initialize(proxy_scope, options)
          @proxy_scope, @proxy_options = proxy_scope, options
        end

        def inspect
          load_found
        end

        def load_found
          find(:all)
        end

        def method_missing(method, *args, &block)
          if proxy_scope.myscopes.include?(method)
            proxy_scope.myscopes[method].call(self)
          else
            with_scope :find => proxy_options do
              proxy_scope.send(method,*args)
            end
          end
        end

      end # end of class Scope

    end # end of module ClassMethods

  end # endof module MynamedScope
end
ActiveRecord::Base.send(:include, ActiveRecord::MynamedScope)

class User < ActiveRecord::Base
  mynamed_scope :active, :conditions => {:status =>  'active'}
  mynamed_scope :male, :conditions => {:gender => 'm'}
end

 原文章参考地址:http://www.neeraj.name/blog/articles/751-under-the-hood-how-named_scope-works

 

 

文章二、

It looks like Nick Kallen’s wildly popular has_finder plugin will be making its way into Rails 2.x in the form of named_scope . Observe:

All the goodness you’ve come to love in has_finder is now available as named_scope – plus you get some extra goodies too. User.all is given to you for free as an alias for User.find(:all) .

class User < ActiveRecord::Base
  named_scope :active, :conditions => {:active => true}
  named_scope :inactive, :conditions => {:active => false}
  named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
end

# Standard usage
User.active    # same as User.find(:all, :conditions => {:active => true})
User.inactive # same as User.find(:all, :conditions => {:active => false})
User.recent   # same as User.find(:all, :conditions => ['created_at > ?', 1.week.ago])

# They're nest-able too!
User.active.recent
  # same as:
  # User.with_scope(:conditions => {:active => true}) do
  #   User.find(:all, :conditions => ['created_at > ?', 1.week.ago])
  # end
 

Advanced

For those with more discriminating needs, don’t forget some of these has_finder tidbits:

Passing Arguments

Pass in arguments to your named scopes to specify conditions (or other props) at run-time.

class User < ActiveRecord::Base
  named_scope :registered, lambda { |time_ago| { :conditions => ['created_at > ?', time_ago] }
end

User.registered 7.days.ago # same as User.find(:all, :conditions => ['created_at > ?', 7.days.ago])
 

Named Scope Extensions

Extend named scopes (in a similar fashion to association extensions ).

class User < ActiveRecord::Base
  named_scope :inactive, :conditions => {:active => false} do
    def activate
      each { |i| i.update_attribute(:active, true) }
    end
  end
end

# Re-activate all inactive users
User.inactive.activate
 

Anonymous Scopes

You can also pass around scopes as first class objects using scoped (a named scoped provided to you for free) as a way to build hairy queries on the fly.

# Store named scopes
active = User.scoped(:conditions => {:active => true})
recent = User.scoped(:conditions => ['created_at > ?', 7.days.ago])

# Which can be combined
recent_active = recent.active

# And operated upon
recent_active.each { |u| ... }
 

named_scope is a truly great feature. If you haven’t started using it yet, do so. You won’t know how you lived without it. Major thanks goes out to Nick.

你可能感兴趣的:(ActiveRecord,Rails,Blog,工作)