第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开发 Web开发敏捷之道-应用Rails进行敏捷Web开发-2版 Web开发敏捷之道-应用Rails进行敏捷Web开发-3版
《Web开发敏捷之道:应用Rails进行敏捷Web开发(第3版)》第1版曾荣获Jolt大奖“最佳技术图书”奖。在前两版的内容架构基础上,第3版增加了对Rails 2中新特性和最佳实践的内容介绍。相比第2版中的内容,Rails 2增加了...
资源名称:Web开发敏捷之道 应用Rails进行敏捷Web开发(第3版)内容简介:全书主要分为两大部分。在“构建应用程序”部分中,读者将看到一个完整的“在线购书网站”示例。在随后的“Rails框架”部分中,作者深入介绍...
《应用Rails进行敏捷Web开发》中文第三版,找了很久才找到,介绍的是rails2.2.2
应用Rails进行敏捷Web开发第三版应用Rails进行敏捷Web开发第三版应用Rails进行敏捷Web开发第三版
Web开发敏捷之道--应用Rails进行敏捷Web开发(第2版中文版).part15.rar
博文链接:https://zhangpeihao.iteye.com/blog/200033
Web开发敏捷之道-应用Rails进行敏捷Web开发-第三版 ruby on rails开发不能错过的参考学习手册 为中文版
应用Rails进行敏捷Web开发第三版 应用Rails进行敏捷Web开发第三版
应用rails进行敏捷Web开发·第三版 应用rails进行敏捷Web开发·第三版 应用rails进行敏捷Web开发·第三版
Web开发敏捷之道-应用Rails进行敏捷Web开发-第三版.rarWeb开发敏捷之道-应用Rails进行敏捷Web开发-第三版.rarWeb开发敏捷之道-应用Rails进行敏捷Web开发-第三版.rarWeb开发敏捷之道-应用Rails进行敏捷Web开发-第三版...
应用rails进行敏捷web开发中文版第3版
应用Rails进行敏捷Web开发第三版20090319.doc ruby运维高阶版 不错的学习材料噢!!
web开发敏捷之道:应用rails进行敏捷web开发(原书第4版) 的源代码。注意是源代码,并非电子书。包含RAILS3.0,3.1.3.2代码。
应用Rails进行敏捷Web开发 第三版(doc格式) 下了个docx格式的。担心有的人打不开,我转成doc格式了。赚点分。O(∩_∩)O哈哈~
应用rails进行敏捷Web开发·第二版源代码
应用Rails进行敏捷Web开发第三版20090319.pdf 关于ruby2.0的说明文档,
应用Rails进行敏捷Web开发2