http://guides.rails.info/active_record_querying.html
1 Retrieving Objects from the Database
1.1 Retrieving a Single Object
使用主键
Model.find(primary_key)
如果找不到记录,会raise一个ActiveRecord::RecordNotFound的异常。
first
Model.first会返回第1条记录。如果表是空的,则返回nil。
last
Model.last返回最后1条记录。如果表是空的,则返回nil。
1.2 Retrieving Multiple Objects
Model.find(1,2)#或者Model.find([1,2])
如果参数中的任何一个id没有在数据库中找到,会raise一个ActiveRecord::RecordNotFound异常。
Model.each
有时候也许你会需要遍历一个巨大的记录集,比如发送一个newsletter给每个user,下面的代码是一种很直接的方式:
# 当users表有成千上万条记录的时候,性能会变得非常低下。
User.each do |user| #在Rails2中通常这么使用:User.all.each do |user|
NewsLetter.weekly_deliver(user)
end
在调用each方法的时候,整个users表的数据都会被载入内存。如果用户总数是一个非常大的数字,将会因为内存被占用过多而导致性能低下。
Model.find_each
为了改善遍历大表的性能,ActiveRecord提供了一个find_each方法:
User.find_each do |user|
NewsLetter.weekly_deliver(user)
end
find_each默认每次加载1000条数据,然后逐个处理。它接受一个:batch_size选项,可以用来设置每一批数据的数量:
User.find_each(:batch_size => 5000) do |user|
NewsLetter.weekly_deliver(user)
end
find_each以id的升序来加载对象,id必须是个整数(
其它类型的怎么办?比如uuid)。它还接受一个:start选项,用于设置要加载的对象的id的起始值,下面的代码从id为2000的user开始发送newsletter:
User.find_each(:batch_size => 5000, :start => 2000) do |user|
NewsLetter.weekly_deliver(user)
end
Model.find_in_batches
find_each在批量加载指定数量的对象后,依次对每个对象进行处理。find_in_batches和find_each的行为差不多,区别在于加载指定数量的对象后,find_in_batches的block里的参数是一个对象数组,而不是单个对象。
2 Conditions
Rails3中不再推荐使用Rails2中的那一系列options:
以下引自:http://m.onkey.org/2010/1/22/active-record-query-interface
引用
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.
简单的说,把:conditions, :include, :joins, :limit, : offset, : order, :select, :readonly, :group, :having, :from, :lock这些选项hash传递给ActiveRecord的任何一个类方法的做法已经不建议使用了。
Going into details, currently ActiveRecord provides the following finder methods :
详细点说,当前版本的ActiveRecord提供了以下finder方法:
* 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.
从Rails3开始,不建议给以上的方法传递任何选项,并且将在Rails3.2中移除对这种方式的支持。同时,find(:first)和find(:all)(不带任何其它选项)也不建议使用,而改用first、all方法。但是还有个特例:count()方法将仍然接收:distinct选项。
那Rails3 中要如何按条件查询、如何给查询结果排序呢?
2.1 Pure String Conditions
Model.where()
Rails3给Model提供了一个where方法,参数可以是一个简单的字符串,当它的参数只是一个简单的字符串的时候,这个参数将被拼接在生成的SQL语句的“WHERE”之后。Client.where("orders_count = '2'")将会返回所有orders_count字段为2的client。但这种方式极不安全,容易受到SQL注入攻击。
2.2 Array Conditions
安全的办法是使用数组形式的参数:
Client.where(["orders_count = ?", params[:orders]])
如果你要指定两个条件,可以这样:
Client.where(["orders_count = ? AND locked = ?", params[:orders], false])
数组中第一个元素和原来的查询条件差不多,只是把值都换成了问号。接下来的元素每一个都依次和第一个元素字符串中的问号对应。
2.2.1 Placeholder Conditions
另一种方法和上面的差不多,只是数组只有2个元素:
Client.where( ["created_at >= :start_date AND created_at <= :end_date", { :start_date => params[:start_date], :end_date => params[:end_date] }])
这里把前面的问号占位符换成了以冒号开头的字符串(这里不能说是symbol吧?),分别对应第2元素中的key。第2个元素是个hash,它的值将被用于替换第一个元素中的占位符(就是以冒号开头的字符串)。
2.2.2 Range Conditions
数组的第2个元素还可以是一个Range对象,经常和“IN”搭配使用,如:
Client.where(["created_at IN (?)", (params[:start_date].to_date)..(params[:end_date].to_date)])
如果这个Range是个小范围,生成的查询一般不会有什么问题。但如果是个大范围,比如一年的365天,生成的SQL将会是这样:
SELECT * FROM users WHERE (created_at IN ('2007-12-31','2008-01-01','2008-01-02','2008-01-03','2008-01-04','2008-01-05', '2008-01-06','2008-01-07','2008-01-08','2008-01-09','2008-01-10','2008-01-11', '2008-01-12','2008-01-13','2008-01-14','2008-01-15','2008-01-16','2008-01-17', '2008-01-18','2008-01-19','2008-01-20','2008-01-21','2008-01-22','2008-01-23',... ‘2008-12-15','2008-12-16','2008-12-17','2008-12-18','2008-12-19','2008-12-20', '2008-12-21','2008-12-22','2008-12-23','2008-12-24','2008-12-25','2008-12-26', '2008-12-27','2008-12-28','2008-12-29','2008-12-30','2008-12-31'))
2.2.3 Time and Date Conditions
上面那种情况可能会引发一个SQL服务器的异常,例如MySQL会抛出这样一个异常:
引用
Got a packet bigger than 'max_allowed_packet' bytes: _query_
比较好的办法是使用之前的Array Conditions或者Placeholder Conditions:
Client.where( ["created_at > ? AND created_at < ?", params[:start_date], params[:end_date]])
2.3 Hash Conditions
除了字符串、数组,where()方法还支持Hash形式的条件。
2.3.1 Equality Conditions
Client.where({ :locked => true })
#或者
Client.where({ 'locked' => true })
2.3.2 Range Conditions
Client.where({ :created_at => (Time.now.midnight - 1.day)..Time.now.midnight})
将会生成SQL语句:
SELECT * FROM clients WHERE (clients.created_at BETWEEN '2008-12-21 00:00:00' AND '2008-12-22 00:00:00')
2.3.3 Subset Conditions
Client.where({ :orders_count => [1,3,5] })
将生成SQL语句:
SELECT * FROM clients WHERE (clients.orders_count IN (1,3,5))
2.4 Ordering
Rails3提供了一个
order()方法用于排序。
Client.order("created_at")
Client.order("created_at DESC")
#或
Client.order("created_at ASC")
#还可以根据多个字段来排序:
Client.order("orders_count ASC, created_at DESC")
………………不记了,也就是把那些个options换成了对应的方法。然后,由于这些方法
返回的是一个ActiveRecord::Relation的对象,并且数据不是即时加载的,所以这些方法可以
链式调用例如:
User.order('users.id DESC').limit(20).includes(:items)
甚至可以这样:
cars = Car.where(:colour => 'black')
rich_ppls_cars = cars.order('cars.price DESC').limit(10)
(感觉好像SearchLogic)
还有,joins()方法只支持内联接(INNER JOIN)。Rails2的named_scope被改名为scope,还有新增的scoped、with_scope和with_exclusive_scope方法,更多更详细的新特性可以参考:
http://m.onkey.org/2010/1/22/active-record-query-interface
http://yehudakatz.com/2010/01/10/activemodel-make-any-ruby-object-feel-like-activerecord/这篇博客让我想起一个
JavaEye新闻,找了一下,果然就是这篇,因为当时rails3还没有发布,所以没有太在意。
Validations
http://guides.rails.info/3_0_release_notes.html#validations
引用
Validations have been moved from Active Record into Active Model, providing an interface to validations that works across ORM libraries in Rails 3.
* There is now a validates :attribute, options_hash shortcut method that allows you to pass options for all the validates class methods, you can pass more than one option to a validate method.
* The validates method has the following options:
* :acceptance => Boolean.
* :confirmation => Boolean.
* :exclusion => { :in => Ennumerable }.
* :inclusion => { :in => Ennumerable }.
* :format => { :with => Regexp, : on => :create }.
* :length => { :maximum => Fixnum }.
* :numericality => Boolean.
* :presence => Boolean.
* :uniqueness => Boolean.
All the Rails version 2.3 style validation methods are still supported in Rails 3.0, the new validates method is designed as an additional aid in your model validations, not a replacement for the existing API.
============算了,直接在这汇总一下吧:=============
Rails3中,
路由的写法变了,可以参考:
http://guides.rails.info/routing.html
http://rizwanreza.com/2009/12/20/revamped-routes-in-rails-3
还有routes.rb的注释部分。
不再使用script/server这样的方式运行rails程序,而改用rails server命令。原来的一系列script/xxxx脚本全没了,统一使用rails命令。
rails generate controller home index
上面那句甚至可以这样写:
rails g controller home index
migration的写法似乎没有变化。
在之前的Rails中,经常需要在页面中调用
h方法,像这样:
<%= h post.name %>
来防止html注入。在Rails3中不需要这么做了,转义的动作变成默认的,如果需要取消转义,只要调用
raw方法即可:
<%= raw post.name %>
最后,还有一处大改动,就是
JavaScript的Helper,这个可以参考比较早的一个帖子:
http://www.iteye.com/topic/476671
一个老外的
Unobtrusive JavaScript in Rails3
这里有一篇比较详细的JavaScript in Rails3:
http://cn.asciicasts.com/episodes/205-unobtrusive-javascript
两个链接:
Rails 3 文章集合、
Rails3 Beta 发布: 重点导览
补一个infoQ关于Rails3的报道:
http://www.infoq.com/cn/news/2010/02/rails-3-beta
再补一篇夜鸣猪的译文:Rails 3中的Active Record的查询变化,比我这个详细。
分享到:
相关推荐
active_record_upsert, Rails 5/Active Record 5的更新更新 ActiveRecordUpsertpostgre 9.5 和 Rails 5/ActiveRecord 5的真正更新。 在冲突时使用进行更新。的主要点是否在单个记录上使用 ON CONFLICT DO U
Rails 3中的Active Record的查询变化.doc
Pro Active Record. Databases with Ruby and Rails
Ruby on Rails Guides_ A Guide to Active Record Associations.pdf
ActiveRecordUpsert PostgreSQL 9.5+和Rails 5+ / ActiveRecord 5+的真实更新。 使用 。 要点 使用ON CONFLICT DO UPDATE在单个记录... gem 'active_record_upsert' 然后执行: $ bundle 或将其自己安装为: $ gem
Rails 3 in Action 2011年9月新鲜出炉,针对最新的Rails 3.1进行说明
在Rails的开发控制台和日志中显示每个查询的回溯。 允许您跟踪应用程序中查询的执行位置。 对于性能优化以及在对大型应用程序进行更改时查找从哪里开始有用。 启用后,每个查询都会记录如下: D, [2019-03-03T19:...
Pro.Active.Record.Databases.with.Ruby.and.Rails
rails generate active_record:session_migration 运行迁移: rake db:migrate 然后,在config/initializers/session_store.rb设置会话存储: Rails . application . config . session_store :active_record_...
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 ...
Now in version 4, Rails is mature and powerful, and to use it effectively you need more than a few Google searches. You'll find no substitute for the guru's-eye-view of design, testing, deployment, ...
Rails 4 in Action, Second Edition.pdf
Record Cache - 在Rails 3中缓存Active Model Records
gem 'active_record_migrations' gem 'sqlite3' # or 'pg', 'mysql2', ... 然后执行: $ bundle --binstubs 创建一个Rakefile: require 'active_record_migrations' ActiveRecordMigrations.load_tasks 用法 ...
What’s New In Rails 2.1: A Well Produced, Free E-Book
Bootstrap 3 和 Rails 4(样例用的是Ruby 2.1.1,Rails 4.1.4) Table of Contents Preface 1 Chapter 1: Introducing Web Application Development in Rails 7 Why Bootstrap with Rails? 8 Setting up a Todo ...
这是Rocket Job原始库的略微修改,只是将其从active_record_slave重命名为active_record_replica 。 为了更清楚地将库与active_record_slave区别开来,我们还增加了主版本–但是,它在功能上是等效的。 介绍 active...
Drawing on their unsurpassed experience and track record, they address the real challenges development teams face, showing how to use Rails 3 to maximize your productivity. Using numerous detailed ...