Rails 手册 | 07 - Rails ORM

122 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 26 天,点击查看活动详情

ActiveRecord

ActiveRecord 是 Rails 进行数据库操作的核心组件,使用它可以非常方便的连接到数据库进行操作和处理数据。

数据库与对象的映射关系

ActiveRecord 采用标准的 ORM 模型,将表迎神到类,将执行记录映射到实例对象,将字段映射到对象的属性。

Rails 应用中的模型类基本都是继承自 ApplicationRecord,而ApplicationRecord又继承了 ActiveRecord::Base,这表示该模型就具有类相应的操作数据库的方法,默认情况下模型类直接对应的表名应该是下划线分割的复数形式,不过在特殊情况下可以自定义类所对应的表名,既使用 set_table_name 方法。

如果想要取消 Rails 应用的模型和表名单复数的约定,可以在 config/enviroment.rb 中加入代码:

ActiveRecord::Base.pluralize_table_names = false 

使用如下命令创建一个 Rails 项目,并通过 “-d” 参数执行数据库为 MySQL 数据库:

rails new railsapp -d=mysql

修改 config/database.yml 中的数据库配置:

default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: root
  host: localhost

执行数据库创建命令,创建数据库:

# 创建数据库 railsapp_development 和 railsapp_test
rails db:create

在 railsapp_development 中创建一个 users 表:

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `create_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ;

在 railsapp 应用中创建一个 User 模型:

rails g model user

app/models 下自动生成的 user.rb 文件内容如下:

class User < ApplicationRecord
end

接着我们可以通过 Rails 控制台来查看 ActiveRecord模型类 User 和 表 users 的对应关系,在控制台中输入如下命令:

rails console

图片.png

User.columns 会返回 users 表中所有的字段信息,而 user 为 User 模型类的实例对象,它的属性与 users 的字段完全一致。users 表中的每一行记录,都会对应 User 的一个实例对象。

users 表的主键是 id 字段,如果要私用 ActiveRecord,表中必须定义一个整数型的主键,因为只有这样才能保证数据能够唯一对应于相应的对象,而 Rails 的约定就是主键的名称为 id,如果表中存在一个名为 id 的主键,那么 ActiveRecord 就会自动使用他来对应实例对象。

User 模型类中没有定义任何属性,为什么 User 的实例对象 user 会有 username,password 等属性呢?

这是因为 Ruby 的动态特性,由于 User 继承了 ActiveRecord::Base,而 ActiveRecord::Base 类中会自动连接数据库获取对应表的信息,并使用 module_eval 之类的冬天执行方法动态生成相应的方法,因此最后 User 类可以看成类似于:

class User < ApplicationRecord

    def username
        ...
    end
    
    def username=(val)
        ...
    end
    
    ...
end

既然 username 是 User 类的实例方法,因此可以被自己编写的代码覆盖,这种可以让访问或者存储数据时进行一些其他的操作,比如数据的合法性校验等。

比如需要用户的密码长度必须大于3,可以这样改写 User 模型类的代码:

class User < ApplicationRecord
  
  def password=(val)
    raise "密码长度必须大于3" if(!val or val.size < 3)
    write_attribute "password", val # 将 val 的值赋值给 password 属性
  end
end

在控制台中测试该代码:

图片.png