基本的数据检索 |
主键(key)搜索 | Class.find(keys) 返回主键所对应的数据(一对一)
|
指定键搜索 | Class.find_by(key, value [,...]) 搜索指定的键对应的值 可以指定多个键来追加限制 返回找到的第一个 |
搜索不存在则创建 | Class.find_or_create_by(同上) |
| |
| |
复杂条件下的数据检索 |
设定基本条件式 | Class.where(exp) ● joins/includes等关联搜索的参数写法 where(关联表格名: {关联处的搜索条件} )
cars = cars.includes(:equipment_spec).where(equipment_specs: { power_window: true })
返回找到的全部(非数组?)
exp | 条件式 哈希表形式 | 哈希表多种形式 |
多个键 | a: v1, b: v2, ... | 键内范围 | a: v1..v2 或者a: (v1..v2) | 键内指定多个元素 | a: [v1, v2, v3, ...] | | | | | | | | | | | | | | |
| | | | | | | |
用占位符生成条件式 | Class.where(exp [, value, ...]) 占位符: ?或者符号(symbol) :sample 注意: 一定要用占位符,别把输入的字符直接展开进去。SQL可能会爆炸的233 不等于是not, 只用于不是nil http://railsdoc.com/references/where
例 | 'israre = ? AND def >= ?', false, 1000 | | 'israre = :sample1 AND def >= :sample2', sample1: false, sample2: 1000 | | Page.where("title not ?", nil) | | | | | | | | | | | | | | |
|
where的否定 | Class.where.not(...) 参数和where一样 |
or | Class.where(...).or(Class.where(...))
ModelTest.where('ap <= ?', 1000).or(ModelTest.where('def > :def', :def => 4000)) |
排序 | Class.where(...).order(sort)
参数 |
sort | 排序式 例 :test => :asc test: :asc 默认 :asc, 可省略 | 格式 | 属性: 顺序 | :asc | 升序 | :desc | 降序 | | |
| | | | | | | | | | | | | | | | | | |
|
重排 | Class.where(...).order(sort).reorder(sort) 写法和order一样 作用是覆盖前面的order 如果只是想清空前面的order,指定nil |
指定读取的列 | Class.where(...).select(cols) 默认获取所有的列, 用这个方法可以指定具体要获得的列
cols | 指定的列 :hp, :mp,.... | select中可以使用SQL函数 | 设置列名称 AS |
呼出列
| select中使用SQL函数 | 例: Book.select('AVG(sample) AS avg_sample') 用AS设定名称 | | | | |
|
去除重复 | Class.where(...).distinct(flag) Class.select(...).distinct(flag)
flag | true 去除重复 false 保留重复 默认true | | | | | | | | |
|
获取特定范围 | limit/offset 和order一起用才有现实意义 limit(rows) offset(off)
rows | 最多获取的行数 | off | 开始获取的位置(从0开始) | | | | | | | | | | | | | | | | | ModelTest.where('hp >= ? AND mp >= ? AND ad >= ?', 1000, 200, 1500).offset(1).limit(1) |
获取开头/结尾数据 | Class.first Class.last (也可以用limit(0)) 不能惰性读取,必须放在方法链最后 |
分组 | Class.where(...).group(key) 可以指定多个 :a, :b, :c, ... |
进一步提取信息 | Class. group (key).have(exp) exp写法参照p206 # TODO: @having = ModelTest.all.group(:israre).having('hp >= ?', 0)\ |
select中使用SQL函数 | 例: Book.select('AVG(sample) AS avg_sample') 用AS设定名称 |
去除条件 | Class.where(...).select(...)unscope(...).unscope(...) 注意:unscoped是删除之前的所以条件
例 ModelTest.where('def <= :def AND israre = :israre', :def => 2000, :israre => false).select(:mp, :mdf).unscope(:select).unscope(where:) | 注意: 如果where里面用最简单的哈希定义,则unscope可以直接删除where的哈希值 | ModelTest.where(israre: false).unscope(where: :israre) | 允许的参数 :where, :select, :group, :order, :lock, :limit, :offset, :joins, :includes, :from, :readonly, :having | |
|
返回空对象 | Class.none Class.where(...)....none 注意: null是空,Class.none这类是空对象(NullObject),可以呼出each等而不出错 |
| |
| |
| |
| |
| |
| |
获取数据的其他方法 |
以数组形式取出列 | Class.where(...).pluck(column [,...]) 例:ModelTest.all.pluck(:israre, :mp) |
确认指定的数据是否存在 | Class.where(...).exists? |
自定义模型搜索方法 |
命名空间 (Named Scope) | scope :name, ->{ ... } scope :rare, -> { where('israre = :israre', israre: true) } 位置: /app/models/... 调用: sample = Class.where(...).scope-name |
设置默认方法 | default_scope { ... } 位置: /app/models/... 例: default_scope { order_with_hp } scope :order_with_hp, ->{ order(:hp) } |
计算结果类 |
获取结果的行数(数量) | Class.where(...).count Class.where(...).size Class.where(...).length 推荐用size,基本没有错 |
计算类 |
平均值 | average(col) | 最大值 | minimum(col) | 最小值 | maximum(col) | 合计值 | sum(col) | | | 一般和group连用 | ModelTest.all.group(:israre).average(:hp) | 注意 | 返回的是哈希表{group的值: 统计值 [, ...]} | | | | | | |
|
直接使用SQL命令 | 一般都用query method, 尽量不要直接用SQL命令 find_by_sql(sql)
sql | '....', val1 [, val2 ...] | | | | | | | | |
|
| |
| |
| |
记录(record)的登陆,更新,删除 |
基础 |
新建 | Class.new/build Class.new(...) Class.build(...) 哈希表形式指定 {:hp => 54321, :mp => 12345, israre: false} @new = ModelTest.new({:hp => 54321, :mp => 12345, israre: false})
![Rails5 <wbr>Model <wbr>Document Rails5 <wbr>Model <wbr>Document](https://i-blog.csdnimg.cn/blog_migrate/a4c26d1e5885305701be709a3d33442f.gif)
|
新建+保存 | Class.create |
登陆(保存) | Class#save 返回true/false 注: @sample.save!失败返回例外(用于transaction) 例: @sample.save |
更新 | @sample.update(...) 返回true/false 哈希表形式指定 {:hp => 54321, :mp => 12345, israre: false} 用于已经存在的记录(record) |
删除 | @sample.delete
delete(keys) 单纯删除(直接执行SQL, 不经过Active Recode) destroy(keys) 先选择后删除, 新手还没理解delete的时候全用destroy就行
例子: sample.delete Class.delete(id) 注: 用对象呼出时候不用指定id |
进一步的操作 |
全部更新 | Class.where(...).update_all(updates) 返回改动的行数 |
删除 |
delete(keys) | 单纯删除(并返回被删的) Member.first.delete
Member Load (0.3ms) SELECT `members`.* FROM `members` ORDER BY `members`.`id` ASC LIMIT 1
SQL (0.6ms) DELETE FROM `members` WHERE `members`.`id` = 207
| destroy(keys) | 先选择后删除(并返回被删的) rails相关处理必须用这个才有(transaction, callback) Member.first.destroy
Member Load (0.4ms) SELECT `members`.* FROM `members` ORDER BY `members`.`id` ASC LIMIT 1
(0.2ms) BEGIN
SQL (0.3ms) DELETE FROM `members` WHERE `members`.`id` = 206
(0.4ms) COMMIT
|
例子: sample.delete Class.delete(id) 注: 用对象呼出时候不用指定id |
全部删除 |
delete_all | 直接一次性删除 Member.delete_all
SQL (0.2ms) DELETE FROM `members`
| destroy_all | 先选择然后一个一个删除(并return 被删除的) Member.destroy_all
Member Load (0.5ms) SELECT `members`.* FROM `members`
(0.2ms) BEGIN
SQL (0.2ms) DELETE FROM `members` WHERE `members`.`id` = 101
(1.3ms) COMMIT
(0.1ms) BEGIN
SQL (0.2ms) DELETE FROM `members` WHERE `members`.`id` = 102
(0.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) DELETE FROM `members` WHERE `members`.`id` = 103
(0.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) DELETE FROM `members` WHERE `members`.`id` = 104
(0.4ms) COMMIT
(0.2ms) BEGIN
SQL (0.3ms) DELETE FROM `members` WHERE `members`.`id` = 105
(0.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) DELETE FROM `members` WHERE `members`.`id` = 106
(0.4ms) COMMIT
(0.1ms) BEGIN
SQL (0.3ms) DELETE FROM `members` WHERE `members`.`id` = 107
|
|
transaction 事务 | def transaction Class.transaction do .... raise ... .... raise ... ... end rescue => e ... end
用发出异常来终止transaction 也可以用模块对象来呼出transaction
经常用@sample.save! 失败返回例外
事务隔离等级 | 用:isolation标签指定 :read_uncommitted :read_committed :repeatable_read :serializable | | | | | | | | |
|
同时运行的管理 |
乐观锁 |
模块要追加列 | 追加lock_version:intefer 用命令行生成时候追加 已有的表格里也可以增加 | 在迁移文件中设置默认值 | 原来:t.intefer :lock_version 更改成:t.intefer :lock_version, default: 0 | 迁移 | rails db:migrate | 设置/改变成隐藏输入框 | 《%= f.hidden_field :lock_version》 如果有显示lock_version的,要删掉 | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | |
|
定义枚举的的域 | 用与设置数字与符号的对应
设置过程 | 以status:integer为例
设置默认值(非必须) 位置:db/migrate/ |
t.integer :status, default 0, null: false
| 设置枚举 位置:app/models/ | 用数组的话值是index(0开始)
enum status: [:draft, :published, :deleted] // 指定值用hash
enum status: {draft: 0, published: 1, deleted: 2}
| | | | | | | | | | | | | | | | |
| 获取enum的值 | @sample = @sample.find_by(...) @sample.status | 设置值 | @sample.status = 1 @sample.status = :published @sample.published! 注: 设定没有定义好的值会出错, ArgumentError | 列举值作搜索范围 | @sample = Sample.published @sample = Sample.published.where(...) | 注意: | 设置enum以后validates的是字符串, 不是integer | | | | | | | | | | |
|
其他更新类方法 |
P245 | 暂略 # TODO: |
| |
实现验证功能(validation) |
ActiveModel可用的validation | 通用参数: 注: 可以直接设置成全部适用, 如 validates :id, allow_blank: true, length: { is: 10 }, uniqueness: true 或对特地验证适用, 如 validates :id, length: {allow_blank: true, is: 10}, uniqueness: true
allow_nil | nil时跳过validation | allow_blank | nil和empty时跳过validation | message | 修改报错信息 | on | validation的触发时刻
create | 新建时 | update | 更新时 | save | create+update |
默认=:save 例: acceptance一般只要新建时同意条款 | if | 条件成立时进行validation 参数:
字符串 |
validates :sample, presence: { if: "sample.method" }
作为代码运行 | Proc式 | 直接运行, 参数是当前的instance | symbol | symbol对应的方法 |
| unless | 条件不成立时进行validation |
with_options:
with_options(on: :create, if: 'true') do |oc|
oc.validates :name, presence: true
oc.validates :user_id, presence: true
end
ActiveModel可用的validation:
acceptance | 是否对checkbox打钩 参数:
不符合时的信息:
注: ● 不一定需要model有此列(自动生成同名假想列)
| confirmation | 待测text_field必须与_confirmation完全一致(如注册时的密码等) 参数: 无 不符合时的信息:
doesn't match confirmation
● 验证所用列不需要model有此列(自动生成加后缀_confirmation的假想列) | exclusion | 值是否不在指定数组/范围里 参数:
不符合时的信息:
| inclusion | 值是否在指定数组/范围里 参数:
不符合时的信息:
is not included in the list
| format | 是否符合正规表达式 参数:
不符合时的信息:
| length | 检验字符串的长度 参数:
minimum | 最小长度 | maximum | 最大长度 | in | 长度范围(Range) | tokenizer | 字符串分割方式(lamda式) | is | 指定长度 | too_long | 不符合maximum时的错误信息 | too_short | 不符合minimum时的错误信息 | wrong_length | 不符合is时的错误信息 |
不符合时的信息:
is too short(minimum is xxx characters)等
| numericality | 检查数值大小/类型 参数:
only_integer | 只能是整数 | greater_than | 必须大于 | greater_than_or_equal_to | 必须大于等于 | euqal_to | 必须等于 | less_than | 必须小于 | less_than_or_equal_to | 必须小于等于 | odd | 必须是奇数 | even | 必须是偶数 |
不符合时的信息:
| presence | 值非null 参数: 无 不符合时的信息:
| absence | 值必须为null 参数: 无 不符合时的信息:
| uniqueness | 值必须唯一(unique) 参数:
scope | 决定unique的其他列
# 只需要此列值唯一
validates :column1, uniqueness: true
# 和一个列绑定
validates :column2, uniqueness: {allow_blank: true, scope: :a}
# 和多个列绑定
validates :column3, uniqueness: {allow_blank: true, scope: [:a, :b]}
设定了以后则, unique是指两列的组合(a, b)唯一 | case_sensitive | 是否区分大小写 默认=true |
不符合时的信息:
|
|
声明validate |
validates field [, ...] name: params [, ...]
参数含义:
filed | 需要检验的field名(可以多个) | name | validate类型 | params | 相关validate类型的参数(没有就指定true) |
|
validate触发时机 |
触发时机 |
create, create! | save, save! | update, update! |
| 不触发的method |
increment! , decrement! | increment_counter, decrement_counter | toggle! | touch | update_all | update_attribute | update_counters | update_column, update_columns | save(validate: false) |
| 手动触发 |
valid? | 是否符合validation | invalid? | 是否不符合validation |
|
|
errors | errors (ActiveModel::Errors类) 前提: 设定了validates, 不然不会有任何错误
是否有错 |
| 获取错误数量 |
sample.errors.count
sample.errors.size
| 获取完整信息(错误信息的文本数组) |
sample.errors.full_messages
sample.errors.to_a
| 获取特定列的错误 |
sample.errors[:column_name]
sample.errors.details[:column_name]
| 手动添加错误 |
sample.errors.add(:column_name, 'error_message')
sample.errors[:column_name] << 'error_message'
| 清除错误 |
注: 只是清除errors里的,实际错误并没有消失 | | |
|
自定义validator1 | 直接呼出方法
validates :method_name [, ...]
|
自定义validator2 | 设置
# config/application.rb
# ...
module Core
class Application < Rails::Application
# ...
# add custom validators path
config.autoload_paths += Dir["#{config.root}/app/models/validators"]
config.enable_dependency_loading = true
# ...
end
end
创建文件
# app/models/validators/sample_validator.rb
class SampleValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
puts "UUID custom validate fired, options: #{options}" # 获取options的方法
record.errors[attribute.to_sym] << "test" # 错误通过此方法发出
end
end
使用
# sample.rb
# ...
class Sample < ApplicationRecord
# ...
validates :user_id, sample: {ko: "ok", sample1: 1}
# ...
end
# 运行 rails c
a = Sample.new
a.valid? # => false
# UUID custom validate fired, options: {:ko=>"ok", :sample1=>1}
|
定义不与数据库关联的model | # TODO: 需要的时候完成此项 2019/02/21 |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
用关联(association)处理复杂表格 |
命名规则 |
外部键 | sample_id 注: 主键默认为id | 中间表 (过渡表) | 用_按字母顺序连接 modelTest_viewTest | | | | | | | | | | | | | | | | |
|
参照的设置 | belongs_to assoc_id [,opt] 例: belongs_to :modeltest1 一对一关系
参数 |
| 位置 | 写在被参照的一方(即belongs_to的一方含有对方id) 含义: sample_id属于... | | | | | | | | | | | | | | | | |
|
一对多 | has_many assoc_id [,opt]
参数 |
| 位置 | 写在被参照的一方 由此被参照方可以获取参照方的数据 | | | | | | | | | | | | | | | | |
|
一对一 | has_one assoc_id [,opt]
参数 |
| 位置 | 写在被参照的一方 由此被参照方可以获取参照方的数据 | | | | | | | | | | | | | | | | |
|
多对多 m:n | has_and_belongs_to_many assoc_id [, opt]
参数 |
| 步骤 |
创建中间表 (过渡表) | 用_按字母顺序连接 modelTest_viewTest | 关联双方定义处 定义关联 | has_and_belongs_to many | | | | | | |
| | | | | | | | | | | | | | | | |
|
多对多2 m:n | a---b---c这种情况下,直接关联a---c has_many assoc_id, through: middle_id [, opt] 例 b定义处 belongs_to :a belongs_to :c a定义处 has_many :b has_many :c through: :b c定义处 has_many :b has_many :a through: :b |
由关联自动定义的方法 | p282~283 # TODO: 略 |
关联可用的opt |
opt | belongs_to | has_one | has_many | has_and_belongs_to_many | # TODO: Supply [选项的意义] | as | X | O | O | O | 多态(自己的名字) | association_foreign_key | X | X | X | O | m:n关联下的外部键 例: Book里的author_id | autosave | O | O | O | O | 父模型保存/删除时自动保存 | class_name | O | O | O | O | 关联模型的类型 | counter_cache | O | X | O | X | 获取数量时是否使用cache | dependent | O | O | O | X | 删除模型时关联的模型也删除
:nullify | 默认, 什么都不做 foreign_id 变为nil | :destroy | 关联的model被删除时, 则呼出destory来删除 | :delete | 关联的model被删除时, 则呼出delete来删除 ● has_many时呼出的是delete_all ● 直接执行SQL, 所以不会对自身关联的其他model有影响 | | |
| foreign_key | O | O | O | O | 使用的外部键名称 | join_table | X | X | X | O | 使用的结合表格名称 | optional | O | X | X | X | 不检查关联的对象是否存在 | primary_key | O | X | O | X | 关联时使用的主键列的名称 | polymorphic | O | X | X | X | 多态关系的有效化? # TODO: Supply [选项的意义] | readonly | X | X | X | O | 设置关联的对象只可读 | required | O | X | X | X | 检查关联对象是否存在 | touch | O | X | X | X | 保存的时候关联的对象的create_at/updated_at也更新 | source | X | O | O | X | 对于 has_many:through , 指定源头(即本model的名称) 只有在指定的关联名称不是对方model名(即使用class_name时)才需要 | through | X | O | O | X | | validate | O | O | O | O | 设置保存的时候是否检查关联的对象 | | | | | | | | | | | | | | | | | | |
|
与相关model结合 | joins(exp) 前提是已经建立association ● 参数是关联名(如has_one则为单数) ● 搜索时候套上的symbol是表格名
cars = cars.includes(:equipment_spec).where(equipment_specs: request)
exp | 结合条件
A. 关联名(Symbol) |
Car.joins(:equipment_spec).select('cars.*, equipment_specs.*')
| B.关联名1: 关联名2 | 关联名1和关联名2也关联
EquipmentSpec.joins(car: :maker) .select('equipment_specs.*, cars.id AS car_id, makers.name AS maker_name')
| C. 字符串 SQL | 用于INNER JOIN以外的结合(LEFT JOIN/ RIGHT JOIN) | | |
| | 必须要带上select, 不然虽然结合了但只获取了当前的model
EquipmentSpec.joins(:car).select('equipment_specs.*, cars.*')
|
用join也能达到association的效果 |
与相关model结合 (左外部结合) Rails 5.0 | left_outer_joins(exp) alias: left_joins(exp) 结合是左外部结合 LEFT OUTER JOIN 写法和上面一样, 但不能用C写法 ● 参数是关联名(如has_one则为单数) ● 搜索时候套上的symbol是表格名 |
和相关model一起获取 | includes(exp) 结合是左外部结合 LEFT OUTER JOIN 写法一样,但不能用C写法 ● 参数是关联名(如has_one则为单数) ● 搜索时候套上的symbol是表格名 |
| |
回调(call back) |
| 用例:注册时候每天的空白自动生成 注册或者更新时候自动发邮件 注册更新时保存为履历等 |
回调函数 |
主要方法 |
各时间点所对应函数
新建,更新,删除 | create/create!, destroy/destroy!, destroy_all increment!, decrement!, save/save!, toggle!, update/update!, update_attribute, valid? 红色: 之前跳过的 | after_find | 搜索数据库后 all,first, find, find_by, find_by_sql | after_initialize | new来生成或者读取数据库后 |
回调函数
创建 | 更新 | 删除 | 运行时间 | before_validation | | | 验证处理前 | after_validation | | | 验证处理后 | before_save | | | 保存前 | around_save | | | 保存前后 | before_create | before_update | before_destroy | 新建/更新/删除前 | around_create | around_update | around_destroy | 新建/更新/删除前后 | after_create | after_update | after_destroy | 新建/更新/删除后 | after_save | | | 保存后 | after_commit | | | commit后? | after_rollback | | | 回调后 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
|
| |
| |
迁移文件 |
位置 | app/db/migrate/ |
生成migration文件 | 本页最上面找 |
构造 |
schame处理 | change方法内部 | 迁移文件的版本信息 |
class CreateEquipmentCars < ActiveRecord::Migration[5.0]
#...
end
ActiveRecord::Migration[5.0]部分 用后面的Migration[版本]来控制
| | | | | | | | | | | | | | | | |
|
逻辑方法 |
|
主要方法 | tname: table name frname: 外部table name fname: field name type: field的数据类型 opt: field的option i_opt: index option t_opt:table option fr_opt: foreign key option
create_table change_table |
create_table tname [,toption] do |t|
t.type fname [, opt, ...]
...
end
create_table, change_table内部可用方法搜[create_table,change_table代码块内可用的方法]
tname | 表格名 | toption 表格选项 | 选项
id | 是否自动生成主键 默认: true | primary_key | 主键的名称 默认: id
改变默认主值: | set_prime_key '...' | 位置: | 模型类 Model Class |
| temporary | 是否作为暂时的表格 默认: false | force | 创建前是否删除已有的表格 默认: false | options | 其他的表格选项 暂时不管 p301 # TODO: | | |
| | |
| 追加列 | add_column(tname, fname, type [, opt]) | 追加索引 | add_index(tname, fname [, i_opt]) | 追加外部键 | add_foreign_key(tname, frname [, fr_opt]) tname: 表格名 frname: 参照的表格名 注: foreign_key追踪的primary_key(默认xxx_id),必须设有index | 追加 create_at update_at | add_timestamps(tname) | 改变已有列 | change_column(tname, fname, type [, opt]) | 是否允许该列可以有null | change_column_null(tname, fname, null) null: true为不允许无效值 false允许 | 改变默认值 | change_column_default(tname, fname, default) | 改变表格 | change_table(tname)
create_table, change_table内部可用方法搜[create_table,change_table代码块内可用的方法] | 确认指定列是否存在 | column_exists?(tname, fname [, type [,opt]]) | 创建表格 | create_table(tname [,t_opt]) 最上面那个就是 | 创建中间表格 | create_join_tabble(tname1, tname2 [, t_opt]) | 删除已有表格 | drop_table(tname [, opt]) | 确认索引是否存在 | index_exists?(tname, fname [i_opt]) | 删除一个列 | remove_column(tname, fname [, type, opt]) | 删除多个列 | remove_columns(tname, fname [,...]) | 删除已有的索引 | remove_index(tname [, i_opt]) | 删除外部键 | remove_foreign_key(tname, frname) | 重命名列 | rename_column(tname, old, new) | 重命名索引 | rename_index(tname, old, new) | 重命名表格 | rename_table(tname, new) | 执行sql指令 | execute(sql) | t.string等的 opt |
limit | 列的位数 字符: 字符长度 数字: 数字的字符长度(包含一切元素,如小数点) | defalut | 默认值 | null | 是否允许null值 默认true | precision | 数值的总位数 123.123 六位 | scale | 小数点以下的位数 | polymorphic | belong_to关联所用的列 | index | 是否生成索引 | comment | 列的说明 | after | 指定在哪一列的后面 |
| t_opt table option |
id | 是否自动生成主键 默认: true | primary_key | 主键的名称 默认: id
改变默认主值: | set_prime_key '...' | 位置: | 模型类 Model Class |
| temporary | 是否作为暂时的表格 默认: false | force | 创建前是否删除已有的表格 默认: false | options | 其他的表格选项 暂时不管 p301 # TODO: |
| i_opt index opt |
unique | 是否保证每一个索引独一无二 | name | 索引名字 | length | 索引包含的列的长度 length: {col1: 10, col2: 20} 好处: 加快运行速度 |
| fr_opt |
collum | 外部key的名字 默认: 参照的model_id | primary_key | 参照model的主key 默认: id | name | ?? | on_delete | 参照的model删除时的动作 默认:restrict
:nullify | 设置成null | :cascade | 更新 | :restrict | 报错 错误信息: 违反外部key制约 |
| on_update | 参照的model更新时的动作 同上 |
|
|
create_table, change_table 代码块内可用的方法 | create_table,change_table代码块内可用的方法 例:
change_table tname do |t|
...
end
● 可用的方法
t.index | 例: t.index 相当于不在change_table代码块下的add_index | t.change | 相当于不在change_table代码块下的change_column | t.change_default | 相当于不在change_table代码块下的change_column_default | t.rename | 相当于不在change_table代码块下的rename_column | t.remove | 相当于不在change_table代码块下的remove_column | t.remove_references | 相当于不在change_table代码块下的remove_foreign_key | t.remove_index | 相当于不在change_table代码块下的remove_index | t.remove_timestamps | 相当于不在change_table代码块下的remove_timestamps | | |
● 可用的列定义
可利用的数据类型和对应关系
迁移(fname) 写在迁移文件里 例: t.string :str | SQLite | Ruby | integer | INTEGER | Fixnum (就是Ruby里的普通整数) | decimal | DECIMAL | BigDecimal (高精度小数) | float | FLOAT | Float | string | VARCHAR(255) | String | text 注: 不能设为index 因为长度太长 | TEXT | String | binary | BLOB | String | date | DATE | Date | datetime | DATETIME | Time | timestamp | DATETIME | Time | time | TIME | Time | boolean | BOOLEAN | TrueClass/FalseClass | 特殊的 | | | timestamps | 自动创建created_at和updated_at 列生成与更新的时候自动设定 | references 相当于 belongs_to | 外部键 例
t.references :book #生成book_id,相当于 t.belongs_to :book
注: 参数是参照名, 可以不是table名。实际rails使用的都是单数来呼出 选项(()内为默认值): index: (true), polymorphic: (false) | | | | | | |
选项opt
limit | 列的位数 字符: 字符长度 数字: 数字的字符长度(包含一切元素,如小数点) | defalut | 默认值 | null | 是否允许null值 默认true | precision | 数值的总位数 123.123 六位 | scale | 小数点以下的位数 | polymorphic | belong_to关联所用的列 | index | 是否生成索引 | comment | 列的说明 | after | 指定在哪一列的后面 |
|
模型处改变迁移文件数据类型 | attribute(name, type [,default: value]) |
迁移文件的生成 | 和模型一起生成 rails generate model name field:type [...] [options] 单独生成 rails generate migration name [field:type ...] [options] |
删除或者增加列 | 生成迁移文件时候命名 rails g model AddXxxxTo表格名
增加 | AddXxxxTo表格名 | 删除 | RemoveXxxxFrom表格名 | | rails generate migration AddBirthToAuthors birth: date | | | | | | | | | | | | | | |
|
升级与回滚 |
原则 | 基本上所有方法都写在change里面 | 可以自动被回滚的方法 |
add_column | | add_index | | add_reference | | add_timestamps | | change_table | 呼出change/change_default/remove的不能自动回滚 | create_table | | create_join_table | | remove_timestamps | | rename_column | | rename_index | | rename_reference | | rename_table | |
| 无法回滚时的方法 |
增加回滚的信息 remove_column/drop_table |
remove_column | 在后面写上被删除的列的详细信息即可
remove_column(tname, fname [, type, opt])
注意: remove_columns无法追加详细信息 | drop_table | 写法和create_table一样 |
| 升降级处理分开写 reversible |
reversible do |dir| # dir: 管理回滚的对象
dir.up do
... # 升级时的处理
end
dir.down do
... # 降级时的处理
end
end
| 写在单独的up/down方法里 |
def up
... # 升级时的处理
end
def down
... # 降级时的处理
end
|
| | | | | | |
|
schema来构筑数据库 |
schema文件位置 | 位置/app/db/schema.rb | 意义 | 自动获取最新的数据库表格信息 和迁移文件一样可能会有无法展现的对象(object) | 放弃现在的数据库, 用schema来构筑最新的数据库 | rails db:reset windows环境下加DISABLE_DATABASE_ENVIROMENT=1
注意: 只是重构,测试数据要另外读取 | | | | | | | | | | | | | | |
|
数据库初始化 |
迁移和初始化一起 | rails db:setup 相当于 rails db:create:all rails db:migrate rails db:seed 或者 rails db:fixtures:load |
seed file | 初始数据来初始化(也可以用fixture)
位置 | db/seed.rb 可能需要自己新建 | 形式 | ruby脚本 | 内容 | 只需要写生成/保存数据的代码
如Sample.new(...) | 运行 | rails db:seed | | | | | | | | | | | | | | |
|
fixture | 测试数据来初始化(也可以用seed)
位置 | test/fixtures/ 表格名.rb | 形式 | yaml脚本 注: 缩进只能用手打两个空格 | 内容 | 标签: 域名: 数值 ...
外部键间接写法 仅yml文件内可用 | 模型名: 标签 | 缩进 | 手打的2个空格 | | | | | | | | | | | | | | | | |
| 运行 | rails db:fixtures:load
指定读取文件 位置: /test/fixtures/... | FIXTURES=sample1, samples2, ... 默认: 读取全部 | 指定测试环境 | RAILS_ENV=prodution/test/development 默认: development | | | | | | |
| | | | | | | | | | | | |
|
Data/Time相关的有用的方法 |
yesterday | 昨天 |
tomorrow | 明天 |
prev_xxxx | 前年/月/周(year,month,week) |
next_xxxx | 下年/月/周(year,month,week) |
beginning_of_xxxx | 年/季/月/周的开始一天(year, quarter, month, day) |
end_of_xxxx | 年/季/月/周的最后一条(year, quarter, month, day) |
| |
n.xxx.ago Numeric | n个年/月/日/时/分/秒以前 years, months, days, hours, minutes, seconds 也可以用单数 |
n.xxx.from_now Numeric | n个年/月/日/时/分/秒以后 years, months, days, hours, minutes, seconds 也可以用单数 |
| |