activerecord查询语法for rails3
首页 | 注册 | 登录 | 用户群体 | 关于我们 Rss Feed
Guides.rubyonrails.org 资讯导航 敏捷开发最佳实践 问题交流 书籍资料 职位招聘 线下活动
Ruby on Rails 敏捷开发最佳实践分享
分享你的敏捷开发最佳实践,为rails社区的枝繁叶茂做出自己的贡献.
Agile Web Development With Rails Fourth Edition
Rails3的ActiveRecord 查询API
2 次投票
jerry 分享于 about 1 month 前, 3 条回复 , 208 次浏览
Share |
Rails3ActiveRecord中修改了较多的代码,很多以前Rails2中普遍使用的用法在Rails3中已经不推荐使用或者已经被移除, 所以此文让大家知道如何去写好Rails3的代码。 本文是翻译自Pratik Naik博客的一篇文章。
众所周知,很多rails2的active record查询方法在rails3众已经不推荐使用,也就是说,过时了。那么,哪些写法在rails3.1众已经不推荐使用了呢?
这些不推荐使用的写法在rails3.1 release版中依然有效,但是将会在rails3.2中全面的移除,考虑到牵涉了比较多的代码修改,所以将会有一个官方的插件来支持他们。
简而言之,通过包含hash的任何ActiveRecord的类方法,都已经不推荐了,比如:
:conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :having, :from, :lock目前ActiveRecord提供了以下finder方法:
find(id_or_array_of_ids, options) find(:first, options) find(:all, options) first(options) all(options) update_all(updates, conditions, options)还有以下的计算方法:
count(column, options) average(column, options) minimum(column, options) maximum(column, options) sum(column, options) calculate(operation, column, options)进入rails3的世界,以上的方法都是不推荐使用的。这些方法将会在rails3.2中完整的移除。此外,find(:first) , find(:all) 也已经不推荐使用了,小小的例外是 count()方法依然接受 :distinct 参数。
下面是一些在 rails3中过时用法的例子:
User.find(:all, :limit => 1) User.find(:all) User.find(:first) User.first(:conditions => {:name => 'lifo'}) User.all(:joins => :items)但是以下的用法还是推荐使用的:
User.find(1) User.find(1,2,3) User.find_by_name('lifo')此外,在rails2中使用率相当大的named_scope 也已经不推荐了
named_scope :red, :conditions => { :colour => 'red' } named_scope :red, lambda {|colour| {:conditions => { :colour => colour }} }with_scope, with_exclusive_scope 和 default_scope 也不推荐使用。
with_scope(:find => {:conditions => {:name => 'lifo'}) { ... } with_exclusive_scope(:find => {:limit =>1}) { ... } default_scope :order => "id DESC"动态 scoped_by_ 也将会废弃。
red_items = Item.scoped_by_colour('red') red_old_items = Item.scoped_by_colour_and_age('red', 2)新的API
Rails3的 ActiveRecord 有以下的finder方法:
where (:conditions) having (:conditions) select group order limit offset joins includes (:include) lock readonly fromChainability
上述的方法都会返回一个关系,从概念上讲,这种关系其实都是一个 named scope类型。所有的这些方法都很好的在关系对象中定义了。
lifo = User.where(:name => 'lifo') new_users = User.order('users.id DESC').limit(20).includes(:items)你可以在现有的关系中应用更多的finder方法
cars = Car.where(:colour => 'black') rich_ppls_cars = cars.order('cars.price DESC').limit(10)Quacks like a Model
Quacks relation 在涉及到主要的CRUD方法的时候其实就像一个模型,你可以调用以下任何方法。
new(attributes) create(attributes) create!(attributes) find(id_or_array) destroy(id_or_array) destroy_all delete(id_or_array) delete_all update(ids, updates) update_all(updates) exists?那么,下面的代码是我们所希望看到的:
red_items = Item.where(:colour => 'red') red_items.find(1) item = red_items.new item.colour #=> 'red' red_items.exists? #=> true red_items.update_all :colour => 'black' red_items.exists? #=> false请注意,调用任何的CRUD方法将会重置关系,也就是说,将会删除记录的缓存,例如 relation.size。
Lazy Loading 延迟加载
我们可能会从上面的例子清楚的知道,关系是延迟加载的,也就是调用了一个枚举的方法,这和 associations 和 named_scopes 是如何协作的比较相似。
cars = Car.where(:colour => 'black') # No Query cars.each {|c| puts c.name } # Fires "select * from cars where ..."这是非常有用的片段缓存,在你的controller,可以这么写
def index @recent_items = Item.limit(10).order('created_at DESC') end然后在你的view中这么写
<% cache('recent_items') do %> <% @recent_items.each do |item| %> ... <% end %> <% end %>在上述例子中,@recent_items 在视图中调用了@recent_items.each后才被加载,作为控制器实际上并没有触发任何查询,在不需要任何特殊工作的时候,片段缓存变得非常有效。
Force loading – all, first & last
有时候,你可能不需要延迟加载,那么,你可以强制进行加载。
cars = Car.where(:colour => 'black').all需要注意的是.all后返回的是一个数组,而不是一个关系。这和rails 2.3下 named_scopes and associations是相类似的。
同样,first 和last 总是会返回一个 ActiveRecord对象或者nil.
cars = Car.order('created_at ASC') oldest_car = cars.first newest_car = cars.lastnamed_scope -> scopes
named_scope在Rails3.0中已经不推荐使用了,你只要将 “named_”这部分去掉就可以了。也就是说 named_scope已经被重新命名成scope了。
老的写法是:
class Item named_scope :red, :conditions => { :colour => 'red' } named_scope :since, lambda {|time| {:conditions => ["created_at > ?", time] }} end新的写法是:
class Item scope :red, :conditions => { :colour => 'red' } scope :since, lambda {|time| {:conditions => ["created_at > ?", time] }} end然而,以上使用的conditions的hash将会在Rails3.1中移除,所以我们需要这么写:
class Item scope :red, where(:colour => 'red') scope :since, lambda {|time| where("created_at > ?", time) } end在内部,命名规范是建立在关系之上的,使它更简单的使用和混用finder方法。
red_items = Item.red available_red_items = red_items.where("quantity > ?", 0) old_red_items = Item.red.since(10.days.ago)Model.scoped
如果你想建立一个复杂的关系查询,从一个空白的关系出发,那么Model.scoped将会是你用到的。
cars = Car.scoped rich_ppls_cars = cars.order('cars.price DESC').limit(10) white_cars = cars.where(:colour => 'red')说到内部,ActiveRecord::Base有以下delegations:
delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped delegate :select, :group, :order, :limit, :joins, :where, :preload, :eager_load, :includes, :from, :lock, :readonly, :having, :to => :scoped delegate :count, :average, :minimum, :maximum, :sum, :calculate, :to => :scoped以上的可能会给你一个更好的方向去理解ActiveRecord::Base类内部是如何工作的。包括动态的finder方法,比如 find_by_name. find_all_by_name_and_colour 等。
with_scope and with_exclusive_scope
with_scope和with_exclusive_scope 现在已被较好的实施在了关系之上:
with_scope(where(:name => 'lifo')) do ... end或者使用一个 named scope:
with_exclusive_scope(Item.red) do ... end查看更多关于activerecord查询语法for rails3的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did43602