ruby小白课程实战--宠物论坛

【Ruby on Rails实战】3.2 配置数据库以及数据库操

2018-12-19  本文已影响41人  808cb3be8e58

1、创建一个database

mysql我们已经在1.3节安装过了。连接远程,在项目目录下连接mysql,创建一个database数据库。如果你在1.3节启动项目时碰到了mysql错误并且解决了,那可以跳过1、2步,因为你已经配置好了。

vagrant@vagrant-ubuntu-trusty-64:/vagrant/data_system$ mysql -u root -p
#输入你在1.3节配置的数据库密码
Enter password:
#创建一个名为data_system数据库
mysql> create database data_system;
#系统返回信息
Query OK, 1 row affected (0.09 sec)
#再输入show databases;展示当前数据库的名字,data_symtem数据库就是我们刚刚创建的。
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| data_symtem        |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

2、配置config/database.yml文件

根据下面代码示例配置你的database.yml文件,其中password是你安装mysql时配置的密码。将development:下面数据库名改成咱们刚刚创建的数据库名database: data_system。test:和production:下面的代码不需要改动

# SQLite version 3.x
#   gem install sqlite3
#
#   Ensure the SQLite 3 gem is defined in your Gemfile
#   gem 'sqlite3'
#
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root   #mysql名称,默认为root
  password: xzn123xzn  #安装mysql时设置的密码
  host: localhost

development:
  <<: *default
  database: data_system #我们建立database的名称

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
#下面信息是默认的,初学的我们暂时不需要改动
test:
  <<: *default
  database: db/test.sqlite3

production:
  <<: *default
  database: db/production.sqlite3

3、创建映射文件,在data数据库中添加表

(1)我们先写一下这个表需要哪些字段,表结构如下:
字段名 字段说明 字段类型 备注
name 用户名称 string 必填
email 注册邮箱 string 必填
password 密码 string 必填
role 用户角色(控制权限) integer 0普通用户 1管理员 2超级管理员
status 用户状态(是否激活) integer 0已激活 1未激活
(2)创建映射文件rails g model ...

在项目目录下输入rails g model account name:string email:string password:string role:integer status:integer。会产生一个映射文件db/migrate/20180915153542_create_accounts.rb

#创建account表
/vagrant/data_symtem$ rails g model account name:string email:string password:string role:integer status:integer
#系统返回信息
create    db/migrate/20180915153542_create_accounts.rb
create    app/models/account.rb
invoke    test_unit
create      test/models/account_test.rb
create      test/fixtures/accounts.yml
(3)将映射文件映射到数据库rake db:migrate
#运行rake db:migrate,将映射文件映射到数据库中,此操作会在数据库建立account表以及在表中建立相应的字段
/vagrant/data_symtem$ rake db:migrate
== 20181127085433 CreateAccounts: migrating ===================================
-- create_table(:accounts)
   -> 0.0150s
== 20181127085433 CreateAccounts: migrated (0.0164s) ==========================

可能出现的错误:
Mac系统中,如果没有安装vagrant,直接在mac系统创建项目并运行rails g model...,可能会出现以下错误:

