In short, passing options hash containing :conditions,
:include, :joins, :limit, :offset, :order, :select, :readonly, :group,
:having, :from, :lock to any of the ActiveRecord provided
class methods, is now deprecated.
Going into details, currently ActiveRecord provides the following
finder methods :
- find(id_or_array_of_ids, options)
- find(:first, options)
- find(:all, options)
- first(options)
- all(options)
- update_all(updates, conditions, options)
And the following calculation methods :
- count(column, options)
- average(column, options)
- minimum(column, options)
- maximum(column, options)
- sum(column, options)
- calculate(operation, column, options)
Starting with Rails 3, supplying any option to the methods
above will be deprecated. Support for supplying options will be
removed from Rails 3.2. Moreover, find(:first) and find(:all)
( without any options ) are also being deprecated in favour of first
and all. A tiny little exception here is that count()
will still accept a :distinct option.
The following shows a few example of the deprecated usages :
1
2
3
4
5
|
User.find(:all, :limit => 1)
User.find(:all)
User.find(:first)
User.first(:conditions => {:name => 'lifo'})
User.all(:joins => :items)
|
But the following is NOT
deprecated :
1
2
3
|
User.find(1)
User.find(1,2,3)
User.find_by_name('lifo')
|
Additionally, supplying options hash to named_scope is also
deprecated :
1
2
|
named_scope :red, :conditions => { :colour => 'red' }
named_scope :red, lambda {|colour| {:conditions => { :colour => colour }} }
|
Supplying options hash to with_scope, with_exclusive_scope
and default_scope has also been deprecated :
1
2
3
|
with_scope(:find => {:conditions => {:name => 'lifo'}) { ... }
with_exclusive_scope(:find => {:limit =>1}) { ... }
default_scope :order => "id DESC"
|
Dynamic scoped_by_ are also going to be deprecated :
1
2
|
red_items = Item.scoped_by_colour('red')
red_old_items = Item.scoped_by_colour_and_age('red', 2)
|
New API
ActiveRecord in Rails 3 will have the following new finder methods.
- where (:conditions)
- having (:conditions)
- select
- group
- order
- limit
- offset
- joins
- includes (:include)
- lock
- readonly
- from
1 Value in the bracket ( if different )
indicates the previous equivalent finder option.
Chainability
All of the above methods returns a Relation. Conceptually, a
relation is very similar to an anonymous
named scope. All these methods are defined on the Relation
object as well, making it possible to chain them.
1
2
|
lifo = User.where(:name => 'lifo')
new_users = User.order('users.id DESC').limit(20).includes(:items)
|
You could also apply more finders to the existing relations :
1
2
|
cars = Car.where(:colour => 'black')
rich_ppls_cars = cars.order('cars.price DESC').limit(10)
|
Quacks like a Model
A relation quacks just like a model when it comes to the primary CRUD methods. You could call any of the following
methods on a relation :
- 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?
So the following code examples work as expected :
1
2
3
4
5
6
7
8
|
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
|
Note that calling any of the update or delete/destroy methods would
reset the relation, i.e delete the cached records used for optimizing
methods like relation.size.
Lazy Loading
As it might be clear from the examples above, relations are loaded
lazily – i.e you call an enumerable method on them. This is very similar
to how associations and named_scopes already work.
1
2
|
cars = Car.where(:colour => 'black') # No Query
cars.each {|c| puts c.name } # Fires "select * from cars where ..."
|
This is very useful along side fragment caching. So in your
controller action, you could just do :
1
2
3
|
def index
@recent_items = Item.limit(10).order('created_at DESC')
end
|
And in your view :
1
2
3
4
5
|
<% cache('recent_items') do %>
<% @recent_items.each do |item| %>
...
<% end %>
<% end %>
|
In the above example, @recent_items are loaded on @recent_items.each
call from the view. As the controller doesn’t actually fire any query,
fragment caching becomes more effective without requiring any special
work arounds.
Force loading – all, first & last
For the times you don’t need lazy loading, you could just call all
on the relation :
|
cars = Car.where(:colour => 'black').all
|
It’s important to note that all returns an Array
and not a Relation. This is similar to how things work in Rails
2.3 with named_scopes and associations.
Similarly, first and last will always return an ActiveRecord
object ( or nil ).
1
2
3
|
cars = Car.order('created_at ASC')
oldest_car = cars.first
newest_car = cars.last
|
named_scope -> scopes
Using the method named_scope is deprecated in Rails 3.0.
But the only change you’ll need to make is to remove the “named_” part.
Supplying finder options hash will be deprecated in Rails 3.1.
named_scope have now been renamed to just scope.
So a definition like :
1
2
3
4
|
class Item
named_scope :red, :conditions => { :colour => 'red' }
named_scope :since, lambda {|time| {:conditions => ["created_at > ?", time] }}
end
|
Now becomes :
1
2
3
4
|
class Item
scope :red, :conditions => { :colour => 'red' }
scope :since, lambda {|time| {:conditions => ["created_at > ?", time] }}
end
|
However, as using options hash is going to be deprecated in 3.1, you
should write it using the new finder methods :
1
2
3
4
|
class Item
scope :red, where(:colour => 'red')
scope :since, lambda {|time| where("created_at > ?", time) }
end
|
Internally, named scopes are built on top of Relation,
making it very easy to mix and match them with the finder methods :
1
2
3
|
red_items = Item.red
available_red_items = red_items.where("quantity > ?", 0)
old_red_items = Item.red.since(10.days.ago)
|
Model.scoped
If you want to build a complex relation/query, starting with a blank
relation, Model.scoped is what you would use.
1
2
3
|
cars = Car.scoped
rich_ppls_cars = cars.order('cars.price DESC').limit(10)
white_cars = cars.where(:colour => 'red')
|
Speaking of internals, ActiveRecord::Base has the following
delegations :
1
2
3
|
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
|
The above might give you a better insight on how ActiveRecord is
doing things internally. Additionally, dynamic finder methods find_by_name,
find_all_by_name_and_colour etc. are also delegated to Relation.
with_scope and with_exclusive_scope
with_scope and with_exclusive_scope are now
implemented on top of Relation as well. Making it possible to
use any relation with them :
1
2
3
|
with_scope(where(:name => 'lifo')) do
...
end
|
Or even use a named scope :
1
2
3
|
with_exclusive_scope(Item.red) do
...
end
|
That’s all. Please open a lighthouse
ticket if you find a bug or have a patch for an improvement!
UPDATE 1 : Added
information about deprecating scoped_by_ dynamic methods.
UPDATE 2 : Added
information about deprecating default_scope with finder
options.
分享到:
相关推荐
Rails3的ActiveRecord 查询API.doc
Rails/ActiveRecord 精简版 ![预览] [预览]: ./docs/preview.png 描述 Rails/ActiveRecord Lite 是流行的 Ruby on Rails 框架的精简版。 这个应用程序的目的是更深入地了解 Rails 和 ActiveRecord 的工作原理,特别...
userstamp, 这个 Rails 插件扩展ActiveRecord Userstamp插件( v-2.0 )概述Userstamp插件扩展了 ActiveRecord::Base,以添加对'创建者','更新程序'和'deleter'属性的自动更新。 它是基于 ActiveRecord::Timesta
数组元素支持对象:ActiveRecord,Mongid,哈希。 在您的Gemfile中: gem 'to_xls-rails' # Last officially released gem # gem "to_xls-rails", :git => "git://github....
主要介绍了Ruby on Rails中的ActiveRecord编程指南,作者对编写ActiveRecord的通用习惯给出了建议,需要的朋友可以参考下
充当可憎的角色(又称“喜欢的”角色) Acts as Votable是专门为Rails / ActiveRecord模型编写的Ruby Gem。 该宝石的主要目标是: 允许对任何模型进行投票,例如喜欢/不喜欢,赞成/反对等。 允许在任意范围内对任何...
Pro ActiveRecord Databases with Ruby and Rails.pdf
没有Rails的ActiveRecord 只是在没有Rails的情况下使用ActiveRecord迁移的简单示例您可以执行的任务: rake db:create rake db:migrate rake db:dropRails 5+的注意事项请注意,即使使用Rails 5,您也需要rake db:...
工作流库的 ActiveRecord/Rails 集成 工作流活动记录的主要+次要版本基于最旧的兼容 ActiveRecord API。 要在 Rails/ActiveRecord 4.1、4.2、5.0、5.1、5.2、6.0、6.1 中使用 ,请使用: gem 'workflow-...
在要启用哈希值的ActiveRecord模型中包括Hashid Rails。 class Model < ActiveRecord :: Base include Hashid :: Rails end 继续使用Model#find输入hashid或常规的'ol id。 @person = Person . find ( params...
《Rails之道》按照Rails的各个子系统进行组织编排,分别介绍了Rails的环境、初始过程、配置和日志记录,Rails的分配器、控制器、页面生成和路由,REST、资源和Rails,ActiveRecord的基础、关联、验证和高级技巧,...
rales_engine 在这个项目中,我们将使用 Rails 和 ActiveRecord 来构建一个公开 SalesEngine 数据模式的 JSON API。
ActiveRecord模型Rails实验室 目标 手动创建迁移 手动创建模型 建立模型实例方法 建立模型 您可以在spec/models目录中找到此应用程序的测试套件,并使用以下命令运行它们: bundle exec rspec 。 该实验室进行测试以...
Active Record是Rails用来管理应用程序模型方面的内置ORM。 什么是ORM? ORM是一个对象关系映射系统,从本质上讲,这是一个模块,它使您的应用程序能够以方法驱动的结构来管理数据。 这意味着您可以利用方法而不是...
this unique book approaches Rails development from the outer layer: the application interface. You'll learn how to create something visible with Rails before reaching the more difficult database ...
Rails3教程系列 DRY(Dont Repeat Yourself) DRY(Dont Repeat Yourself) DRY(Dont Repeat Yourself) DRY(Dont Repeat Yourself) DRY(Dont Repeat Yourself) DRY(Dont Repeat Yourself) DRY(Dont Repeat Yourself) DRY...
The Rails™ 3 Way is a comprehensive resource that digs into the new features in Rails 3 and perhaps more importantly, the rationale behind them. —Yehuda Katz, Rails Core The Bible for Ruby on ...
ActiveRecordLite 在这个项目中,我构建了自己的 ActiveRecord 精简版。 该项目的目的是了解 ActiveRecord 的实际工作原理:您的 ActiveRecord 世界如何转换为 SQL。
Apress Pro ActiveRecord Databases with Ruby and Rails.pdf <br>好书一本
Windows7_Cygwin_Git_RVM_Ruby1.9.3_Rails3_MongoD B_Nginx_Unicorn_Rspec_Guard_Spork(2-Ruby on Rails3 安装配置