第19章 Active Record
这章介绍:
-
>establish_connection方法
-
>表、类、列、属性
-
>id和关联关系
-
>增删改查的方法
-
>回调与事物处理
Active Record是Rails提供的对象关系映射(ORM)层,它帮助你实现了你的Model层。
这一章会涉及使用Active Record(后面简称AR)进行增删改查(CRUD)。最后会深入了解AR的生命周期(包括回调和事物)。
19.1 定义数据
在Depot项目中(可参考原书P70—P256)我们定义了一系列的models,其中有Order,它有一些属性例如String类型的email地址,除此之外,Rails提供了一个名为id的属性来标注该记录的主键(pk)。另外还有一些属性用于跟踪每一行的更新行为。Rails也提供了对象关系映射的功能,正如Depot中Order和LineItem的关系
组织表与列
每一个ActiveRecord::Base的子类,比如Order类,都包装了一个数据库表。默认情况下,AR假设表的名称关联到一个给定类名的复数形式,如果该类的名里包含大写字母,则该表名就会用下划线分割这些单词
如图:
大部分情况下Rails可以正确处理这些复数形式,但也有时你会不经意发现一些错误。比如可能你会遇到这种情况,你可以通过修改config/initializers/inflections.rb文件,让Rails理解英语的用法习惯情况
# Be sure to restart your server when you modify this file.
#
Add new inflection rules using the following format
#
(all these examples are active by default):
# ActiveSupport::Inflector.inflections do |inflect|
# inflect.plural /^(ox)$/i, '\1en'
# inflect.singular /^(ox)en/i, '\1'
# inflect.irregular 'person', 'people'
# inflect.uncountable %w( fish sheep )
# end
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'tax', 'taxes'
end
如果你要处理旧的表,并且不许要上述Rails自动关联行为可以自行指定
class Sheep < ActiveRecord::Base
self.table_name = "sheep"
# 设置表名
end
Ar的每一个实例都相当于一个数据库表中的行,而这些对象的属性相当于对应表中的列。在Depot项目重的Order实体中并没有提及任何关于orders表的列信息,因为AR是在运行时动态测定的。AR通过数据库的schema来配置包装表的那些实体类。
比如我们的orders表是通过下面的migration定义的(db/migrate/2011021100000007_create_orders.rb)
def self.up
create_table :orders do |t|
t.string :name
t.text :address
t.string :email
t.string :pay_type, :limit => 10
t.timestamps
end
end
我们可以通过rails console 命令来查看这个模型
首先获取所有的列
depot> rails console
Loading development environment (Rails 3.0.5)
>> Order.column_names
=> ["id", "name", "address", "email", "pay_type", "created_at", "updated_at"]
然后我们查看pay_type列的具体信息
>> Order.columns_hash["pay_type"]
=> #<ActiveRecord::ConnectionAdapters::SQLiteColumn:0x7fe673f7da80
@name="pay_type", @null=true, @default=nil, @sql_type="varchar(10)",
@type=:string, @scale=nil, @precision=nil, @primary=false,
@limit=10>
可见AR可以获取该列的所有信息。Rails在我们第一次使用Order类时通过底层数据库获取所有的信息
AR实例的属性通常和相关数据库表中的行信息相关连。例如,orders表可能包含以下信息
depot> sqlite3 -line db/development.sqlite3 "select * from orders limit 1"
id = 1
name = Dave Thomas
address = 123 Main St
email = customer@example.com
pay_type = Check
created_at = 2010-06-18 00:36:57.355069
updated_at = 2010-06-18 00:36:57.355069
如果我们的AR对象获取到这个记录,该对象就会有七个属性如上
我们通过访问方法来访问这些属性。Rails自动转陪了属性读写方法
o = Order.find(1)
puts o.name
#=> "Dave Thomas
o.name = "Fred Smith"
给属性设值并不会改变数据库的数据,我们必须执行save才能持久化
Ar在读取属性值时会将其转换成有效的Ruby类型(如一个时间戳timestamp类型的数据会被当作Time类型的对象返回),如果我们希望得到原生数据,可以在该属性名称后加上_before_type_cast:
product.price_before_type_cast
#=> "29.95", a string
product.
updated_at_before_type_cast #=> "2008-05-13 10:13:14"
在model的代码重,我们可以使用 read_attribute和write_attribute私有方法,将属性名以String类型传入
SQL类型和Ruby类型的映射
Rails将没有小数位的Decimal转换成Fixnum对象,否则,转换成BigDecimal对象,为了确保不失精度。
至于Boolean的情况,由于不是所有的数据库都有boolean类型,为了防止像Mysql,0被当作false处理,1是true。不幸的是,Ruby把所有非false或nil都当作true处理,所以直接使用该值会出问题。通常我们在列名后加上问号
user = User.find_by_name("Dave")
if user.superuser?
grant_privileges
end
除了我们自己定义的属性,还有一些Rails自动提供的或有其他含义的属性。
关于Active Record提供的(其他)列
这里说明一些对于AR有特别意义的列的总结:
create_at, create_on, updated_at, updated_on
这几个列会在创建行或更新行的时候自动更新。以确保底层数据库列可以接受date,datetime, 或者string。Rails约定使用_on后缀的列标识date列,_at后缀标志time
lock_version
Rails会跟踪行版本号,如果表中有lock_version产生乐观锁
type
Ar可以被子类化,如果你这么做,所有的子类的属性都被保存在一个表中,而type属性就是用来标 注每一行的类型
id
这是表的主键的默认名称
xxx_id
这是默认的外键名,xxx是所引用的表名的单数形式
xxx_count
用于保持子表xxx的一个计数器缓存
还有一些插件,例如act_as_list,可能定义了其他的列名
主键和外键在数据库中是十分重要的,后面还会再探讨
19.2 定位与遍历记录
在Depot项目中,LineItem和其他三个模型有直接的关系:Cart,Order,Product.除此之外,模型之间有着间接联系。如Orders和Products通过LineItems维持这种关系
是id让这些关系成为可能
Ar的类和数据库中的表对应,类的实例与数据库表中每一行记录相对应。通过调用Order.find(1),可以返回包含这一主键为1的行的Order实例。
你可能随大流的往你所有的表结构中添加id主键列。然而如果你的数据库是旧的,AR给你了一个简单的方法来重写表主键名的方法。
比如这里一个books的数据库表的主键是ISBN
那么秩序在AR模型中如下指定
class LegacyBook < ActiveRecord::Base
self.primary_key = "isbn"
end
通常AR负责在我们向数据库中插入记录时为记录增加主键值。一般是增加的整形数,然而一旦我们重写了主键名,我们也许要承担设值主键的责任。我们依然需要设置一个名为id的属性。可能让我们感到惊讶的是,我们仍然需要设置id属性值来实现为主键赋值。在AR看来,主键值总是用id这个名称。
primary_key=xxx 设置了主键的名称。如下代码,我们通过给id属性设值,然而数据库中的主键的名称却是isbn:
book = LegacyBook.new
book.id = "0-12345-6789"
book.title = "My Great American Novel"
book.save
# ...
book = LegacyBook.find("0-12345-6789")
puts book.title
# => "My Great American Novel"
p book.attributes #=> {"isbn" =>"0-12345-6789",
"title"=>"My Great American Novel"}
这里查看book的属性,只有isbn和title,却不见id。当你要设置主键,还要使用id。其他时间,使用实际的列名。
Model重定义了Ruby的id和hash方法来引用model的主键。这意味着有合法id的model对象可以当作hash的key来使用。也说明,没有保存的model对象不能作为hash的key(因为没有合法id)
如果两个model对象是同样的类型,并且主键值相等,则Rails认为他们相同(==)。即没有被持久化的model对象即使有不同的属性数据,也被看作是相同。所以,如果你发先你在比较未被持久化的对象则需要覆盖==方法。
- 大小: 12.3 KB
- 大小: 13.9 KB
分享到:
相关推荐
《Web开发敏捷之道-应用Rails进行敏捷Web开发》是一本深度探讨如何利用Ruby on Rails框架进行高效、灵活的Web应用程序开发的专业书籍。该书的第四版,也被称为"Agile Web Development with Rails (4th edition)",是...
### Web 开发敏捷之道 —— 应用 Rails 进行敏捷 Web 开发 第三版 #### 一、Rails 的背景与发展 **Rails**,全称为 **Ruby on Rails**,是一种用于构建 Web 应用的开源框架,由 David Heinemeier Hansson 在 2004 ...
Web开发敏捷之道 应用Rails进行敏捷Web开发第4版 原版书及代码 (rails3.2版) 原书名为:Agile Web Development with Rails 4th for Rails 3.2 代码包含了 3.0、3.1、3.2 ,与原书配套的是3.2。 里面包含了第三版的...
《Web开发敏捷之道:应用Rails进行敏捷Web开发》是由美国知名开发者Sam Ruby撰写的一本经典著作,该书的第四版提供了全面且深入的指导,帮助读者掌握使用Ruby on Rails框架进行敏捷开发的方法和技术。Ruby on Rails...
( [应用Rails进行敏捷Web开发(第4版)].(Agile.Web.Development.with.Rails.4th.Edition).S.Ruby&D.Thomas&D.H.Hansson.原版
### Ruby on Rails Web 敏捷开发第四版 #### 关于本书的重要信息 《Ruby on Rails Web 敏捷开发第四版》是一本专为希望深入了解 Ruby on Rails 的开发者编写的书籍。该书主要针对 Rails 3 版本进行讲解,因此对于...
《敏捷Web开发与Rails:程序指南 第四版》是一本深度探讨使用Ruby on Rails框架进行敏捷Web应用开发的专业书籍。本书旨在帮助开发者充分利用Rails 4的特性,提高开发效率,实现快速迭代和高质量的代码编写。 Rails是...
《敏捷Web开发与Rails》第四版是一本专为软件开发者设计的权威指南,全面涵盖了使用Ruby on Rails框架进行敏捷Web应用开发的知识。Rails 3是该版本的重点,它引入了许多新特性和改进,使得开发过程更为高效且灵活。...
在本文中,我们将深入探讨如何使用Rails敏捷开发技术构建一个购物车系统,特别是在参考《rails敏捷开发第四版》中的示例。Rails 3.2.6是本文的基础框架,它是一个强大的Ruby Web应用程序框架,以其MVC(模型-视图-...
**标题与描述**:本书《Rails敏捷开发,我的成功之路》是一本详细介绍如何使用Rails框架进行高效、快速的网站开发的专业书籍。作者通过丰富的实例来阐述Rails框架的优势及其在敏捷开发中的应用。 **详细说明**:...
通过上述分析,我们可以看到,《敏捷Web开发与Rails》第三版不仅是一本关于Rails框架的技术书籍,更是一部指导开发者如何运用敏捷方法论进行Web开发的经典之作。无论对于初学者还是经验丰富的开发者而言,本书都具有...
本书《敏捷Web开发与Rails》第二版针对的是Rails 1.2版本。 在本书写作时,Rails 1.2版本的核心代码已经完成,但尚未被封装为Gem。这意味着读者可能需要采取一些特殊步骤来安装最新版本的Rails以匹配书中的示例代码...