/Users/xuzhaoning/.rvm/rubies/ruby-2.4.4/lib/ruby/gems/2.4.0/gems/activerecord-
5.1.1/lib/active_record/connection_adapters/connection_specification.rb:188
:in `rescue in spec': Specified 'mysql2' for database adapter, but the gem is 
not loaded. Add `gem 'mysql2'` to your Gemfile (and ensure its version is at 
the minimum required by ActiveRecord). (Gem::LoadError)

解决方法:
安装vagrant,在Ubuntu环境中启动项目

4、进入控制台,查看数据

#进入控制台
/vagrant/data_symtem$ rails c 
#查看创建的accounts表
irb(main):001:0> Account.new  
=> #<Account id: nil, name: nil, email: nil, password: nil, role: nil, status: 0, created_at: nil, updated_at: nil>

5、数据库操作知识

Rails中的数据库操作用的是Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。
比如:Account这个模型类对应了mysql数据库中的accounts表,Account类的一个实例对象对应accounts表中的一条数据。

我们在项目目录下,输入rails c进入控制台,在控制台中操作数据库

(1)创建数据
#a是一个Accoun类的实例对象。
irb(main):001:0>  a = Account.create(name: "猫宁", email: "12345@qq.com")
#相当于mysql代码。当我们创建或者修改数据时,created_at字段和updated_at字段都会自动改变。
INSERT INTO accounts (name, email, created_at, updated_at) VALUES ('猫宁', '12345@qq.com', '2018-12-26 15:55:30', '2018-12-26 15:55:30')

#再创建一个name为“狗宁”,email为"23456@qq.com"的实例对象
irb(main):002:0> Account.create(name: "狗宁", email: "23456@qq.com")
(2)查找数据
1)查找第一条数据,返回我们创建的第一个Account对象
irb(main):001:0> a1 = Account.first
=> #<Account id: 1, name: "猫宁", email: "12345@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-26 15:55:30", updated_at: "2018-12-26 15:55:30">
#相当于mysql代码
SELECT * FROM accounts ORDER BY id ASC LIMIT 1
2)查找最后一条数据,返回我们创建的第二个Account对象
irb(main):002:0> a2 = Account.last
=> #<Account id: 2, name: "狗宁", email: "23456@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-28 09:31:22", updated_at: "2018-12-28 09:31:22">
#相当于mysql代码
SELECT * FROM accounts ORDER BY id DESC LIMIT 1
3)查找出所有数据,返回Account对象集合,里面包含我们创建的所有对象。

如果数据较多,在实际项目中不建议用.all拿出所有数据,因为这样会耗费很多的内存。数据量大,用分页或者where查询缩小范围。

irb(main):003:0> a3 = Account.all
=> #<ActiveRecord::Relation [#<Account id: 1, name: "猫宁", email: "12345@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-26 15:55:30", updated_at: "2018-12-26 15:55:30">, #<Account id: 2, name: "狗宁", email: "23456@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-28 09:31:22", updated_at: "2018-12-28 09:31:22">]
#相当于mysql代码
SELECT  * FROM accounts
4)通过id查找数据,这样会返回对应id的Account对象。

需要注意的是,如果没有此id,会报错,所以我们再实际项目中,在不确定该id存在的情况下,一般不会用find查找,而是用find_by替代,下面会讲。

irb(main):006:0> Account.find(2)
=> #<Account id: 11, name: "狗宁", email: "23456@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-28 09:31:22", updated_at: "2018-12-28 09:31:22">
#相当于mysql代码
SELECT * FROM accounts WHERE id = 2
5)通过条件查找数据,这样会得到Account对象集合,具体对象实例根据集合索引获取。
#查找name为"猫宁"的数据,得到一个对象的集合。
irb(main):008:0> accs = Account.where(name:"猫宁")
=> #<ActiveRecord::Relation [#<Account id: 1, name: "猫宁", email: "12345@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-26 15:55:30", updated_at: "2018-12-26 15:55:30">]>
#获取集合中第一个name为"猫宁"的对象
irb(main):009:0> acc = accs.first
=> #<Account id: 1, name: "猫宁", email: "12345@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-26 15:55:30", updated_at: "2018-12-26 15:55:30">
#然后获取该对象的邮箱,即accounts表中的email字段
irb(main):010:0> email = acc.email
=> "12345@qq.com"

#上面3步可以整合成一句
irb(main):011:0> email = Account.where(name:"猫宁").first.email
=> "12345@qq.com"
#也等同于,find_by相当于where().first
irb(main):012:0> email = Account.find_by(name:"猫宁").email
=> "12345@qq.com"
#如果没有相对应的条件会返回一个nil对象
irb(main):013:0> accounts = Account.find_by(name:"猫宁喵喵喵")
=> nil
#对nil进行.first.email操作会报错
irb(main):014:0> email = Account.where(name:"猫宁喵喵喵").first.email
NoMethodError: undefined method `email' for nil:NilClass
    from (irb):14
(3)修改数据

修改一个对象用update,修改对象集合用update_all

#将name为"猫宁"的对象,修改name为"可爱的猫宁"
#如果知道这个对象的id,那直接用find找出对象修改即可
irb(main):018:0> Account.find(1).update(name:"可爱的猫宁")
=> true
#查询符合条件的account对象集合,修改名字为"可爱的狗宁"
irb(main):019:0> Account.where(name:"狗宁").update_all(name:"可爱的狗宁")
=> true
(4)删除数据
#删除第一个name为"可爱的猫宁"的对象
irb(main):019:0> Account.where(name:"可爱的猫宁").first.delete
=> #<Account id: 1, name: "可爱的猫宁", email: "12345@qq.com", password: nil, role: nil, status: nil, created_at: "2018-12-26 15:55:30", updated_at: "2018-12-28 10:18:34">
#删除符合name为"可爱的狗宁"条件的对象集合。
irb(main):020:0> Account.where(name:"可爱的狗宁").delete_all
=> 1
(5)数据排序
#将查询结果根据创建时间正序排序
Account.where(name:"猫宁").order(created_at: :asc)
#将查询结果根据创建时间倒序排序
Account.where(name:"猫宁").order(created_at: :desc)
#将查询结果先根据创建时间倒序排序,再根据修改时间正序排序
Account.where(name:"猫宁").order(created_at: :desc,updated_at: :asc)
(6)数据分组及相关应用
#将account数据根据email、name的值分组
Account.where(name:"猫宁").group(:email,:name)
#返回一个哈希。key为email name值的数组,value为对应数据的条数
Account.where("name like '%管理员%'").group(:email,:name).count
=> {["123456781@qq.com", "管理员2"]=>1, ["123456782@qq.com", "管理员3"]=>1, ["12345678@qq.com", "管理员1"]=>1}
(7)其他常用方法
1)map,返回对应字段的数组
irb(main):023:0> Account.where("name like '%管理员%'").collect(&:name)
=> ["管理员1", "管理员2", "管理员3"]
2)select,只返回想要展示的字段
irb(main):025:0>  Account.where("name like '%管理员%'").select("name,email")
=> #<ActiveRecord::Relation [#<Account id: nil, name: "管理员1", email: "12345678@qq.com">, #<Account id: nil, name: "管理员2", email: "123456781@qq.com">, #<Account id: nil, name: "管理员3", email: "123456782@qq.com">]>
上一篇下一篇

猜你喜欢

热点阅读