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.
分享到:
相关推荐
Ruby on Rails:ActiveRecord模型操作教程.docx
Rails 3.1 及以后版本的 ...总的来说,Rails 3 的 ActiveRecord 查询API引入了一种更模块化、更面向对象的方式来处理数据库查询,提高了代码的可读性和可维护性。开发者应逐渐适应并采用新的API,以充分利用其优势。
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
该项目是采用Java语言实现的Ruby on Rails ActiveRecord设计理念的源码,总计包含46个文件,其中40个为Java源文件,其他包括Git忽略文件、许可证、Markdown文件、XML配置文件、数据库方言和驱动文件等。该设计旨在...
### ActiveRecord在Ruby与Rails中的高级应用 #### 一、引言 《Pro ActiveRecord Databases with Ruby and Rails》这本书深入探讨了如何使用ActiveRecord框架来高效地处理Ruby on Rails中的数据库操作。本书由Kevin ...
充当可憎的角色(又称“喜欢的”角色) Acts as Votable是专门为Rails / ActiveRecord模型编写的Ruby Gem。 该宝石的主要目标是: 允许对任何模型进行投票,例如喜欢/不喜欢,赞成/反对等。 允许在任意范围内对任何...
没有Rails的ActiveRecord 只是在没有Rails的情况下使用ActiveRecord迁移的简单示例您可以执行的任务: rake db:create rake db:migrate rake db:dropRails 5+的注意事项请注意,即使使用Rails 5,您也需要rake db:...
### Ruby on Rails中的ActiveRecord编程指南 #### 一、引言 在Ruby on Rails框架中,ActiveRecord是一种用于实现数据库抽象层的对象关系映射(ORM)工具。它为开发人员提供了一种简单而强大的方式来处理数据库记录...
工作流库的 ActiveRecord/Rails 集成 工作流活动记录的主要+次要版本基于最旧的兼容 ActiveRecord API。 要在 Rails/ActiveRecord 4.1、4.2、5.0、5.1、5.2、6.0、6.1 中使用 ,请使用: gem 'workflow-...
### Rails3教程知识点详解 #### 一、Rails3简介与核心原则 **Rails3**是Ruby on Rails框架的一个重要版本,它对之前的版本进行了大量的改进和优化,使其更加强大和灵活。Rails3的核心设计理念围绕着几个关键的概念...
在要启用哈希值的ActiveRecord模型中包括Hashid Rails。 class Model < ActiveRecord :: Base include Hashid :: Rails end 继续使用Model#find输入hashid或常规的'ol id。 @person = Person . find ( params...
5. **生成器**:Rails提供了一系列命令行生成器,如`rails new`创建新项目,`rails generate controller`创建控制器,`rails generate model`创建模型等,这能快速构建应用结构。 6. **ActiveRecord查询接口**:...
《Rails 3 in Action》是2011年由Ryan Bigg撰写的一本关于Ruby on Rails框架的权威指南,专门针对当时最新的Rails 3.1版本进行了深入解析。这本书旨在帮助开发者充分利用Rails 3.1的强大功能,提升Web应用开发的效率...
你将学习ActiveRecord,它是Rails提供的一个ORM(Object-Relational Mapping)工具,允许你用Ruby代码操作数据库。 在控制器(Controllers)部分,你将学习如何处理HTTP请求,组织应用逻辑,并将数据传递给视图...
Ruby on Rails 3 是一个基于Ruby编程语言的开源Web应用程序框架,它遵循MVC(Model-...提供的文档如"Ruby192和Rails3.0.3的新征程.doc"和"rails3入门教程.pdf"等,将有助于深入理解这一框架及其在实际项目中的应用。
ActiveRecord模型Rails实验室 目标 手动创建迁移 手动创建模型 建立模型实例方法 建立模型 您可以在spec/models目录中找到此应用程序的测试套件,并使用以下命令运行它们: bundle exec rspec 。 该实验室进行测试以...
### ActiveRecord在Ruby与Rails中的应用 #### 一、前言 《Pro ActiveRecord:Databases with Ruby and Rails》这本书深入探讨了如何使用ActiveRecord这一对象关系映射(Object Relational Mapping, ORM)工具来...
Rails3 是 Ruby on Rails 框架的一个版本,它提供了一系列强大的命令行工具,使得开发者可以快速地构建和管理Web应用。在本文中,我们将深入探讨Rails3中的常用命令,帮助你更高效地进行开发工作。 首先,新建一个...
Active Record是Rails用来管理应用程序模型方面的内置ORM。 什么是ORM? ORM是一个对象关系映射系统,从本质上讲,这是一个模块,它使您的应用程序能够以方法驱动的结构来管理数据。 这意味着您可以利用方法而不是...