rabbit-slide-yancya-evacuate_from_sti 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|