Ruby on Rails,使用find方法加载持久化对象

前文《Ruby on Rails,使用new和create创建ActiveRecord对象及他们之间的区别》,《Ruby on Rails,使用save和update_attributes更新持久化的ActiveRecord对象,《Ruby on Rails,使用destroy方法删除ActiveRecord对象》中,分别介绍了向数据库中创建、更新、删除对象的方法。在应用实践中,从数据库查询对象的机会要远远高于创建、修改、删除的机会。下面来看看如何通过find方法加载ActiveRecord对象。

之前我们就已经使用过类似于Subject.find(1)的方法从数据库中加载Subject对象了。这是find的最简单用法,传入主键,得到对应的对象实例。

irb(main):015:0* subject = Subject.find(1)
  [1m[35mSubject Load (1.0ms)[0m  SELECT `subjects`.* FROM `subjects` WHERE `subjects`.`id` = 1 LIMIT 1
=> #<Subject id: 1, created_at: "2012-10-20 06:14:56", updated_at: "2012-10-20 06:14:56", name: "First Subject", position: nil>
irb(main):016:0>

如果传入的主键id对应的记录并不存在,将会抛出异常通知"RecordNotFound: Couldn't find Subject with id=2"以便进行后续处理。关于异常处理在后面会有所涉及,在这里只要知道主键查询这种方式有可能抛出异常即可。

irb(main):019:0* subject = Subject.find(2)
  [1m[36mSubject Load (1.0ms)[0m  [1mSELECT `subjects`.* FROM `subjects` WHERE `subjects`.`id` = 2 LIMIT 1[0m
ActiveRecord::RecordNotFound: Couldn't find Subject with id=2
        from E:/greensoft/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/relation/finder_methods.rb:340:in `find_one'
        from E:/greensoft/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/relation/finder_methods.rb:311:in `find_with_ids'
        from E:/greensoft/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/relation/finder_methods.rb:107:in `find'
        from E:in `find'
        from (irb):19
        from E:/greensoft/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands/console.rb:47:in `start'
        from E:/greensoft/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in `start'
        from E:/greensoft/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands.rb:41:in `<top (required)>'
        from script/rails:6:in `require'
        from script/rails:6:in `<main>'

通过all方法,可以返回所有对象的列表。

 

irb(main):051:0* Subject.all
  [1m[35mSubject Load (1.0ms)[0m  SELECT `subjects`.* FROM `subjects`
=> [#<Subject id: 1, created_at: "2012-10-20 06:14:56", updated_at: "2012-10-20 06:14:56", name: "First Subject", position: nil>, #<Subject id: 2, created_at: "2012-10-20 06:25:27", updated_at: "2012-
10-20 06:25:27", name: "First Subject", position: nil>]

通过first和last方法,可以分别返回数据库中第一个和最后一个对象。

irb(main):055:0* Subject.first
  [1m[36mSubject Load (1.0ms)[0m  [1mSELECT `subjects`.* FROM `subjects` LIMIT 1[0m
=> #<Subject id: 1, created_at: "2012-10-20 06:14:56", updated_at: "2012-10-20 06:14:56", name: "First Subject", position: nil>
irb(main):056:0> Subject.last
  [1m[35mSubject Load (1.0ms)[0m  SELECT `subjects`.* FROM `subjects` ORDER BY `subjects`.`id` DESC LIMIT 1
=> #<Subject id: 2, created_at: "2012-10-20 06:25:27", updated_at: "2012-10-20 06:25:27", name: "First Subject", position: nil>

另外一种查询对象的方法是类似于Subject.find_by_name("First Subject")的形式,称之为动态查询。其中by后面是某一个进行查询的属性的名字,比如Subject的name属性。参数是属性的值,比如“First Subject”。如此调用将会返回name属性值为“First Subject”的Subject对象。

irb(main):034:0* Subject.find_by_name("First Subject")
  [1m[36mSubject Load (0.0ms)[0m  [1mSELECT `subjects`.* FROM `subjects` WHERE `subjects`.`name` = 'First Subject' LIMIT 1[0m
=> #<Subject id: 1, created_at: "2012-10-20 06:14:56", updated_at: "2012-10-20 06:14:56", name: "First Subject", position: nil>

通过find_by_id方法和find方法一样,都是通过id进行查询。

如果通过动态查询没有查找到符合条件的对象,与find方法抛出异常不同,find_by_xx方法只会返回nil表示记录没有找到。

irb(main):039:0* Subject.find_by_name("Second Subject")
  [1m[35mSubject Load (1.0ms)[0m  SELECT `subjects`.* FROM `subjects` WHERE `subjects`.`name` = 'Second Subject' LIMIT 1
=> nil

使用find_by_xx方法只会返回第一个符合条件的对象,所以一般来说这个方法大多用于探测一下数据库中有指定属性等于特定值的对象。要想得到符合条件的所有对象,需要将find_by和all组合在一起,使用find_all_by_xx。

irb(main):060:0* Subject.find_all_by_name("First Subject")
  [1m[36mSubject Load (1.0ms)[0m  [1mSELECT `subjects`.* FROM `subjects` WHERE `subjects`.`name` = 'First Subject'[0m
=> [#<Subject id: 1, created_at: "2012-10-20 06:14:56", updated_at: "2012-10-20 06:14:56", name: "First Subject", position: nil>, #<Subject id: 2, created_at: "2012-10-20 06:25:27", updated_at: "2012-
10-20 06:25:27", name: "First Subject", position: nil>]

请注意find系列的方法都是实时加载的,也就是说调用方法的同时就会与数据库交互进行查询。后面会讲到可以使用懒加载的方法。find_by_xx方法虽然能够进行条件过滤,但是返回的结果是一个列表,失去了再进一步过滤的能力。在Rails3.2以后就应该都转向使用where方法进行条件过滤查询了。

posted on 2012-10-20 19:33  边晓宇  阅读(2162)  评论(0编辑  收藏  举报