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 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
+ * まめ知識を披露しますね
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: []