named_scope使用

本文介绍name scope的使用。是文档和其他人的文档的汇编。


本文所用例子:
数据库定义
create table orders (
    id int not null auto_increment,
    name varchar(100) not null,
    email varchar(255) not null,
    address text not null,
    pay_type char(10) not null,
    shipped_at datetime null,
    primary key (id)
);
数据库抽象类
class Order < ActiveRecord::Base
end

简单示例
pp Order.find([22,23,24])  
# 返回一个列表 列表每个元素为 Order类型(也就是继承的ActiveRecord::Base类型)
pp Order.scoped      
# 返回一个 ActiveRecord::Relation类型,继承于ActiveRecord::Base类型
pp Order.find(:first, :conditions => { :name => "ottocho" })  
k = Order.scoped(:conditions => { :name => "ottocho" })
pp k.find(:first)

什么是scope
我理解为接受了约束的数据抽象类对象 它代表的是在此约束下的此数据对象

类型
scope 返回的是ActiveRecord::Relation类型,继承于ActiveRecord::Base类型
find  返回的是一个列表,其中每个元素为定义的数据抽象类型(也是继承于ActiveRecord::Base类型)
他们两个返回的类型不同,但是都可以用each迭代
一个scope就可以利用迭代器了 如果还需要加其他约束条件 有两种做法
otto_order = Order.scoped(:conditions => { :name => "ottocho" })
pp otto_order.find(:first, :conditions => { :address => "guangzhou" })
pp otto_order.scoped(:conditions => { :address => "guangzhou" }).first

具体介绍:
named_scope功能:
在类定义中利用named_scope方法定义的scope,可以很便捷提供检索查询。
数据库抽象类
class Order < ActiveRecord::Base
    named_scope :cash_pay, :conditions => { :pay_type => "cash" }
    named_scope :card_pay, :conditions => { :pay_type => "card" }
    named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
end

示例
 
# 有人写的是"same as" 其实不同
# find返回的是列表(:all)或者单个对象(:first)
Order.cash_pay   # Order.find(:all, :conditions => { :pay_type => "cash" })
Order.card_pay   # Order.find(:all, :conditions => { :pay_type => "card" })
Order.recent     # Order.find(:all, :conditions => ['created_at > ?', 1.week.ago])
# scope可以调用scope(scope返回的relations类型继承于ActiveRecord::Base,显然拥有此方法)
Order.card_pay.recent
# 有人写的是"same as" 其实不同
Order.with_scope(:conditions => { :pay_type => "card" }) do
  Order.find(:all, :conditions => ['created_at > ?', 1.week.ago])
end
# 可以给命名的scope传递参数,使得在运行时指定条件
class Order < ActiveRecord::Base
    named_scope :shipped, lambda { |time_ago| { :conditions => ['shipped_at > ?', time_ago] }
end
Order.shipped 7.days.ago
# 类似于:
# Order.find(:all, :conditions => ['shipped_at > ?', 7.days.ago])
# 可以为定义的scope定义方法
class Order < ActiveRecord::Base
    named_scope :shipped, :conditions => ['created_at > ?', 1.week.ago] do
        def cash_paid
            each { |i| i.update_attribute(:pay_type, "cash") }
        end
    end
end
# 把装好的order设置为cash支付的
Order.shipped.cash_paid
# scoped也是个类方法 匿名定义
card_pay = Order.scoped(:conditions => {:pay_type => "card"})  
recent = Order.scoped(:conditions => ['created_at > ?', 7.days.ago])  
recent_card_pay = recent.card_pay  


以下还有两个很好的范例:
平常我们在使用named_scope时,对于一些sql语句无法表达的集合筛选,总是需要进行select处理,代码读起来就不那么优雅。
named_scope + block 则解决了这个问题。
class User < ActiveRecord::Base
  has_many :stories
 
  named_scope :inactive, :conditions => {:active => false} do
     def latest(number = 1, role = nil)
       collection = role.blank? ? self : self.find_all_by_role(role)
       collection[0, number]
     end
  end  
 
end  
 
# Re-activate all inactive users
User.inactive.latest(5,'admin')
rails中不仅named_scope可以这样写,has_many等关联方法 也可以 带block.例如:
class User < ActiveRecord::Base
  has_many :stories do
    def latest_public
      self.select{|story| story.public? }.first
    end
  end
end
这两个例子中block内的self 都是代表当前集合,所以self其实是对集合做操作。

参考
http://ar.rubyonrails.org/
http://ar.rubyonrails.org/classes/ActiveRecord/Base.html
http://ar.rubyonrails.org/classes/ActiveRecord/NamedScope.html
http://www.cnblogs.com/orez88/articles/1580930.html
https://github.com/wvanbergen/scoped_search
https://github.com/wvanbergen/scoped_search/wiki/search-definition



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值