rabbit-slide-yancya-evacuate_from_sti 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rabbit +1 -0
- data/README.rd +25 -0
- data/README.rd~ +24 -0
- data/Rakefile +17 -0
- data/config.yaml +19 -0
- data/evacuate_from_sti.rab +321 -0
- data/pdf/evacuate_from_sti-evacuate_from_sti.pdf +0 -0
- data/yancya.jpg +0 -0
- metadata +67 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0b0692b790bd3a14da6769f938b8d0c45812730c
|
4
|
+
data.tar.gz: 5ab1e08304cfa811e5674029f551da72d4faf02a
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: df4f94ca33ad865c0f26a72c2452c953cf6e4f5e842ff822b7a85a97ff7f9c68dfe751ee95516b33f4b5eccac841868025d5ca5ddc4cfdc57ac5957d1f0d6c34
|
7
|
+
data.tar.gz: e93b882f9fed7e9b30585d6c6e8e38346ba7641a9d8bce2d733e24c30ce7a9074197fc315920e617ab9231be48e0f374e66d1e0f695be52629e7c4afcd4db23d
|
data/.rabbit
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
evacuate_from_sti.rab
|
data/README.rd
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
= Evacuate from STI
|
2
|
+
|
3
|
+
RubyHiroba 2014 の生活発表会で発表したスライドです
|
4
|
+
STI についてと、それを避けたらどういう実装がありうるかという話です
|
5
|
+
|
6
|
+
== 作者向け
|
7
|
+
|
8
|
+
=== 表示
|
9
|
+
|
10
|
+
rake
|
11
|
+
|
12
|
+
=== 公開
|
13
|
+
|
14
|
+
rake publish
|
15
|
+
|
16
|
+
== 閲覧者向け
|
17
|
+
|
18
|
+
=== インストール
|
19
|
+
|
20
|
+
gem install rabbit-slide-yancya-evacuate_from_sti
|
21
|
+
|
22
|
+
=== 表示
|
23
|
+
|
24
|
+
rabbit rabbit-slide-yancya-evacuate_from_sti.gem
|
25
|
+
|
data/README.rd~
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
= TODO: スライドのタイトル
|
2
|
+
|
3
|
+
TODO: スライドの説明
|
4
|
+
|
5
|
+
== 作者向け
|
6
|
+
|
7
|
+
=== 表示
|
8
|
+
|
9
|
+
rake
|
10
|
+
|
11
|
+
=== 公開
|
12
|
+
|
13
|
+
rake publish
|
14
|
+
|
15
|
+
== 閲覧者向け
|
16
|
+
|
17
|
+
=== インストール
|
18
|
+
|
19
|
+
gem install rabbit-slide-yancya-evacuate_from_sti
|
20
|
+
|
21
|
+
=== 表示
|
22
|
+
|
23
|
+
rabbit rabbit-slide-yancya-evacuate_from_sti.gem
|
24
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rabbit/task/slide"
|
2
|
+
|
3
|
+
# Edit ./config.yaml to customize meta data
|
4
|
+
|
5
|
+
spec = nil
|
6
|
+
Rabbit::Task::Slide.new do |task|
|
7
|
+
spec = task.spec
|
8
|
+
# task.spec.files += Dir.glob("doc/**/*.*")
|
9
|
+
# task.spec.files -= Dir.glob("private/**/*.*")
|
10
|
+
# task.spec.add_runtime_dependency("YOUR THEME")
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Tag #{spec.version}"
|
14
|
+
task :tag do
|
15
|
+
sh("git", "tag", "-a", spec.version.to_s, "-m", "Publish #{spec.version}")
|
16
|
+
sh("git", "push", "--tags")
|
17
|
+
end
|
data/config.yaml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
---
|
2
|
+
id: evacuate_from_sti
|
3
|
+
base_name: evacuate_from_sti
|
4
|
+
tags: []
|
5
|
+
presentation_date:
|
6
|
+
version: 1.0.0
|
7
|
+
licenses: []
|
8
|
+
slideshare_id: yancyajp
|
9
|
+
speaker_deck_id: yancya
|
10
|
+
ustream_id:
|
11
|
+
vimeo_id:
|
12
|
+
youtube_id:
|
13
|
+
author:
|
14
|
+
markup_language: :rd
|
15
|
+
name: yancya
|
16
|
+
email: yancya@upec.jp
|
17
|
+
rubygems_user: yancya
|
18
|
+
slideshare_user: yancyajp
|
19
|
+
speaker_deck_user: yancya
|
@@ -0,0 +1,321 @@
|
|
1
|
+
= STI を避けたい
|
2
|
+
|
3
|
+
: subtitle
|
4
|
+
I wish I evacuate STI
|
5
|
+
: author
|
6
|
+
yancya
|
7
|
+
# : institution
|
8
|
+
# 所属
|
9
|
+
: content-source
|
10
|
+
RubyHiroba 2014
|
11
|
+
: date
|
12
|
+
2014/09/21
|
13
|
+
: allotted-time
|
14
|
+
18m
|
15
|
+
: theme
|
16
|
+
rabbit
|
17
|
+
|
18
|
+
= 自己紹介
|
19
|
+
|
20
|
+
# image
|
21
|
+
# src = yancya.jpg
|
22
|
+
# width = 150
|
23
|
+
# height = 150
|
24
|
+
|
25
|
+
* @yancya
|
26
|
+
* 何者でも無い1人の Rubyist
|
27
|
+
* 3児の父
|
28
|
+
|
29
|
+
= STI って使ってます?
|
30
|
+
|
31
|
+
* どうですか?
|
32
|
+
|
33
|
+
= STI とは
|
34
|
+
|
35
|
+
* Single Table Inheritance
|
36
|
+
* 単一テーブル継承
|
37
|
+
* モデルクラスを継承で表現し、永続化部分はスーパークラスのテーブル1枚でまかなう
|
38
|
+
|
39
|
+
= STI の実装例(親クラス)
|
40
|
+
|
41
|
+
# coderay ruby
|
42
|
+
class CreateCars < ActiveRecord::Migration
|
43
|
+
def change
|
44
|
+
create_table :cars do |t|
|
45
|
+
t.integer :weight
|
46
|
+
t.string :color
|
47
|
+
t.string :type
|
48
|
+
t.timestamps
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Car < ActiveRecord::Base
|
54
|
+
end
|
55
|
+
|
56
|
+
= STI の実装例(親クラス)
|
57
|
+
|
58
|
+
# coderay ruby
|
59
|
+
class CreateCars < ActiveRecord::Migration
|
60
|
+
def change
|
61
|
+
create_table :cars do |t|
|
62
|
+
t.integer :weight
|
63
|
+
t.string :color
|
64
|
+
t.string :type
|
65
|
+
t.timestamps
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class Car < ActiveRecord::Base
|
71
|
+
end
|
72
|
+
|
73
|
+
= STI の実装例(子クラス)
|
74
|
+
|
75
|
+
# coderay ruby
|
76
|
+
class CreateManualCars < ActiveRecord::Migration
|
77
|
+
def change
|
78
|
+
# スーパークラスのテーブルにカラムを追加するだけ
|
79
|
+
add_column :cars, :number_of_gears, :integer
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
class ManualCar < Car
|
84
|
+
end
|
85
|
+
|
86
|
+
class AutomaticCar < Car
|
87
|
+
end
|
88
|
+
|
89
|
+
= STI の便利さ
|
90
|
+
|
91
|
+
* サブクラス特有のカラムを add_column して、スーパークラスを継承するだけで作れちゃう便利
|
92
|
+
* スーパークラスに共通処理や属性を持たせることで、サブクラスのコードがスッキリ!
|
93
|
+
|
94
|
+
= STI すごい
|
95
|
+
|
96
|
+
* メタデータカラムがあるので、親クラスのインスタンスから、子クラスを特定出来たりする
|
97
|
+
|
98
|
+
# coderay ruby
|
99
|
+
AutomaticCar.create(
|
100
|
+
weight: 1000,
|
101
|
+
color: "blue"
|
102
|
+
) #=> #<AutomaticCar id: 1>
|
103
|
+
|
104
|
+
Car.find(1).tap{|car|
|
105
|
+
break car.type.classify.constantize.find(car.id)
|
106
|
+
}.class #=> AutomaticCar
|
107
|
+
|
108
|
+
= STI の注意点
|
109
|
+
|
110
|
+
# coderay ruby
|
111
|
+
# スーパークラスからサブクラスの属性に触れちゃう
|
112
|
+
Car.find(1).number_of_gears #=> 6
|
113
|
+
Car.find(1).update(number_of_gears: 5)
|
114
|
+
|
115
|
+
# それを防ぐために、守るコードを追加
|
116
|
+
# gem 'protected_attributes'
|
117
|
+
class Car < ActiveRecord::Base
|
118
|
+
attr_accessible :weight, :color
|
119
|
+
end
|
120
|
+
|
121
|
+
class ManualCar < Car
|
122
|
+
attr_accessible :number_of_gears
|
123
|
+
end
|
124
|
+
|
125
|
+
= 外部キー制約
|
126
|
+
|
127
|
+
* ついに Rails 本体に外部キー制約サポートがくるよー
|
128
|
+
|
129
|
+
# blockquote
|
130
|
+
# title = http://weblog.rubyonrails.org/2014/8/20/Rails-4-2-beta1/
|
131
|
+
Support for real foreign keys!
|
132
|
+
add_foreign_key/remove_foreign_key are now available in migrations.
|
133
|
+
|
134
|
+
= 外部キー制約って使います?
|
135
|
+
|
136
|
+
* みなさん、どうですか?
|
137
|
+
|
138
|
+
= STI と外部キー制約
|
139
|
+
|
140
|
+
* 外部キー制約を使うとして
|
141
|
+
* 子クラス特有の属性を定義
|
142
|
+
* その属性が外部キー
|
143
|
+
* その属性に NOT NULL 制約を付けたいとする
|
144
|
+
|
145
|
+
= STI で外部キー制約
|
146
|
+
|
147
|
+
* 親や他の子クラスから INSERT したら NULL が入っちゃう(入らなくてエラー)
|
148
|
+
* いいこと思いついた!外部テーブル側に {id: 99999, value: "無し"} みたいなレコードを入れておいて、外部キーに NULL が入りそうになったら、代わりに 99999 を
|
149
|
+
|
150
|
+
= 例えば、STI を避ける
|
151
|
+
|
152
|
+
* STI を避ける必要は全然無い
|
153
|
+
* 呪われし RDB 厨の業
|
154
|
+
* Nullable column
|
155
|
+
* 正規化
|
156
|
+
* では、しかるべきデータ格納方法とは
|
157
|
+
|
158
|
+
= STI の背景
|
159
|
+
|
160
|
+
# blockquote
|
161
|
+
# title = http://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
|
162
|
+
Relational databases don't support inheritance, so when mapping...
|
163
|
+
|
164
|
+
= RDBMS
|
165
|
+
|
166
|
+
* みなさん、何使ってます?
|
167
|
+
|
168
|
+
= PostgreSQL
|
169
|
+
|
170
|
+
* RDBMS 界の優等生
|
171
|
+
* バージョン毎の日本語ドキュメントが充実
|
172
|
+
* Heroku のデフォルト RDBMS
|
173
|
+
* v9.2 から JSON 型をサポート(v9.3 で更に高機能に)
|
174
|
+
|
175
|
+
= Table Inherited
|
176
|
+
|
177
|
+
* "Relational databases don't support inheritance, so when mapping..."
|
178
|
+
* テーブルの継承 PostgreSQL にはあるんです
|
179
|
+
|
180
|
+
= 継承先テーブルの作成
|
181
|
+
|
182
|
+
# coderay ruby
|
183
|
+
class AddManualCar < ActiveRecord::Migration
|
184
|
+
def up
|
185
|
+
execute <<-SQL
|
186
|
+
CREATE TABLE manual_cars(number_of_gears integer)
|
187
|
+
INHERITS cars
|
188
|
+
SQL
|
189
|
+
end
|
190
|
+
|
191
|
+
def down
|
192
|
+
drop_table :manual_cars
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
class AddAutomaticCar < ActiveRecord::Migration
|
197
|
+
def up
|
198
|
+
execute "CREATE TABLE automatic_cars() INHERITS cars"
|
199
|
+
end
|
200
|
+
|
201
|
+
def down
|
202
|
+
drop_table :automatic_cars
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
= Where a row come from?
|
207
|
+
|
208
|
+
# blockquote
|
209
|
+
# title = システム行 - tableoid
|
210
|
+
この列は特に、継承階層からの選択問い合わせでは便利です。
|
211
|
+
tableoidはテーブル名を得るためにpg_classのoid列に結合することができます。
|
212
|
+
|
213
|
+
= Behavior of Parental Model
|
214
|
+
|
215
|
+
# coderay ruby
|
216
|
+
module Parental
|
217
|
+
def down_cast
|
218
|
+
sub_model.find(self)
|
219
|
+
end
|
220
|
+
|
221
|
+
private
|
222
|
+
def sub_model
|
223
|
+
relation_name = ActiveRecord::Base.connection.execute(<<-SQL).first["relname"]
|
224
|
+
SELECT relname
|
225
|
+
FROM #{self.class.to_s.tableize} p, pg_class c
|
226
|
+
WHERE p.tableoid = c.oid
|
227
|
+
AND p.id = #{self.id}
|
228
|
+
LIMIT 1
|
229
|
+
SQL
|
230
|
+
|
231
|
+
relation_name.classify.constantize
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
= Behavior of Inherit Model
|
236
|
+
|
237
|
+
* 継承したままだと table_name がスーパークラスのもの
|
238
|
+
|
239
|
+
# coderay ruby
|
240
|
+
module PgInherits
|
241
|
+
extend ActiveSupport::Concern
|
242
|
+
|
243
|
+
included do |base|
|
244
|
+
base.table_name = base.name.tableize
|
245
|
+
end
|
246
|
+
end
|
247
|
+
|
248
|
+
= Model Classes
|
249
|
+
|
250
|
+
# coderay ruby
|
251
|
+
class Car < ActiveRecord::Base
|
252
|
+
include Parental
|
253
|
+
end
|
254
|
+
|
255
|
+
class ManualCar < Car
|
256
|
+
include PgInherits
|
257
|
+
end
|
258
|
+
|
259
|
+
class AutomaticCar < Car
|
260
|
+
include PgInherits
|
261
|
+
end
|
262
|
+
|
263
|
+
= テーブル継承の注意点
|
264
|
+
|
265
|
+
* 多重継承ができる
|
266
|
+
* 単にデータベースの機能として見れば便利
|
267
|
+
* 多重継承の無いプログラミング言語とマッピングしづらい
|
268
|
+
|
269
|
+
= テーブル継承の注意点
|
270
|
+
|
271
|
+
* 親テーブルで PRIMARY KEY, UNIQUE の宣言をしていても、子テーブルまでは制約が伝播しません
|
272
|
+
* 親テーブルに外部キーを持って、外部キー制約をつけていても、子テーブルまで制約が伝播しません
|
273
|
+
|
274
|
+
= テーブル継承の注意点
|
275
|
+
|
276
|
+
* NOT NULL
|
277
|
+
* DEFAULT
|
278
|
+
* これらは子テーブルに伝播します
|
279
|
+
|
280
|
+
= 何が起こりうるか
|
281
|
+
|
282
|
+
* PRIMARY KEY, UNIQUE について、親まで遡らないので、子テーブルから重複値を入れ放題
|
283
|
+
* 子テーブルに別途制約を付けても、子テーブル内でしかチェックしないので根本解決にならない
|
284
|
+
|
285
|
+
= 具体的に困ること
|
286
|
+
|
287
|
+
# coderay ruby
|
288
|
+
Car.create #=> #<Car id: 1>
|
289
|
+
AutomaticCar.create(id: 1) #=> #<AutomaticCar id: 1>
|
290
|
+
Car.where(id: 1).count #=> 2
|
291
|
+
|
292
|
+
ただ、DEFAULT は伝播するので、ID シーケンスは親テーブルと共通なので、ID を直接指定して INSERT UPDATE しなければ問題ない。しなければ
|
293
|
+
|
294
|
+
= 回避策
|
295
|
+
|
296
|
+
# coderay ruby
|
297
|
+
module PgInherits
|
298
|
+
extend ActiveSupport::Concern
|
299
|
+
|
300
|
+
included do |base|
|
301
|
+
base.table_name = base.name.tableize
|
302
|
+
# gem 'protected_attributes'
|
303
|
+
attr_protected :id
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
= テーブル継承のこれから
|
308
|
+
|
309
|
+
* PostgreSQL 9.3.2文書 5.8.1 によれば
|
310
|
+
* 「これらの機能の不足は、今後のリリースでおそらく改善されるでしょう」とのこと
|
311
|
+
* ただ、まぁ Version 7.4 からずっと書いてあるので
|
312
|
+
|
313
|
+
= まとめ
|
314
|
+
|
315
|
+
* おとなしく STI を使いましょう
|
316
|
+
* でも、必要がなくなったら使うのをやめたい
|
317
|
+
|
318
|
+
= 質疑応答
|
319
|
+
|
320
|
+
* もし質問がなければ、こちらから皆さんに質問したり
|
321
|
+
* まめ知識を披露しますね
|
Binary file
|
data/yancya.jpg
ADDED
Binary file
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rabbit-slide-yancya-evacuate_from_sti
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- yancya
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-21 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rabbit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.2
|
27
|
+
description: |-
|
28
|
+
RubyHiroba 2014 の生活発表会で発表したスライドです
|
29
|
+
STI についてと、それを避けたらどういう実装がありうるかという話です
|
30
|
+
email:
|
31
|
+
- yancya@upec.jp
|
32
|
+
executables: []
|
33
|
+
extensions: []
|
34
|
+
extra_rdoc_files: []
|
35
|
+
files:
|
36
|
+
- ".rabbit"
|
37
|
+
- README.rd
|
38
|
+
- README.rd~
|
39
|
+
- Rakefile
|
40
|
+
- config.yaml
|
41
|
+
- evacuate_from_sti.rab
|
42
|
+
- pdf/evacuate_from_sti-evacuate_from_sti.pdf
|
43
|
+
- yancya.jpg
|
44
|
+
homepage: http://slide.rabbit-shocker.org/authors/yancya/evacuate_from_sti/
|
45
|
+
licenses: []
|
46
|
+
metadata: {}
|
47
|
+
post_install_message:
|
48
|
+
rdoc_options: []
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ">="
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
requirements: []
|
62
|
+
rubyforge_project:
|
63
|
+
rubygems_version: 2.2.2
|
64
|
+
signing_key:
|
65
|
+
specification_version: 4
|
66
|
+
summary: Evacuate from STI
|
67
|
+
test_files: []
|