Rails数据库操作:CRUD全解析
立即解锁
发布时间: 2025-08-17 02:27:07 阅读量: 2 订阅数: 4 

### Rails 数据库操作:CRUD 全解析
在数据库操作中,SQLite 和 MySQL 等数据库通常通过结构化查询语言(SQL)来访问数据。在大多数情况下,Rails 会帮助我们处理这些操作,但我们也可以自行提供 SQL 子句甚至完整的 SQL 语句。如果你熟悉 SQL,在使用 Rails 时会发现它为我们提供了熟悉的子句位置,如 `select`、`from`、`where`、`group by` 等;如果你不熟悉 SQL,Rails 的优势在于你可以在真正需要深入操作数据库时再去学习相关知识。
下面我们将以 Depot 应用中的 `Order` 模型为例,介绍如何使用 Active Record 方法进行数据库的创建(Create)、读取(Read)、更新(Update)和删除(Delete)操作,也就是常说的 CRUD 操作。
#### 1. 创建新行
在 Rails 中,表被表示为类,行被表示为对象。因此,我们可以通过创建相应类的新对象来在表中创建新行。以下是几种创建新行的方法:
##### 1.1 使用 `new` 方法
首先,我们可以使用 `Order.new` 方法创建一个新的 `Order` 对象,然后填充对象的属性值,最后调用 `save` 方法将对象保存到数据库中。示例代码如下:
```ruby
an_order = Order.new
an_order.name = "Dave Thomas"
an_order.email = "[email protected]"
an_order.address = "123 Main St"
an_order.pay_type = "check"
an_order.save
```
如果不调用 `save` 方法,对象只会存在于本地内存中,不会保存到数据库。
##### 1.2 使用 `new` 方法并传入块
`Active Record` 构造函数可以接受一个可选的块。在块中,我们可以直接操作新创建的对象并保存它,而无需创建新的局部变量。示例代码如下:
```ruby
Order.new do |o|
o.name = "Dave Thomas"
# ...
o.save
end
```
##### 1.3 使用 `new` 方法并传入属性哈希
我们还可以在 `new` 方法中传入一个属性哈希,这样可以更方便地设置对象的属性值。示例代码如下:
```ruby
an_order = Order.new(
name: "Dave Thomas",
email: "[email protected]",
address: "123 Main St",
pay_type: "check"
)
an_order.save
```
需要注意的是,在上述示例中,我们没有设置新行的 `id` 属性。因为 `Active Record` 默认使用整数列作为主键,当保存行时,它会自动创建一个唯一的值并设置 `id` 属性。我们可以通过查询对象的 `id` 属性来获取这个值:
```ruby
an_order = Order.new
an_order.name = "Dave Thomas"
# ...
an_order.save
puts "The ID of this order is #{an_order.id}"
```
##### 1.4 使用 `create` 方法
`Active Record` 还提供了一个便捷方法 `create`,它可以同时实例化模型对象并将其保存到数据库中。示例代码如下:
```ruby
an_order = Order.create(
name: "Dave Thomas",
email: "[email protected]",
address: "123 Main St",
pay_type: "check"
)
```
此外,`create` 方法还可以接受一个属性哈希数组,用于一次性创建多个行,并返回相应的模型对象数组。示例代码如下:
```ruby
orders = Order.create(
[ { name: "Dave Thomas",
email: "[email protected]",
address: "123 Main St",
pay_type: "check"
},
{ name: "Andy Hunt",
email: "[email protected]",
address: "456 Gentle Drive",
pay_type: "po"
} ]
)
```
`new` 和 `create` 方法接受属性哈希的真正原因是,我们可以直接从表单参数构造模型对象,例如在 `orders_controller.rb` 中常见的代码:
```ruby
@order = Order.new(order_params)
```
#### 2. 读取现有行
从数据库中读取数据时,我们需要先指定感兴趣的特定行数据,即给 `Active Record` 提供某种条件,它会返回符合条件的行数据对象。
##### 2.1 通过主键查找行
最直接的查找行的方法是指定其主键。每个模型类都支持 `find` 方法,该方法可以接受一个或多个主键值。如果只提供一个主键,它将返回包含相应行数据的对象;如果提供多个主键值,`find` 方法将返回一个包含相应对象的数组。需要注意的是,如果任何一个 ID 无法找到,将抛出 `ActiveRecord::RecordNotFound` 异常。示例代码如下:
```ruby
an_order = Order.find(27) # find the order with id == 27
# Get a list of product ids from a form, then
# find the associated Products
product_list = Product.find(params[:product_ids])
```
##### 2.2 使用条件查找行
除了通过主键查找行,我们还可以使用条件来查找行。`Active Record` 提供了 `where` 方法,用于指定查询条件。例如,要返回所有名为 Dave 且支付类型为 “po” 的订单列表,我们可以使用以下代码:
```ruby
pos = Order.where("name = 'Dave' and pay_type = 'po'")
```
上述代码将返回一个 `ActiveRecord::Relation` 对象,其中包含所有符合条件的行,每行数据都封装在一个 `Order` 对象中。
如果条件中的值是外部设置的(例如来自 Web 表单),直接将变量值代入条件字符串是不安全的,因为这可能会导致 SQL 注入攻击。正确的做法是让 `Active Record` 处理动态 SQL,它会创建正确转义的 SQL,从而避免 SQL 注入攻击。以下是几种安全的动态 SQL 生成方法:
- **使用问号占位符**:
```ruby
name = params[:name]
pos = Order.where(["name = ? and pay_type = 'po'", name])
```
- **使用命名占位符**:
```ruby
name = params[:name]
pay_type = params[:pay_type]
pos = Order.where("name = :name and pay_type = :pay_type",
pay_type: pay_type, name: name)
```
- **直接传递哈希作为条件**:
```ruby
pos = Order.where(params[:order])
```
需要注意的是,直接传递哈希作为条件时,会使用哈希中的所有键值对来构造条件。如果需要明确指定使用哪些参数,可以手动指定:
```ruby
pos = Order.where(name: params[:name],
pay_type: params[:pay_type])
```
##### 2.3 使用 `like` 子句
在条件中使用 `like` 子句时,需要注意正确的使用方法。例如,以下代码是错误的:
```ruby
# Doesn't work
User.where("name like '?%'", params[:name])
```
因为 Rails 不会解析条件中的 SQL,所以它会在参数值周围添加额外的引号。正确的做法是构造完整的 `like` 子句参数并传递给条件:
```ruby
# Works
User.where("name like ?", params[:name] + "%")
```
需要注意的是,如果参数值中包含百分号等字符,它们将被视为通配符。
##### 2.4 对返回记录进行子集操作
`ActiveRecord::Relation` 对象支持许多方法,用于对返回的记录进行子集操作。以下是一些常用的方法:
- **`first` 方法**:返回关系中的第一行,如果关系为空则返回 `nil`。
- **`all` 方法**:返回关系中的所有行,以数组形式返回。
- **`order` 方法**:指定查询结果的排序条件,类似于 SQL 中的 `order by` 子句。例如
0
0
复制全文
相关推荐










