一、CRUD的含义
CRUD是四种数据操作的简称,分别对应的是:
- C即Create,表示创建资料,并存入数据库
- R即Read,表示读取或显示数据库中的资料
- U即Update,表示更新数据库中已有的资料
- D即Destroy,表示删除数据库中的资料
下面分别介绍下它们各自的用法
二、CRUD的用法
一、C(创建)
Active Record对象的创建有三种方式:
- 使散列(也叫哈希)创建
- 创建后手动设置属性
- 在块中创建
new和create都是创建对象,区别在于:
new方法创建新对象,但没有存入数据库
create方法创建新对象,并将其存入数据库
下面分别用new和create方法结合三种对象的创建方式在Rails console中来展示创建对象的过程:
1.使用new方法
(1)使用散列创建对象
p= Product.new(title: "葡萄",quantiy: 20)
此时创建了一个p对象,但 还没有存入到数据库:
使用p.save将会将对象p的内容存入到数据库,如图:
(2)创建对象,然后手动设置属性
a = Product.new
a.title = "苹果"
a.quantity =66
此时创建了一个a对象,一开始没有值,后面通过a.title和a.quantity为a对象的属性赋值,如图:
使用a.save就可以将a对象存入数据库
(3)使用块创建对象
b = Product.new do |f|
f.title = "橄榄"
f.quantity = 88
end
此时使用块方法创建了b对象,并为b对象赋值,如图:
使用b.save即可将b对象存入数据库。
当然,你可以用new和块方法创建空的b对象,如:
b = Product.new do |f|
end
这样创建的b对象就是空对象
2.使用create方法
(1)使用散列创建对象
c = Product.create(title: "橘子",quantity: 50)
create在创建c对象的同时,将c对象存入数据库,如图:
(2)创建对象,然后手动设置属性
d = Product.create
d.title = "柠檬"
d.quantity = 100
d.save
首先使用create创建了一个空的d对象,并存入数据库,接下来对d对象的title和quantity进行赋值,但要注意到是需要使用d.save才能将设定的新的属性值存入数据库
(3)使用块创建对象
e= Product.create do |f|
f.title = "红树莓"
end
e.quantity = 100
e.save
先用块创建了e对象,同时为title赋值,然后存入数据库。接下来为e对象的quantity属性进行赋值,并使用e.save将新属性值存入到数据库,如图:
当然你也可以使用create和块方法创建空的对象,将其存入到数据库中
g = Product.create do |f|
end
如图:
二、R(读取)
这里介绍常见的几种查询方式:
(1)all
p = Product.all
将会返回所有product组成的集合
(2)first
p = Product.first
将会返回第一product
也可以对first传入数字,返回不超过指定数量的查询结果,如:
p = Product.first(4)
将会按照升序返回前4个product,若数据库中只有3条数据(不足4个)结果,则返回3个product
(3)last
p = Product.last
将会返回最后一个product
也可以对last方法传入数字,返回不超过指定数量的查询结果,如:
p = Product.last(4)
将会按照升序方式返回最后4个product,若数据库中只有3条数据(不足4个)结果,则返回3个product
(4)find
使用 find 方法时会检索指定主键对应的对象,默认的主键一般是id
p = Product.find(3)
返回id为3的product,若不存在id为3的product,则会出现ActiveRecord::RecordNotFound 异常
也可以用find来查找多个对象
p = Product.find([1,3])
返回id为1和id为3的两个product,若不存在对应id的product,则会出现ActiveRecord::RecordNotFound 异常
(5)find_by
可以使用find_by按照属性进行查找结果,并且只会返回符合条件的结果中的第一个结果
p = Product.find_by(quantity: 20)
将返回所有quantity为20的product,若不存在,则返回nil,不抛出异常
p = Product.find_by(title: "香蕉")
将返回所有title为香蕉的product,若不存在,则返回nil,不抛出异常
另外上述代码可以改写成:
p = Product.find_by_quantity(20)
p = Product.find_by_title("香蕉")
find_by的效果相当于where和first的组合使用
需要注意的是:
find_by! 方法的行为和 find_by 方法类似,两者的区别在于如果没有找到匹配的记录,find_by! 方法会抛出 ActiveRecord::RecordNotFound 异常,因此使用!的方式(如save!,find_by!,last!等)可以用来排除bug,找出出错点
(6)order
p = Product.order("id DESC")
将所有product按照id进行降序排列
p = Product.order("created_at ASC")
将所有product按照created_at进行升序排列
p = Product.order(:quantity)
将所有product按照quantity栏位属性进行升序排列
(7)where
where查询方法将会返回元素集合,若不存在则返回空数组[]
p = Product.where(title: "红树莓", quantity: 20)
将会查找title为红树莓,并且quantity为20的product集合,如果不存在则返回空数组[]
(8)组合运用
除了上面的查询方法可以单个运用,我们也可以组合起来使用,例如:
p = Product.order(:price).find_by(quantity: 20)
这样可以先按照price对product进行升序排列,然后从中找到quantity为20的prodcut
补充:
在使用上述这些查询方式的时候,要注意哪些是返回元素集合方式的,哪些是返回元素的,并按照顺序进行组合使用,否则,会发生NoMethodError: undefined method报错,例如:
p = Product.find_by(title: "香蕉").last
就是错误的用法,因为find_by返回的元素,last方法是对集合使用的,因此正确的用法是:
p = Product.where(title: "香蕉").last(2)
where将返回title为香蕉的元素集合,然后通过last(2)找到集合中的最后两个元素,形成新的数组
因此可以总结为:
(1)返回元素集合的查询方法可以和返回元素集合的查询方法组合使用
(2)返回元素集合的查询方法也可以和返回元素的查询方法组合使用,并且返回元素的查询方法只能放在返回元素集合查询方法的后面
(3)但是返回元素的查询方法无法和返回元素的查询方法组合使用
更多查询接口参考:Active Record 查询接口
三、U(更新)
更新数据库中的资料有以下方法:
(1)使用赋值运算符,然后保存
p = Product.find_by(title: "苹果")
p.title = "石榴"
p.save
上述代码从数据库中找出title为苹果的那一笔资料,然后修改其title值,最后存入数据库
(2)update_all
update_all是批量更新的方法
p = Product.where(quantity: 20)
p.update_all(quantity: 200)
上述代码捞出数据库中quantity为20的所有资料,并且将它们的quantity更新为200
(3)update
(4)update_columns
(5)udpate_attribute
关于使用update,update_all,update_columns,update_attribute更新数据库的详细资料可以参考我的这篇文章:使用update_columns/update/update_attribute/update_all更新数据库资料
此处就不再赘述。
四、D(删除)
(1)destroy_all批量删除
p = Product.where(quantity: 200).destory_all
上述代码分别是查找所有quantity为200的product资料,并将其删除,
q = Product.all.destroy_all
上述代码是删除数据库中所有的product资料
(2)destroy删除单笔资料
p = Product.find_by(title: "柠檬")
p.destroy
上述代码查找title为柠檬的资料,然后删除那一笔资料
注意:
destroy_all是删除元素集合(可以理解成多笔资料),destroy是删除元素(单笔资料),不要对find_by等返回元素的方法或单个元素使用destory_all;也不要对where等返回元素集合的方法或元素集合使用destroy,否则都会发生NoMethodError: undefined method报错