class: center middle
class: center middle
不同的 DBA
数据库表的命名方式真的千差万别
create table driver(...);
create table order_detail(...);
create table person(...);
而 Rails
默认是这样
Driver ................ drivers
OrderDetail ..... order_details
Person ................ people
.left-column[
] .right-column[ 如果数据库中只有少数表名为单数模式,则可以单独在 migrate 时做修改。
migration
class CreateGroups < ActiveRecord::Migration
def change
create_table :groups do |t|
# ...
end
end
rename_table :groups, :group
end
或者
create_table :group do |t|
# ...
end
model
class Group < ActiveRecord::Base
self.table_name = 'group'
# attr_accessible ....
end
.left-column[
] .right-column[ 如果大部分的表都为单数,就没有必要逐个修改表名,rails 提供了统一的配置方法,来自动生成单数表名,对于个别复数或者不规则的情况,可能参考上一切的方法修改。
config/application.rb
class Application < Rails::Application
# ...
config.active_record.pluralize_table_names = false
end
设置为单数模式后 generator 会自动生成单数表名
rails g model Customer name:string
生成的 migrate
class CreateCustomer < ActiveRecord::Migration
def change
create_table :customer do |t|
t.string :name
t.timestamps
end
end
end
.left-column[
] .right-column[ Wordpress 及一些 CMS 会有表名前缀或者后缀的规则
config/application.rb
class Application < Rails::Application
# ...
config.active_record.table_name_prefix = 'foo_'
config.active_record.table_name_suffix = '_bar'
end
执行
$ rails g modal Detail name:string
# migration output
create_table :details do |t|
t.string :name
# ...
end
# database output
create table foo_details_bar ( ... );
前后缀作用于全局,但可在 model 中显式指定表名绕过规则。
self.table_name = 'details'
detail_id
, id
字符型:UUID、按规则拼接
复合型:复合主键
.left-column[
]
.right-column[
migration
class CreateDetails < ActiveRecord::Migration
def change
create_table :details, :primary_key => :detail_id do |t|
# attributes ...
end
# ...
end
end
model
class Detail < ActiveRecord::Base
# ...
self.primary_key = :detail_id
self.sequence_name = 'YOUR_SEQUENCE_NAME' # Oracle only
alias_attribute :detail_id, :id
# attr_accessible ....
end
**TIP: ** 查找ORACLE表的SEQUENCE
select * from user_sequences
where sequence_name like '%TABLE_NAME%'
.left-column[
] .right-column[ 非默认类型主键无法识别
migration
class CreateDetails < ActiveRecord::Migration
def change
create_table :details, :id => false do |t|
t.string, :code, :limit => 36
# attributes ...
end
execute 'ALTER TABLE details ADD PRIMARY KEY(code);'
# ...
end
end
根据数据库的不同,这里设置主键的语句会有变化
model
class Detail < ActiveRecord::Base
# ..
self.primary_key = :code
# attr_accessible ....
end
.left-column[
]
.right-column[
lib/extras/uuid_helper.rb
require 'rubygems'
require 'uuidtools'
module UUIDHelper
def self.included(base)
base.class_eval do
before_create :set_guuid
def set_guuid
self.code = UUIDTools::UUID.random_create.to_s
end
end
end
end
config/application.rb
config.autoload_paths += %W(#{config.root}/extras)
model
class Detail < ActiveRecord::Base
include UUIDHelper
# attr_accessible ....
end
.left-column[
] .right-column[ 与 UUID 类似,先使用 类型差异 一节中的方法设置一个字符型的主键
model
class Detail < ActiveRecord::Base
before_create :set_code
def set_code
self.code = "#{attr1}-#{attr2}"
end
end
.left-column[
] .right-column[
migration
create_table :detail, :id => false do |t|
t.integer :id1
t.integer :id2
t.string :name
end
execute 'ALTER TABLE detail ADD PRIMARY KEY(id1, id2);'
model
class Detail < ActiveRecord::Base
self.primary_keys = :id1, :id2
end
relations
belongs_to :detail, :foreign_key => [:id1, :id2]
query
Detail.find(1, 1)
Rails默认时间戳
created_at, updated_at
公司数据库中的时间戳
created_date, last_modified_date
解决方法
config/initializers/active_record.rb
module ActiveRecord
module Timestamp
private
def timestamp_attributes_for_update #:nodoc:
[:last_modified_date, :updated_at, :updated_on, :modified_at]
end
def timestamp_attributes_for_create #:nodoc:
[:create_date, :created_at, :created_on]
end
end
end
vim配置
" 转换公司的DB描述
function DbConvert()
:%s/^\s*\(\S\+\)\s\+varchar\s\+\(\d\+\)\s*$/ \1:string{\2} \\/g
:%s/^\s*\(\S\+\)\s\+int\s*$/ \1:integer \\/g
:%s/^\s*\(\S\+\)\s\+datetime\s*$/ \1:datetime \\/g
:%s/^\s*\(\S\+\)\s\+tinyint\s*$/ \1:boolean \\/g
endfunction
调用
:call DbConvert()
# source
column1 varchar 10
column2 int
column3 tinyint
column4 datetime
# output
rails g scaffold Detail \
column1:string{10} \
column2:integer \
column3:boolean \
column4:datetime
单表
rails g model table_name
整库
gem install rmre
rmre -a mysql -d dbname -u user -p pwd -o app/models
# output
class District < ActiveRecord::Base
self.table_name = 'district'
self.primary_key = :district_code
end
rmre 会自动为你配置好主键和表名
attr_accessible
:%s/\(\w\+\)\s*\n/:\1, /g
# source
title
body
# output
:title, :body
理由
- 有的gem不规范,不会认异于 Rails 约定的主键和关系
- 异于约定的表名、主键和关系配置显示指定可以提高速度
显式指定关系
belongs_to :detail, :class_name => Detail, :foreign_key => :detail_id
- Universally Unique Identifier, UUID
- Ruby and Rails Naming Conventions
- Rails Composite Primary Keys
- Ruby on Rails Guides
- Ruby on Rails RDoc
- Ruby on Rails 3 Model Working with Legacy Database
- Getting rails to play with a legacy Oracle database
- Rails and Legacy Databases - RailsConf 2009
name: last-page template: inverse class: center middle
Slideshow created using remark.