rabbit-slide-kou-rubykaigi-2018 2018.6.1.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 +47 -0
- data/Rakefile +17 -0
- data/config.yaml +22 -0
- data/images/bindings-by-gobject-introspection.svg +499 -0
- data/images/bindings-by-swig.svg +273 -0
- data/images/cairo-gc-trigger.pdf +0 -0
- data/images/cairo-no-gc-trigger.pdf +0 -0
- data/images/clear-code-rubykaigi-2018-silver-sponsor.png +0 -0
- data/images/code-party.png +0 -0
- data/images/jekyll-task-i18n-red-data-tools.gif +0 -0
- data/images/pdf-clickable.png +0 -0
- data/images/rabbit-slide-show.png +0 -0
- data/images/ruby-gtk3-with-ruby-gi.svg +411 -0
- data/images/ruby-gtk3-without-ruby-gi.svg +313 -0
- data/images/rubykaigi-2017-extension-by-cpp-title.pdf +1853 -4
- data/images/rurema-search.png +0 -0
- data/images/shocker.jpeg +0 -0
- data/images/the-tortoise-and-the-hare-fast.png +0 -0
- data/images/the-tortoise-and-the-hare-good.png +0 -0
- data/images/the-tortoise-and-the-hare-hare.png +0 -0
- data/images/the-tortoise-and-the-hare-raw.png +0 -0
- data/images/the-tortoise-and-the-hare-slow.png +0 -0
- data/images/the-tortoise-and-the-hare-tortoise.png +0 -0
- data/images/the-tortoise-and-the-hare.gif +0 -0
- data/images/the-tortoise-and-the-hare.png +0 -0
- data/interface.rab +614 -0
- data/my-way-with-ruby.rab +1668 -0
- data/pdf/rubykaigi-2018-my-way-with-ruby.pdf +0 -0
- data/theme.rb +4 -0
- metadata +108 -0
@@ -0,0 +1,1668 @@
|
|
1
|
+
= My way with Ruby
|
2
|
+
|
3
|
+
: author
|
4
|
+
Kouhei Sutou
|
5
|
+
: institution
|
6
|
+
ClearCode Inc.
|
7
|
+
: content-source
|
8
|
+
RubyKaigi 2018
|
9
|
+
: date
|
10
|
+
2018-06-01
|
11
|
+
: start-time
|
12
|
+
2018-06-01T09:40:00+09:00
|
13
|
+
: end-time
|
14
|
+
2018-06-01T10:35:00+09:00
|
15
|
+
: theme
|
16
|
+
.
|
17
|
+
|
18
|
+
= Ad: Silver sponsor
|
19
|
+
|
20
|
+
# img
|
21
|
+
# src = images/clear-code-rubykaigi-2018-silver-sponsor.png
|
22
|
+
# relative_height = 100
|
23
|
+
# reflect_ratio = 0.1
|
24
|
+
|
25
|
+
== Slide properties
|
26
|
+
|
27
|
+
: enable-title-on-image
|
28
|
+
false
|
29
|
+
|
30
|
+
= Keynote-ish topic\n(('note:キーノートっぽい話題'))
|
31
|
+
|
32
|
+
Did you think about it?\n
|
33
|
+
(('note:考えたことある?'))
|
34
|
+
|
35
|
+
= Keynote-ish topic1\n(('note:キーノートっぽい話題1'))
|
36
|
+
|
37
|
+
Future\n
|
38
|
+
(('note:未来のこと'))
|
39
|
+
|
40
|
+
= Keynote-ish topic2\n(('note:キーノートっぽい話題2'))
|
41
|
+
|
42
|
+
Focus on\n
|
43
|
+
one thing\n
|
44
|
+
((*deeply*))\n
|
45
|
+
(('note:なにかを深掘り'))
|
46
|
+
|
47
|
+
= Keynote-ish topic3\n(('note:キーノートっぽい話題3'))
|
48
|
+
|
49
|
+
Overview\n
|
50
|
+
(('note:俯瞰した話'))
|
51
|
+
|
52
|
+
= My activities\nas a Rubyist\n(('note:私のRubyist活動'))
|
53
|
+
|
54
|
+
* Increase what Ruby can\n
|
55
|
+
(('note:Rubyでできることを増やす'))
|
56
|
+
* Maintain libraries\n
|
57
|
+
(('note:ライブラリーのメンテナンス'))
|
58
|
+
|
59
|
+
= The number of developing libraries\n(('note:開発しているライブラリー数'))
|
60
|
+
|
61
|
+
About 130\n
|
62
|
+
(('note:130くらい'))
|
63
|
+
|
64
|
+
= How to find targets?\n(('note:そんなにネタがあるの?'))
|
65
|
+
|
66
|
+
Just I needed\n
|
67
|
+
(('note:単に自分が必要だったから'))
|
68
|
+
|
69
|
+
= Today's topic\n(('note:今日の話題'))
|
70
|
+
|
71
|
+
Overview\n
|
72
|
+
what we can do\n
|
73
|
+
((*with Ruby*))\n
|
74
|
+
(('note:Rubyでできるようになったことをたくさん紹介'))
|
75
|
+
|
76
|
+
= Category1\n(('note:分類1'))
|
77
|
+
|
78
|
+
Web feed\n
|
79
|
+
(('note:Webフィード'))
|
80
|
+
|
81
|
+
= RSS Parser
|
82
|
+
|
83
|
+
RSS/Atom parser\n
|
84
|
+
with\n
|
85
|
+
((*validation*))\n
|
86
|
+
(('note:バリデーション機能付きのRSS/Atomパーサー'))
|
87
|
+
|
88
|
+
= RSS Parser - History\n(('note:歴史'))
|
89
|
+
|
90
|
+
* 2003-05: The first release\n
|
91
|
+
(('note:最初のリリース'))
|
92
|
+
* No other RSS/Atom parser that supports validation even now\n
|
93
|
+
(('note:今でもバリデーション付きのパーサーは他にない'))
|
94
|
+
* 2004-01: Ruby bundles this\n
|
95
|
+
(('note:RubyがRSS Parserをバンドル'))
|
96
|
+
* I became a Ruby committer\n
|
97
|
+
(('note:Rubyコミッターになる'))
|
98
|
+
|
99
|
+
= Validate RSS/Atom\n(('note:RSS/Atomのバリデーション'))
|
100
|
+
|
101
|
+
* Important for me\n
|
102
|
+
(('note:私にとっては大事'))
|
103
|
+
* Most wild RSS/Atom feeds are\n
|
104
|
+
((*invalid*))\n
|
105
|
+
(('note:野生のRSS/Atomの多くは不正'))
|
106
|
+
* Validation helps to find problems\n
|
107
|
+
(('note:バリデーションがあると問題を見つけやすくなる'))
|
108
|
+
|
109
|
+
= RSS::Parser.parse
|
110
|
+
|
111
|
+
# coderay ruby
|
112
|
+
|
113
|
+
# Validates by default
|
114
|
+
# デフォルトでバリデーション
|
115
|
+
RSS::Parser.parse(rss)
|
116
|
+
# Validation can be disabled
|
117
|
+
# 無効にできる
|
118
|
+
RSS::Parser.parse(rss, false)
|
119
|
+
|
120
|
+
= Since Ruby 2.6\n(('note:Ruby 2.6以降'))
|
121
|
+
|
122
|
+
# coderay ruby
|
123
|
+
|
124
|
+
# Supports keyword argument
|
125
|
+
# キーワード引数対応
|
126
|
+
parse(rss, validate: false)
|
127
|
+
|
128
|
+
= REXML
|
129
|
+
|
130
|
+
XML parser\n
|
131
|
+
written in\n
|
132
|
+
((*pure Ruby*))\n
|
133
|
+
(('note:Ruby実装のXMLパーサー'))
|
134
|
+
|
135
|
+
= REXML - History\n(('note:歴史'))
|
136
|
+
|
137
|
+
* 2001: Started by Sean Russell\n
|
138
|
+
(('note:Seanさんが開発を開始'))
|
139
|
+
* Based on Electric XML (Java)\n
|
140
|
+
(('note:Java実装のElectric XMLを参考に開発'))
|
141
|
+
* REXML is "Ruby Electric XML"\n
|
142
|
+
(('note:REXMLは「Ruby Electric XML」'))
|
143
|
+
* 2003-01: Ruby bundles this\n
|
144
|
+
(('note:RubyがREXMLをバンドル'))
|
145
|
+
|
146
|
+
= REXML - Side story\n(('note:おまけ話'))
|
147
|
+
|
148
|
+
* Sean was "書運" in Kanji\n
|
149
|
+
(('note:Seanさんには「書運」という漢字表記があった'))
|
150
|
+
* He was interested in Japan\n
|
151
|
+
(('note:日本好きだった'))
|
152
|
+
* (('tag:x-small'))"How to write your name in Kanji?"\n
|
153
|
+
(('note:「君の名前は漢字でどう書くの?」'))
|
154
|
+
* We can connect with Ruby!\n
|
155
|
+
(('note:RubyistはRubyをきっかけにつながれる!'))
|
156
|
+
|
157
|
+
= Ad: Code Party\n(('note:宣伝:コード懇親会'))
|
158
|
+
|
159
|
+
# img
|
160
|
+
# src = images/code-party.png
|
161
|
+
# relative_height = 100
|
162
|
+
# reflect_ratio = 0.1
|
163
|
+
|
164
|
+
== Slide properties
|
165
|
+
|
166
|
+
: enable-title-on-image
|
167
|
+
false
|
168
|
+
|
169
|
+
= Ad: Code Party\n(('note:宣伝:コード懇親会'))
|
170
|
+
|
171
|
+
(('tag:center'))
|
172
|
+
This is a challenge\n
|
173
|
+
(('note:実験的な企画'))
|
174
|
+
|
175
|
+
* Ruby focus to have fun\n
|
176
|
+
(('note:Rubyは楽しさを大事にしている'))
|
177
|
+
* We have fun writing Ruby\n
|
178
|
+
(('note:Rubyistは楽しくRubyを書いている'))
|
179
|
+
* We have fun together with writing Ruby at after party!?\n
|
180
|
+
(('note:だったら懇親会で一緒にRubyを書くと楽しそう!?'))
|
181
|
+
|
182
|
+
= Ad: Code Party\n(('note:宣伝:コード懇親会'))
|
183
|
+
|
184
|
+
* Matz attends Code Party\n
|
185
|
+
(('note:まつもとさんもコード懇親会に参加'))
|
186
|
+
* Sponsored by Speee, Inc.\n
|
187
|
+
(('note:Speeeさんがスポンサー'))
|
188
|
+
|
189
|
+
= REXML - Recent1\n(('note:最近1'))
|
190
|
+
|
191
|
+
* 2010-08: RubyKaigi 2010
|
192
|
+
* I became the maintainer\n
|
193
|
+
(('note:私がメンテナーになった'))
|
194
|
+
* Because RSS Parser uses it\n
|
195
|
+
(('note:RSS Parserが使っているから'))
|
196
|
+
|
197
|
+
= REXML - Recent2\n(('note:最近2'))
|
198
|
+
|
199
|
+
* 2016: (({element[attribute_name]}))
|
200
|
+
* Ruby 2.5 ships it\n
|
201
|
+
(('note:Ruby 2.5以降で使える'))
|
202
|
+
|
203
|
+
= REXML - Recent3\n(('note:最近3'))
|
204
|
+
|
205
|
+
* 2018: Fix XPath related bugs\n
|
206
|
+
(('note:XPath関連のバグ修正'))
|
207
|
+
* Ruby 2.6 ships it\n
|
208
|
+
(('note:Ruby 2.6以降で使える'))
|
209
|
+
|
210
|
+
= REXML - Future?\n(('note:未来はあるの?'))
|
211
|
+
|
212
|
+
* ((*Pure Ruby*)) is valuable\n
|
213
|
+
(('note:Rubyだけで書かれていることには価値がある'))
|
214
|
+
* Easy to install\n
|
215
|
+
(('note:インストールが簡単'))
|
216
|
+
* JIT may improve performance\n
|
217
|
+
(('note:NOTE: We should improve general logic before we expect JIT to improve performance😉'))\n
|
218
|
+
(('note:JITで速くなるかもしれない'))\n
|
219
|
+
(('note:JITの前に普通にロジックを改良するのが先だけどね😉'))\n
|
220
|
+
|
221
|
+
= Recent my works\n(('note:最近の仕事'))
|
222
|
+
|
223
|
+
* XML/HTML libraries for LuaJIT\n
|
224
|
+
(('note:LuaJIT用のXML/HTMLライブラリー'))
|
225
|
+
* XMLua: (('tag:xx-small:((<URL:https://clear-code.github.io/xmlua/>))'))\n
|
226
|
+
libxml2 based XML/HTML parser
|
227
|
+
* LuaCS: (('tag:xx-small:((<URL:https://clear-code.github.io/luacs/>))'))\n
|
228
|
+
CSS Selectors→XPath converter
|
229
|
+
* Found what lacks in REXML API\n
|
230
|
+
(('note:REXMLのAPIに足りないものはなにか考えた'))
|
231
|
+
|
232
|
+
= REXML - Future1\n(('note:機能1'))
|
233
|
+
|
234
|
+
Introduce NodeSet\n
|
235
|
+
(('note:NodeSetが足りないんじゃないか'))
|
236
|
+
|
237
|
+
= REXML - NodeSet
|
238
|
+
|
239
|
+
# coderay ruby
|
240
|
+
doc.
|
241
|
+
search("//item"). # => NodeSet
|
242
|
+
text # All texts in <item>
|
243
|
+
|
244
|
+
= REXML - Future2\n(('note:機能2'))
|
245
|
+
|
246
|
+
Support\n
|
247
|
+
CSS Selectors\n
|
248
|
+
(('note:CSSセレクターが足りないんじゃないか'))
|
249
|
+
|
250
|
+
= REXML - CSS Selectors\n(('note:CSSセレクター'))
|
251
|
+
|
252
|
+
# coderay ruby
|
253
|
+
doc.css_select("ul li, dl dt")
|
254
|
+
|
255
|
+
= REXML - Future3\n(('note:機能3'))
|
256
|
+
|
257
|
+
Support\n
|
258
|
+
HTML5 support\n
|
259
|
+
(('note:HTML5対応が足りないんじゃないか'))
|
260
|
+
|
261
|
+
= REXML - HTML5
|
262
|
+
|
263
|
+
# coderay ruby
|
264
|
+
|
265
|
+
doc = REXML::HTML5Document.new(html5)
|
266
|
+
doc.search("//li")
|
267
|
+
doc.css_select("ul li")
|
268
|
+
|
269
|
+
= REXML - Future\n(('note:未来'))
|
270
|
+
|
271
|
+
* Low priority in my activities\n
|
272
|
+
(('note:優先度は高くない'))
|
273
|
+
* Do you want to work with me?\n
|
274
|
+
(('note:一緒にやりたい人はいる?'))
|
275
|
+
|
276
|
+
= Category2\n(('note:分類1'))
|
277
|
+
|
278
|
+
Presentation\n
|
279
|
+
(('note:プレゼンテーション'))
|
280
|
+
|
281
|
+
= Rabbit
|
282
|
+
|
283
|
+
(('tag:center'))
|
284
|
+
(('tag:large'))
|
285
|
+
Presentation tool\n
|
286
|
+
for ((*Rubyist*))\n
|
287
|
+
(('note:Rubyist用のプレゼンツール'))
|
288
|
+
|
289
|
+
((' '))
|
290
|
+
|
291
|
+
= Rabbit - History\n(('note:歴史'))
|
292
|
+
|
293
|
+
* 2004-07: The first release\n
|
294
|
+
(('note:最初のリリース'))
|
295
|
+
* No other presentation tool for Rubyist even now\n
|
296
|
+
(('note:今でもRubyist用のプレゼンツールは他にない'))
|
297
|
+
* 2010: Matz migrated to Rabbit\n
|
298
|
+
(('note:まつもとさんがRabbitに乗り換えた'))
|
299
|
+
* Since RubyKaigi 2010?\n
|
300
|
+
(('note:RubyKaigi 2010から?'))
|
301
|
+
|
302
|
+
= For Rubyist?\n(('note:Rubyist向けに必要なもの'))
|
303
|
+
|
304
|
+
RD support\n
|
305
|
+
(('note:RDサポート'))
|
306
|
+
|
307
|
+
= RD
|
308
|
+
|
309
|
+
* ((*R*))uby ((*D*))ocument\n
|
310
|
+
* Designed by Matz (('note:(Right?)'))\n
|
311
|
+
(('note:まつもとさんがデザインしたはず'))
|
312
|
+
* A text based markup language\n
|
313
|
+
(('note:テキストベースのマークアップ言語'))
|
314
|
+
* Version controllable\n
|
315
|
+
(('note:バージョン管理できる'))
|
316
|
+
|
317
|
+
= For Rubyist?\n(('note:Rubyist向けに必要なもの'))
|
318
|
+
|
319
|
+
Publish\n
|
320
|
+
our slides\n
|
321
|
+
as usual\n
|
322
|
+
(('note:いつも通りスライドを公開できる'))
|
323
|
+
|
324
|
+
= Publish as usual\n(('note:いつも通り公開'))
|
325
|
+
|
326
|
+
# coderay console
|
327
|
+
% gem push your-slide-1.0.gem
|
328
|
+
|
329
|
+
= Published!\n(('note:公開完了!'))
|
330
|
+
|
331
|
+
# img
|
332
|
+
# src = images/rabbit-slide-show.png
|
333
|
+
# relative_height = 78
|
334
|
+
|
335
|
+
(('tag:center'))
|
336
|
+
(('tag:small'))
|
337
|
+
((<URL:https://slide.rabbit-shocker.org/>))
|
338
|
+
|
339
|
+
= What's needed for presentation tool?\n(('note:プレゼンツールに必要なもの'))
|
340
|
+
|
341
|
+
GUI
|
342
|
+
|
343
|
+
= Ruby/GTK3
|
344
|
+
|
345
|
+
Multi-platform GUI toolkit\n
|
346
|
+
(('note:複数プラットフォーム対応GUIツールキット'))
|
347
|
+
|
348
|
+
= Ruby/GTK3 - History\n(('note:歴史'))
|
349
|
+
|
350
|
+
* 1998-01: 1st release by Matz\n
|
351
|
+
((<[ruby-list:5877]|URL:http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/5877>))\n
|
352
|
+
(('note:まつもとさんが最初のリリース'))
|
353
|
+
* 2004-05: I joined development\n
|
354
|
+
(('note:私が開発に参加'))
|
355
|
+
|
356
|
+
= Example - Window
|
357
|
+
|
358
|
+
# coderay ruby
|
359
|
+
require "gtk3"
|
360
|
+
app = Gtk::Application.new
|
361
|
+
app.signal_connect(:activate) do
|
362
|
+
window = Gtk::ApplicationWindow.new(app)
|
363
|
+
window.show_all
|
364
|
+
end
|
365
|
+
app.run
|
366
|
+
|
367
|
+
= Approaches on\nmissing libraries(1)\n(('note:ライブラリーがない時のやり方(1)'))
|
368
|
+
|
369
|
+
(1) Implement only the needed features\n
|
370
|
+
(('note:必要な機能だけ実装'))
|
371
|
+
(2) then back to Rabbit\n
|
372
|
+
(('note:必要な機能ができたらRabbitに戻る'))
|
373
|
+
|
374
|
+
= Approaches on\nmissing libraries(2)\n(('note:ライブラリーがない時のやり方(2)'))
|
375
|
+
|
376
|
+
(1) Implement not only the needed features\n
|
377
|
+
(('note:必要な機能だけじゃなく'))
|
378
|
+
(2) but also (('note:almost')) all features\n
|
379
|
+
(('note:ほぼすべての機能を実装'))
|
380
|
+
(3) then back to Rabbit\n
|
381
|
+
(('note:終わったらRabbitに戻る'))
|
382
|
+
|
383
|
+
= My approach\n(('note:私のやり方'))
|
384
|
+
|
385
|
+
Implement\n
|
386
|
+
all features\n
|
387
|
+
(('note:testing with Rabbit'))\n
|
388
|
+
(('note:すべての機能を実装'))
|
389
|
+
|
390
|
+
= My priority\n(('note:私の優先度'))
|
391
|
+
|
392
|
+
* Rabbit is important\n
|
393
|
+
(('note:Rabbitは大事だけど'))
|
394
|
+
* Increasing what Ruby can is also important\n
|
395
|
+
(('note:Rubyでできることを増やすのも大事'))
|
396
|
+
|
397
|
+
= GTK+ 3 - Size\n(('note:サイズ'))
|
398
|
+
|
399
|
+
3000 over API\n
|
400
|
+
(('note:3000以上のAPI'))
|
401
|
+
|
402
|
+
= How to implement\n(('note:実装方法'))
|
403
|
+
|
404
|
+
Handwriting\n
|
405
|
+
(('note:手書き'))\n
|
406
|
+
↓\n
|
407
|
+
Auto generation\n
|
408
|
+
(('note:自動生成'))
|
409
|
+
|
410
|
+
= Ruby/GI
|
411
|
+
|
412
|
+
(('tag:center'))
|
413
|
+
(('tag:large'))
|
414
|
+
Generate bindings\n
|
415
|
+
automatically\n
|
416
|
+
at run-time\n
|
417
|
+
(('note:実行時に自動でバインディングを生成'))
|
418
|
+
|
419
|
+
(('note:GI: GObject Introspection'))
|
420
|
+
|
421
|
+
= Ruby/GI - History\n(('note:歴史'))
|
422
|
+
|
423
|
+
* 2012: The first commit by me\n
|
424
|
+
(('note:最初のコミット'))
|
425
|
+
* 2014: Ruby/GTK3 used Ruby/GI\n
|
426
|
+
(('note:Ruby/GTK3をRuby/GIベースに移行'))
|
427
|
+
|
428
|
+
= Handwriting\n(('note:手書き'))
|
429
|
+
|
430
|
+
# img
|
431
|
+
# src = images/ruby-gtk3-without-ruby-gi.svg
|
432
|
+
# relative_width = 100
|
433
|
+
|
434
|
+
== Slide properties
|
435
|
+
|
436
|
+
: enable-title-on-image
|
437
|
+
false
|
438
|
+
|
439
|
+
= Auto generation\n(('note:自動生成'))
|
440
|
+
|
441
|
+
# img
|
442
|
+
# src = images/ruby-gtk3-with-ruby-gi.svg
|
443
|
+
# relative_width = 100
|
444
|
+
|
445
|
+
== Slide properties
|
446
|
+
|
447
|
+
: enable-title-on-image
|
448
|
+
false
|
449
|
+
|
450
|
+
= Ruby/GI - See also\n(('note:参考情報'))
|
451
|
+
|
452
|
+
* "How to create bindings 2016" at RubyKaigi 2016\n
|
453
|
+
* (('tag:xx-small'))
|
454
|
+
((<URL:http://rubykaigi.org/2016/presentations/ktou.html>))
|
455
|
+
* "GI Introduction" (('note:(in Japanese)'))\n
|
456
|
+
(('note:「GObject Introspection入門」'))
|
457
|
+
* (('tag:xx-small'))
|
458
|
+
((<URL:https://github.com/RubyData/workshop-materials/blob/master/gobject-introspection/introduction.md>))
|
459
|
+
* Build system: Meson + Ninja\n
|
460
|
+
(('note:ビルドシステム:Meson + Ninja'))
|
461
|
+
|
462
|
+
= Ruby/GI based bindings\n(('note:Ruby/GIベースのバインディング'))
|
463
|
+
|
464
|
+
Ruby/Pango
|
465
|
+
|
466
|
+
= Ruby/Pango
|
467
|
+
|
468
|
+
(('tag:center'))
|
469
|
+
(('tag:large'))
|
470
|
+
Text layout engine\n
|
471
|
+
with\n
|
472
|
+
i18n support\n
|
473
|
+
(('note:国際化対応のテキストレイアウトエンジン'))
|
474
|
+
|
475
|
+
(('note:i18n: Internationalization'))
|
476
|
+
|
477
|
+
= Prohibition processing\n(('note:禁則処理'))
|
478
|
+
|
479
|
+
# coderay ruby
|
480
|
+
|
481
|
+
widget.signal_connect(:draw) do |_, context|
|
482
|
+
layout = context.create_pango_layout
|
483
|
+
layout.text = "Helloこんにちは。🍣"
|
484
|
+
context.show_pango_layout(layout)
|
485
|
+
GLib::Source::CONTINUE
|
486
|
+
end
|
487
|
+
|
488
|
+
= Bidirectional text\n(('note:双方向テキスト'))
|
489
|
+
|
490
|
+
Hello
|
491
|
+
|
492
|
+
مرحبا
|
493
|
+
|
494
|
+
こんにちは
|
495
|
+
|
496
|
+
= Ruby/GI based bindings\n(('note:Ruby/GIベースのバインディング'))
|
497
|
+
|
498
|
+
Ruby/GdkPixbuf2
|
499
|
+
|
500
|
+
= Ruby/GdkPixbuf2
|
501
|
+
|
502
|
+
Image manipulation\n
|
503
|
+
(('note:画像操作'))
|
504
|
+
|
505
|
+
= Half image\n(('note:画像を半分に'))
|
506
|
+
|
507
|
+
# coderay ruby
|
508
|
+
|
509
|
+
require "gdk_pixbuf2"
|
510
|
+
# Load an image: Format is auto detected
|
511
|
+
pixbuf = GdkPixbuf::Pixbuf.new(file: "x.png")
|
512
|
+
# Scale to half size
|
513
|
+
half = pixbuf.scale(pixbuf.width / 2,
|
514
|
+
pixbuf.height / 2,
|
515
|
+
:bilinear)
|
516
|
+
# Save as different format
|
517
|
+
half.save("half.jpg")
|
518
|
+
|
519
|
+
= Animation GIF\n(('note:アニメーションGIF'))
|
520
|
+
|
521
|
+
# img
|
522
|
+
# src = images/the-tortoise-and-the-hare.gif
|
523
|
+
# relative_width = 100
|
524
|
+
|
525
|
+
== Slide properties
|
526
|
+
|
527
|
+
: enable-title-on-image
|
528
|
+
false
|
529
|
+
|
530
|
+
= Ruby/GI based bindings\n(('note:Ruby/GIベースのバインディング'))
|
531
|
+
|
532
|
+
Ruby/Poppler
|
533
|
+
|
534
|
+
= Ruby/Poppler
|
535
|
+
|
536
|
+
PDF\n
|
537
|
+
parser/renderer\n
|
538
|
+
(('note:PDFパーサー・レンダラー'))
|
539
|
+
|
540
|
+
= Text extraction\n(('note:テキスト抽出'))
|
541
|
+
|
542
|
+
# coderay ruby
|
543
|
+
|
544
|
+
require "poppler"
|
545
|
+
doc = Poppler::Document.new("x.pdf")
|
546
|
+
doc.each do |page|
|
547
|
+
puts(page.text) # Extract all texts
|
548
|
+
end
|
549
|
+
|
550
|
+
= Embed PDF\n(('note:PDFの埋め込み'))
|
551
|
+
|
552
|
+
# image
|
553
|
+
# src = images/rubykaigi-2017-extension-by-cpp-title.pdf
|
554
|
+
# relative_height = 80
|
555
|
+
# reflect_ratio = 0.1
|
556
|
+
|
557
|
+
(('tag:center'))
|
558
|
+
(('tag:xx-small'))
|
559
|
+
((<URL:http://rubykaigi.org/2017/presentations/ktou.html>))
|
560
|
+
|
561
|
+
== Slide properties
|
562
|
+
|
563
|
+
: enable-title-on-image
|
564
|
+
false
|
565
|
+
|
566
|
+
= Ruby/GI based bindings\n(('note:Ruby/GIベースのバインディング'))
|
567
|
+
|
568
|
+
Ruby/GStreamer
|
569
|
+
|
570
|
+
= Ruby/GStreamer
|
571
|
+
|
572
|
+
(('tag:center'))
|
573
|
+
(('tag:large'))
|
574
|
+
Audio/Video player\n
|
575
|
+
(('note:音声・動画プレイヤー'))
|
576
|
+
|
577
|
+
(('note:(*) Streaming media framework'))\n
|
578
|
+
(('note:本当はストリーミングメディアフレームワーク'))
|
579
|
+
|
580
|
+
= Camera(('note:(カメラ)'))
|
581
|
+
|
582
|
+
# coderay ruby
|
583
|
+
|
584
|
+
require "gst"
|
585
|
+
description = [
|
586
|
+
"autovideosrc", # Camera
|
587
|
+
"videoconvert", # Filter
|
588
|
+
"autovideosink", # Window
|
589
|
+
].join(" ! ")
|
590
|
+
pipeline = Gst.parse_launch(description)
|
591
|
+
pipeline.play
|
592
|
+
until pipeline.bus.poll.type.eos? do
|
593
|
+
end # Main loop
|
594
|
+
pipeline.stop
|
595
|
+
|
596
|
+
= Face detection\n(('note:顔認識'))
|
597
|
+
|
598
|
+
# coderay ruby
|
599
|
+
|
600
|
+
description = [
|
601
|
+
"autovideosrc", # Camera
|
602
|
+
"videoconvert", # Filter
|
603
|
+
"facedetect", # Face detection (!)
|
604
|
+
"videoconvert", # Filter (!)
|
605
|
+
"autovideosink", # Window
|
606
|
+
].join(" ! ")
|
607
|
+
pipeline = Gst.parse_launch(description)
|
608
|
+
pipeline.play
|
609
|
+
|
610
|
+
# = Embed video
|
611
|
+
|
612
|
+
# TODO
|
613
|
+
|
614
|
+
# # # video
|
615
|
+
# # # src = test.mp4
|
616
|
+
|
617
|
+
= What's needed for presentation tool?\n(('note:プレゼンツールに必要なもの'))
|
618
|
+
|
619
|
+
PDF output\n
|
620
|
+
(('note:PDF出力'))
|
621
|
+
|
622
|
+
= rcairo
|
623
|
+
|
624
|
+
2D graphics renderer\n
|
625
|
+
(('note:2次元画像レンダラー'))
|
626
|
+
|
627
|
+
= rcairo - Outputs\n(('note:出力'))
|
628
|
+
|
629
|
+
* PNG・SVG
|
630
|
+
* ((*PDF*))
|
631
|
+
* ((*Display*)) (X/macOS/Windows)
|
632
|
+
* ...
|
633
|
+
|
634
|
+
= rcairo - History\n(('note:歴史'))
|
635
|
+
|
636
|
+
* 2003-10: The initial commit\n
|
637
|
+
(('note:最初のコミット'))
|
638
|
+
* 2005-09: I started developing\n
|
639
|
+
(('note:私が開発に参加'))
|
640
|
+
|
641
|
+
= Red A4 PDF\n(('note:赤いA4のPDFを出力'))
|
642
|
+
|
643
|
+
# coderay ruby
|
644
|
+
|
645
|
+
require "cairo"
|
646
|
+
include Cairo
|
647
|
+
PDFSurface.create("x.pdf", "A4") do |surface|
|
648
|
+
Context.create(surface) do |context|
|
649
|
+
context.set_source_color(:red)
|
650
|
+
context.paint
|
651
|
+
end
|
652
|
+
end
|
653
|
+
|
654
|
+
= rcairo - GC
|
655
|
+
|
656
|
+
# image
|
657
|
+
# src = images/cairo-no-gc-trigger.pdf
|
658
|
+
# align = right
|
659
|
+
# vertical_align = bottom
|
660
|
+
# relative_width = 65
|
661
|
+
# relative_padding_right = -7
|
662
|
+
# relative_padding_bottom = -10
|
663
|
+
|
664
|
+
# coderay ruby
|
665
|
+
1000.times do
|
666
|
+
Cairo::ImageSurface.new(:argb32, 6000, 6000)
|
667
|
+
end
|
668
|
+
|
669
|
+
(('tag:margin-bottom * 20'))
|
670
|
+
|
671
|
+
= GC - Cause(('note:(原因)'))
|
672
|
+
|
673
|
+
# image
|
674
|
+
# src = images/cairo-no-gc-trigger.pdf
|
675
|
+
# align = right
|
676
|
+
# vertical_align = bottom
|
677
|
+
# relative_width = 67
|
678
|
+
# relative_padding_right = -11
|
679
|
+
# relative_padding_bottom = -10
|
680
|
+
|
681
|
+
* GC isn't ran enough frequency\n
|
682
|
+
(('note:GCの実行頻度が十分じゃなかった'))
|
683
|
+
* Because Ruby doesn't know how many memory used by cairo\n
|
684
|
+
(('note:Rubyはcairoのメモリー使用量を知らないから'))
|
685
|
+
|
686
|
+
(('tag:margin-bottom * 16'))
|
687
|
+
|
688
|
+
= GC - Fix(('note:(修正)'))
|
689
|
+
|
690
|
+
# image
|
691
|
+
# src = images/cairo-gc-trigger.pdf
|
692
|
+
# align = right
|
693
|
+
# vertical_align = bottom
|
694
|
+
# relative_width = 67
|
695
|
+
# relative_padding_right = -11
|
696
|
+
# relative_padding_bottom = -10
|
697
|
+
|
698
|
+
* (({rb_gc_adjust_memory_usage()}))
|
699
|
+
* Improve GC frequency(('note:(GC実行頻度を改善)'))
|
700
|
+
* Ruby 2.4 ships it(('note:(Ruby 2.4以降)'))
|
701
|
+
|
702
|
+
(('tag:margin-bottom * 18'))
|
703
|
+
|
704
|
+
= Easy to install\n(('note:簡単インストール'))
|
705
|
+
|
706
|
+
Important\n
|
707
|
+
(('note:大事'))
|
708
|
+
|
709
|
+
= native-package-installer
|
710
|
+
|
711
|
+
Install\n
|
712
|
+
system packages\n
|
713
|
+
on (({gem install}))\n
|
714
|
+
(('note:gem install時にシステムのパッケージをインストール'))
|
715
|
+
|
716
|
+
= extconf.rb/Rakefile
|
717
|
+
|
718
|
+
# coderay ruby
|
719
|
+
|
720
|
+
require "pkg-config"
|
721
|
+
require "native-package-installer"
|
722
|
+
unless PKGConfig.check_version?("gdk-3.0")
|
723
|
+
packages = {
|
724
|
+
altlinux: "libgtk+3-devel",
|
725
|
+
debian: "libgtk-3-dev",
|
726
|
+
redhat: "pkgconfig(gdk-3.0)",
|
727
|
+
homebrew: "gtk+3",
|
728
|
+
macports: "gtk3",
|
729
|
+
msys2: "gtk3",
|
730
|
+
}
|
731
|
+
unless NativePackageInstaller.install(packages)
|
732
|
+
exit(false)
|
733
|
+
end
|
734
|
+
end
|
735
|
+
|
736
|
+
= rake-compiler
|
737
|
+
|
738
|
+
Build fat gem\n
|
739
|
+
by\n
|
740
|
+
cross compile\n
|
741
|
+
(('note:クロスコンパイルでfat gemをビルド'))
|
742
|
+
|
743
|
+
= rake-compiler - History\n(('note:歴史'))
|
744
|
+
|
745
|
+
* 2008-11: The first commit\n
|
746
|
+
(('note:最初のコミット'))
|
747
|
+
* 2014-12: Orphan\n
|
748
|
+
(('note:だれかメンテナー変わってー'))
|
749
|
+
* 2014-12:\n
|
750
|
+
I became the maintainer\n
|
751
|
+
(('note:私がメンテナーになった'))
|
752
|
+
|
753
|
+
= Category3\n(('note:分類3'))
|
754
|
+
|
755
|
+
Test\n
|
756
|
+
(('note:テスト'))
|
757
|
+
|
758
|
+
= test-unit
|
759
|
+
|
760
|
+
Testing framework\n
|
761
|
+
to write tests\n
|
762
|
+
((*in Ruby*))\n
|
763
|
+
(('note:Rubyでテストを書けるテスティングフレームワーク'))
|
764
|
+
|
765
|
+
= test-unit - History\n(('note:歴史'))
|
766
|
+
|
767
|
+
* 2003-02: Import to Ruby\n
|
768
|
+
(('note:Rubyに取り込まれる'))
|
769
|
+
* 2008-05:\n
|
770
|
+
I became the maintainer\n
|
771
|
+
(('note:私がメンテナーになった'))
|
772
|
+
* 2008-10: Removed from Ruby\n
|
773
|
+
(('note:Rubyから削除'))
|
774
|
+
|
775
|
+
(('note:See also: "The history of testing framework in Ruby"'))\n
|
776
|
+
(('tag:x-small'))((<URL:http://rubykaigi.org/2015/presentations/kou>))
|
777
|
+
|
778
|
+
= test-unit - New feature\n(('note:新機能'))
|
779
|
+
|
780
|
+
Grouping\n
|
781
|
+
(('note:グループ化'))
|
782
|
+
|
783
|
+
= Grouping\n(('note:グループ化'))
|
784
|
+
|
785
|
+
* The most important feature\n
|
786
|
+
(('note:一番大事な機能'))
|
787
|
+
* Keep tests maintainable\n
|
788
|
+
(('note:メンテナンスできるテストを維持できる'))
|
789
|
+
|
790
|
+
= Example(('note:(例)'))
|
791
|
+
|
792
|
+
# coderay ruby
|
793
|
+
|
794
|
+
class StackTest < Test::Unit::TestCase
|
795
|
+
class PushTest < self
|
796
|
+
def test_XXX; end
|
797
|
+
end
|
798
|
+
class PopTest < self
|
799
|
+
def test_XXX; end
|
800
|
+
end
|
801
|
+
end
|
802
|
+
|
803
|
+
= Method style(('note:(メソッド形式)'))
|
804
|
+
|
805
|
+
# coderay ruby
|
806
|
+
|
807
|
+
class StackTest < Test::Unit::TestCase
|
808
|
+
sub_test_case("#push") do
|
809
|
+
def test_XXX; end
|
810
|
+
end
|
811
|
+
sub_test_case("#pop") do
|
812
|
+
def test_XXX; end
|
813
|
+
end
|
814
|
+
end
|
815
|
+
|
816
|
+
= test-unit - New feature\n(('note:新機能'))
|
817
|
+
|
818
|
+
Data driven test\n
|
819
|
+
(('note:データ駆動テスト'))
|
820
|
+
|
821
|
+
= Data driven test\n(('note:データ駆動テスト'))
|
822
|
+
|
823
|
+
# coderay ruby
|
824
|
+
|
825
|
+
data("positive", [3, 1, 2])
|
826
|
+
data("negative", [-4, 1, -5])
|
827
|
+
def test_add(data)
|
828
|
+
expected, augend, addend = data
|
829
|
+
assert_equal(expected,
|
830
|
+
add(augend, addend))
|
831
|
+
end
|
832
|
+
|
833
|
+
= test-unit - New feature\n(('note:新機能'))
|
834
|
+
|
835
|
+
Reverse backtrace\n
|
836
|
+
(('note:逆順のバックトレース'))
|
837
|
+
|
838
|
+
= Reverse backtrace\n(('note:逆順のバックトレース'))
|
839
|
+
|
840
|
+
* Reverse backtrace only when terminal output\n
|
841
|
+
(('note:ターミナル出力のときだけ逆順'))
|
842
|
+
* The same change as Ruby 2.5.0\n
|
843
|
+
(('note:Ruby 2.5.0と同じ変更'))
|
844
|
+
|
845
|
+
= test-unit - New feature\n(('note:新機能'))
|
846
|
+
|
847
|
+
Test double\n
|
848
|
+
(('note:テストダブル'))
|
849
|
+
|
850
|
+
= test-unit-rr
|
851
|
+
|
852
|
+
RR integration\n
|
853
|
+
(('note:RRとの統合'))
|
854
|
+
|
855
|
+
= RR - History\n(('note:歴史'))
|
856
|
+
|
857
|
+
* 2007-06: The initial commit\n
|
858
|
+
(('note:最初のコミット'))
|
859
|
+
* 2014-12: Orphan\n
|
860
|
+
(('note:だれかメンテナー変わってー'))
|
861
|
+
* 2015-05:\n
|
862
|
+
I became the maintainer\n
|
863
|
+
(('note:私がメンテナーになった'))
|
864
|
+
|
865
|
+
= Stub(('note:(スタブ)'))
|
866
|
+
|
867
|
+
# coderay ruby
|
868
|
+
|
869
|
+
adder = Object.new
|
870
|
+
adder.add(1, 2) # => Error
|
871
|
+
stub(adder).add(1, 2) {3}
|
872
|
+
adder.add(1, 2) # => 3
|
873
|
+
|
874
|
+
= Category4\n(('note:分類4'))
|
875
|
+
|
876
|
+
Full text search\n
|
877
|
+
(('note:全文検索'))
|
878
|
+
|
879
|
+
= Rroonga
|
880
|
+
|
881
|
+
Full text search\n
|
882
|
+
((*library*))\n
|
883
|
+
(('note:全文検索ライブラリー'))
|
884
|
+
|
885
|
+
= ((*Library*)) vs Client\n(('note:ライブラリー対クライアント'))
|
886
|
+
|
887
|
+
* No server process\n
|
888
|
+
(('note:サーバープロセスがいらない'))
|
889
|
+
* Easy to start\n
|
890
|
+
(('note:簡単に使い始められる'))
|
891
|
+
* Write in Ruby\n
|
892
|
+
(('note:Rubyで書ける'))
|
893
|
+
|
894
|
+
= Create DB(('note:(データベース作成)'))
|
895
|
+
|
896
|
+
# coderay ruby
|
897
|
+
require "groonga"
|
898
|
+
|
899
|
+
Groonga::Database.create(path: "/tmp/db")
|
900
|
+
|
901
|
+
= Define schema(('note:(スキーマ定義)'))
|
902
|
+
|
903
|
+
# coderay ruby
|
904
|
+
|
905
|
+
Groonga::Schema.define do |schema|
|
906
|
+
schema.create_table("docs") do |table|
|
907
|
+
# The column to store text
|
908
|
+
table.text("content")
|
909
|
+
end
|
910
|
+
# The index for full text search
|
911
|
+
schema.create_lexicon("terms") do |table|
|
912
|
+
table.index("docs.content")
|
913
|
+
end
|
914
|
+
end
|
915
|
+
|
916
|
+
= Add records(('note:(レコード追加)'))
|
917
|
+
|
918
|
+
# coderay ruby
|
919
|
+
|
920
|
+
docs = Groonga["docs"]
|
921
|
+
docs.add(content: "String#<< concatenates ...")
|
922
|
+
docs.add(content: "String#dup duplicates ...")
|
923
|
+
|
924
|
+
= Search(('note:(検索)'))
|
925
|
+
|
926
|
+
# coderay ruby
|
927
|
+
|
928
|
+
matches = docs.select do |record|
|
929
|
+
record.content.match("concat")
|
930
|
+
end
|
931
|
+
p matches.size # => 1
|
932
|
+
matches.each do |record|
|
933
|
+
p record.content # => "String#<< concat..."
|
934
|
+
end
|
935
|
+
|
936
|
+
= User - Rabbit Slide Show
|
937
|
+
|
938
|
+
# img
|
939
|
+
# src = images/rabbit-slide-show.png
|
940
|
+
# relative_height = 78
|
941
|
+
|
942
|
+
(('tag:center'))
|
943
|
+
(('tag:small'))
|
944
|
+
((<URL:https://slide.rabbit-shocker.org/>))
|
945
|
+
|
946
|
+
= User - Rurema Search
|
947
|
+
|
948
|
+
# img
|
949
|
+
# src = images/rurema-search.png
|
950
|
+
# relative_height = 78
|
951
|
+
|
952
|
+
(('tag:center'))
|
953
|
+
(('tag:small'))
|
954
|
+
((<URL:https://docs.ruby-lang.org/ja/search/>))
|
955
|
+
|
956
|
+
= Rurema Search\n(('note:るりまサーチ'))
|
957
|
+
|
958
|
+
* Super fast!\n
|
959
|
+
(('note:すごく速い!'))
|
960
|
+
* Tune for programming document\n
|
961
|
+
(('note:プログラミングのドキュメント用にチューニング'))
|
962
|
+
* Symbols (@, #, ...) are important\n
|
963
|
+
(('note:@とか#とかの記号も大事'))
|
964
|
+
|
965
|
+
= User - RDoc Search
|
966
|
+
|
967
|
+
* Planning\n
|
968
|
+
(('note:考えてはいるけど。。。'))
|
969
|
+
* Do you want to work with me?\n
|
970
|
+
(('note:一緒にやりたい人はいる?'))
|
971
|
+
|
972
|
+
= Rurema and RDoc
|
973
|
+
|
974
|
+
# RT
|
975
|
+
|
976
|
+
Project, Language, Target
|
977
|
+
|
978
|
+
Rurema, Japanese, Japanese Rubyists
|
979
|
+
RDoc, English, All Rubyists
|
980
|
+
|
981
|
+
= Source\n(('note:ソース'))
|
982
|
+
|
983
|
+
* Shared nothing\n
|
984
|
+
(('note:共有していない'))
|
985
|
+
* Copy based share\n
|
986
|
+
(('note:共有するときはコピー'))
|
987
|
+
* e.g.:\n
|
988
|
+
Description,\n
|
989
|
+
Sample codes,\n
|
990
|
+
...\n
|
991
|
+
(('note:例:説明やサンプルコードなどをコピー'))
|
992
|
+
|
993
|
+
= From my point of view\n(('note:私が思うこと'))
|
994
|
+
|
995
|
+
* Can we share documents?\n
|
996
|
+
(('note:ドキュメントを共有できないかな'))
|
997
|
+
* How to work together deeply?\n
|
998
|
+
(('note:もっと協力してできないかな'))
|
999
|
+
|
1000
|
+
= I18n\n(('note:国際化'))
|
1001
|
+
|
1002
|
+
* Source: RDoc\n
|
1003
|
+
(('note:ソースはRDoc'))
|
1004
|
+
* For all Rubyists\n
|
1005
|
+
(('note:これは全Rubyist向け'))
|
1006
|
+
* Translate to Japanese\n
|
1007
|
+
(('note:RDocのドキュメントを日本語に翻訳'))
|
1008
|
+
* For Japanese Rubyists\n
|
1009
|
+
(('note:これは日本人Rubyist向け'))
|
1010
|
+
|
1011
|
+
= Add i18n support\n(('note:国際化サポートを追加'))
|
1012
|
+
|
1013
|
+
* YARD
|
1014
|
+
* Since 0.8.0 at 2012-04
|
1015
|
+
* RDoc
|
1016
|
+
* Since 4.2.0 at 2014-12
|
1017
|
+
|
1018
|
+
= YARD - i18n
|
1019
|
+
|
1020
|
+
# coderay console
|
1021
|
+
|
1022
|
+
# Generates po/yard.pot
|
1023
|
+
# po/yard.potを生成
|
1024
|
+
% yard i18n
|
1025
|
+
|
1026
|
+
= YARD - i18n
|
1027
|
+
|
1028
|
+
# coderay console
|
1029
|
+
|
1030
|
+
# Create po/ja.po from po/yard.pot
|
1031
|
+
# po/yard.potからpo/ja.poを作成
|
1032
|
+
% msginit \
|
1033
|
+
--locale=ja_JP.UTF-8 \
|
1034
|
+
--input=po/yard.pot \
|
1035
|
+
--output-file=po/ja.po
|
1036
|
+
|
1037
|
+
= YARD - i18n
|
1038
|
+
|
1039
|
+
# coderay console
|
1040
|
+
|
1041
|
+
# Translate messages in po/ja.po
|
1042
|
+
# po/ja.po内のメッセージを翻訳
|
1043
|
+
% editor po/ja.po
|
1044
|
+
|
1045
|
+
= YARD - i18n
|
1046
|
+
|
1047
|
+
# coderay console
|
1048
|
+
|
1049
|
+
# Generate documents with
|
1050
|
+
# translated messages
|
1051
|
+
# 翻訳したメッセージを使って
|
1052
|
+
# ドキュメント生成
|
1053
|
+
% yard --locale ja
|
1054
|
+
|
1055
|
+
= Packnga
|
1056
|
+
|
1057
|
+
Rake task\n
|
1058
|
+
for\n
|
1059
|
+
YARD i18n\n
|
1060
|
+
(('note:YARDの国際化機能向けのRakeタスク'))
|
1061
|
+
|
1062
|
+
= Setting\n(('note:設定'))
|
1063
|
+
|
1064
|
+
# coderay ruby
|
1065
|
+
|
1066
|
+
# Rakefile
|
1067
|
+
require "packnga"
|
1068
|
+
Packnga::DocumentTask.new(spec) do |task|
|
1069
|
+
task.original_language = "en"
|
1070
|
+
task.translate_languages = ["ja"]
|
1071
|
+
end
|
1072
|
+
|
1073
|
+
= Workflow\n(('note:ワークフロー'))
|
1074
|
+
|
1075
|
+
# coderay console
|
1076
|
+
|
1077
|
+
% rake reference:translate
|
1078
|
+
% editor doc/po/ja/x.edit.po
|
1079
|
+
% rake reference:translate
|
1080
|
+
% editor lib/x.rb
|
1081
|
+
% rake reference:translate
|
1082
|
+
...
|
1083
|
+
|
1084
|
+
= Users\n(('note:ユーザー'))
|
1085
|
+
|
1086
|
+
* test-unit
|
1087
|
+
* Rroonga
|
1088
|
+
* ...
|
1089
|
+
|
1090
|
+
= RDoc - i18n
|
1091
|
+
|
1092
|
+
# coderay console
|
1093
|
+
|
1094
|
+
# Generates doc/rdoc.pot
|
1095
|
+
# doc/rdoc.potを生成
|
1096
|
+
% rdoc --format=pot
|
1097
|
+
|
1098
|
+
= RDoc - i18n
|
1099
|
+
|
1100
|
+
# coderay console
|
1101
|
+
|
1102
|
+
# Create locale/ja.po
|
1103
|
+
# from doc/rdoc.pot
|
1104
|
+
# doc/rdoc.potからlocale/ja.poを作成
|
1105
|
+
% mkdir -p locale
|
1106
|
+
% msginit \
|
1107
|
+
--locale=ja_JP.UTF-8 \
|
1108
|
+
--input=doc/rdoc.pot \
|
1109
|
+
--output-file=locale/ja.po
|
1110
|
+
|
1111
|
+
= RDoc - i18n
|
1112
|
+
|
1113
|
+
# coderay console
|
1114
|
+
|
1115
|
+
# Translate messages in locale/ja.po
|
1116
|
+
# locale/ja.po内のメッセージを翻訳
|
1117
|
+
% editor locale/ja.po
|
1118
|
+
|
1119
|
+
= RDoc - i18n
|
1120
|
+
|
1121
|
+
# coderay console
|
1122
|
+
|
1123
|
+
# Generate documents with
|
1124
|
+
# translated messages
|
1125
|
+
# 翻訳したメッセージを使って
|
1126
|
+
# ドキュメント生成
|
1127
|
+
% rdoc --locale ja
|
1128
|
+
|
1129
|
+
= RDoc, Rurema and i18n
|
1130
|
+
|
1131
|
+
* No progress...\n
|
1132
|
+
(('note:ツールの整備まででそれ以降は進んでいない。。。'))
|
1133
|
+
* Do you want to work with me?\n
|
1134
|
+
(('note:一緒にやりたい人はいる?'))
|
1135
|
+
|
1136
|
+
= jekyll-task-i18n
|
1137
|
+
|
1138
|
+
Jekyll + i18n
|
1139
|
+
|
1140
|
+
= Features\n(('note:機能'))
|
1141
|
+
|
1142
|
+
* Support all markups!\n
|
1143
|
+
(('note:すべてのマークアップ対応!'))
|
1144
|
+
* GitHub Pages ready!\n
|
1145
|
+
(('note:GitHub Pagesでも使える!'))
|
1146
|
+
|
1147
|
+
= Setting(('note:(設定)'))
|
1148
|
+
|
1149
|
+
# coderay ruby
|
1150
|
+
|
1151
|
+
# Rakefile
|
1152
|
+
require "jekyll/task/i18n"
|
1153
|
+
Jekyll::Task::I18n.define do |task|
|
1154
|
+
task.locales = ["ja"]
|
1155
|
+
task.files = Rake::FileList["**/*.md"]
|
1156
|
+
task.files -= Rake::FileList["_*/**/*.md"]
|
1157
|
+
task.locales.each do |locale|
|
1158
|
+
task.files -= Rake::FileList["#{locale}/**/*.md"]
|
1159
|
+
end
|
1160
|
+
end
|
1161
|
+
task default: ["jekyll:i18n:translate"]
|
1162
|
+
|
1163
|
+
= Workflow(('note:(ワークフロー)'))
|
1164
|
+
|
1165
|
+
% editor index.md
|
1166
|
+
% rake
|
1167
|
+
% editor _po/ja/index.edit.po
|
1168
|
+
% rake
|
1169
|
+
% git commit -a
|
1170
|
+
|
1171
|
+
= User - Red Data Tools
|
1172
|
+
|
1173
|
+
# img
|
1174
|
+
# src = images/jekyll-task-i18n-red-data-tools.gif
|
1175
|
+
# relative_height = 78
|
1176
|
+
|
1177
|
+
(('tag:center'))
|
1178
|
+
(('tag:small'))
|
1179
|
+
((<URL:https://red-data-tools.github.io/>))
|
1180
|
+
|
1181
|
+
= groonga-client
|
1182
|
+
|
1183
|
+
Full text search\n
|
1184
|
+
((*client*))\n
|
1185
|
+
(('note:全文検索クライアント'))
|
1186
|
+
|
1187
|
+
= Library vs ((*Client*))\n(('note:ライブラリー対クライアント'))
|
1188
|
+
|
1189
|
+
* Less dependencies\n
|
1190
|
+
(('note:依存関係が少ない'))
|
1191
|
+
* Less needed resource\n
|
1192
|
+
(('note:必要なリソースが少ない'))
|
1193
|
+
|
1194
|
+
= Search(('note:(検索)'))
|
1195
|
+
|
1196
|
+
# coderay ruby
|
1197
|
+
|
1198
|
+
require "groonga/client"
|
1199
|
+
url = "http://localhost:10041"
|
1200
|
+
Groonga::Client.open(url: url) do |client|
|
1201
|
+
response =
|
1202
|
+
client.select(table: "docs",
|
1203
|
+
match_columns: "content",
|
1204
|
+
query: "concat")
|
1205
|
+
p response.n_hits # => 1
|
1206
|
+
end
|
1207
|
+
|
1208
|
+
= Asynchronous(('note:(非同期)'))
|
1209
|
+
|
1210
|
+
# coderay ruby
|
1211
|
+
|
1212
|
+
# Call with block
|
1213
|
+
client.select(table: "docs",
|
1214
|
+
match_columns: "content",
|
1215
|
+
query: "concat") do |response|
|
1216
|
+
p response.n_hits # => 1
|
1217
|
+
end
|
1218
|
+
p :here # => :here then ↑
|
1219
|
+
sleep(0.1)
|
1220
|
+
|
1221
|
+
= Asynchronous - wait
|
1222
|
+
|
1223
|
+
# coderay ruby
|
1224
|
+
|
1225
|
+
request =
|
1226
|
+
client.select(table: "docs",
|
1227
|
+
match_columns: "content",
|
1228
|
+
query: "concat") do |response|
|
1229
|
+
p response.n_hits # => 1
|
1230
|
+
end
|
1231
|
+
p :here # => :here then ↑
|
1232
|
+
request.wait
|
1233
|
+
|
1234
|
+
= groonga-client-rails
|
1235
|
+
|
1236
|
+
Ruby on Rails\n
|
1237
|
+
integration\n
|
1238
|
+
for\n
|
1239
|
+
groonga-client\n
|
1240
|
+
(('note:Ruby on Railsで使う'))
|
1241
|
+
|
1242
|
+
= Architecture\n(('note:アーキテクチャー'))
|
1243
|
+
|
1244
|
+
* Data: RDBMS\n
|
1245
|
+
(('note:データはRDBMSに格納'))
|
1246
|
+
* Full text search: Groonga\n
|
1247
|
+
(('note:全文検索はGroongaで処理'))
|
1248
|
+
|
1249
|
+
= Define app searcher\n(('note:アプリ用サーチャーを定義'))
|
1250
|
+
|
1251
|
+
# coderay ruby
|
1252
|
+
|
1253
|
+
# app/searchers/application_searcher.rb
|
1254
|
+
class ApplicationSearcher <
|
1255
|
+
Groonga::Client::Searcher
|
1256
|
+
end
|
1257
|
+
|
1258
|
+
= Define searcher\n(('note:サーチャーを定義'))
|
1259
|
+
|
1260
|
+
# coderay ruby
|
1261
|
+
|
1262
|
+
# app/searchers/document_searcher.rb
|
1263
|
+
class DocumentsSearcher < ApplicationSearcher
|
1264
|
+
# Define a full text search index as "content"
|
1265
|
+
# 全文検索用のインデックスを定義
|
1266
|
+
schema.column :content, {
|
1267
|
+
type: "Text",
|
1268
|
+
index: true,
|
1269
|
+
index_type: :full_text_search,
|
1270
|
+
}
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
= Bind to model\n(('note:モデルと結びつける'))
|
1274
|
+
|
1275
|
+
# coderay ruby
|
1276
|
+
|
1277
|
+
# app/models/document.rb
|
1278
|
+
class Document < ApplicationRecord
|
1279
|
+
# DocumentsSearcher searches Document model
|
1280
|
+
source = DocumentsSearcher.source(self)
|
1281
|
+
# Bind Document's "content" column to
|
1282
|
+
# DocumentsSearcher's "content" index
|
1283
|
+
source.content = :content
|
1284
|
+
end
|
1285
|
+
|
1286
|
+
= Search(('note:(検索)'))
|
1287
|
+
|
1288
|
+
# coderay ruby
|
1289
|
+
|
1290
|
+
# app/controllers/documents_controller.rb
|
1291
|
+
class DocumentsController < ApplicationController
|
1292
|
+
def index
|
1293
|
+
@query = params[:query]
|
1294
|
+
searcher = DocumentSearcher.new
|
1295
|
+
@result_set = searcher.search.
|
1296
|
+
query(@query).
|
1297
|
+
result_set
|
1298
|
+
end
|
1299
|
+
end
|
1300
|
+
|
1301
|
+
= See also\n(('note:参考情報'))
|
1302
|
+
|
1303
|
+
* Tutorial in Japanese\n
|
1304
|
+
(('note:日本語のチュートリアル'))
|
1305
|
+
* (('tag:xx-small'))
|
1306
|
+
((<URL:http://www.clear-code.com/blog/2016/12/22.html>))
|
1307
|
+
|
1308
|
+
= Groonga
|
1309
|
+
|
1310
|
+
mruby embedded\n
|
1311
|
+
full text search engine\n
|
1312
|
+
(('note:mruby組込の全文検索エンジン'))
|
1313
|
+
|
1314
|
+
= How mruby is used?\n(('note:mrubyの使い方'))
|
1315
|
+
|
1316
|
+
* Optimizer\n
|
1317
|
+
(('note:オプティマイザー'))
|
1318
|
+
* Custom command\n
|
1319
|
+
(('note:カスタムコマンド'))
|
1320
|
+
|
1321
|
+
= Custom command\n(('note:カスタムコマンド'))
|
1322
|
+
|
1323
|
+
# coderay ruby
|
1324
|
+
|
1325
|
+
module Sharding
|
1326
|
+
class LogicalSelectCommand < Groonga::Command
|
1327
|
+
# ...
|
1328
|
+
end
|
1329
|
+
end
|
1330
|
+
|
1331
|
+
= Use cases\n(('note:利用例'))
|
1332
|
+
|
1333
|
+
* Redmine plugin\n
|
1334
|
+
(('note:Redmineのプラグイン'))
|
1335
|
+
* (('tag:x-small'))
|
1336
|
+
Repository: ((<URL:https://github.com/clear-code/redmine_full_text_search>))
|
1337
|
+
* (('tag:x-small'))
|
1338
|
+
Slide (in Japanese): ((<URL:https://slide.rabbit-shocker.org/authors/kou/redmine-tokyo-12/>))
|
1339
|
+
* ...
|
1340
|
+
|
1341
|
+
= Ranguba (WIP)(('note:(開発中)'))
|
1342
|
+
|
1343
|
+
Full text search system\n
|
1344
|
+
(('note:全文検索システム'))
|
1345
|
+
|
1346
|
+
= Use cases\n(('note:利用例'))
|
1347
|
+
|
1348
|
+
* File server search\n
|
1349
|
+
(('note:ファイルサーバー検索'))
|
1350
|
+
* Mail search\n
|
1351
|
+
(('note:メール検索'))
|
1352
|
+
* Web site search\n
|
1353
|
+
(('note:Webサイト検索'))
|
1354
|
+
|
1355
|
+
= Features\n(('note:機能'))
|
1356
|
+
|
1357
|
+
* Crawlers\n
|
1358
|
+
(('note:クローラー'))
|
1359
|
+
* Web UI
|
1360
|
+
* CLI
|
1361
|
+
* Update documents\n
|
1362
|
+
(('note:更新'))
|
1363
|
+
* Search documents\n
|
1364
|
+
(('note:検索'))
|
1365
|
+
|
1366
|
+
= ChupaText
|
1367
|
+
|
1368
|
+
Text extractor\n
|
1369
|
+
(('note:テキスト抽出'))
|
1370
|
+
|
1371
|
+
= Supported formats\n(('note:対応フォーマット'))
|
1372
|
+
|
1373
|
+
* PDF
|
1374
|
+
* Office documents(('note:(オフィス文書)'))
|
1375
|
+
* OpenDocument, Word, Excel, ...
|
1376
|
+
* E-mail(('note:(メール)'))
|
1377
|
+
* ...
|
1378
|
+
|
1379
|
+
= Interface\n(('note:インターフェイス'))
|
1380
|
+
|
1381
|
+
* HTTP
|
1382
|
+
* Web UI
|
1383
|
+
* CLI
|
1384
|
+
* API (Library)
|
1385
|
+
|
1386
|
+
= Install - Docker
|
1387
|
+
|
1388
|
+
# coderay console
|
1389
|
+
% GITHUB=https://github.com
|
1390
|
+
% git clone \
|
1391
|
+
${GITHUB}/ranguba/chupa-text-docker.git
|
1392
|
+
% cd chupa-text-docker
|
1393
|
+
% docker-compose up --build
|
1394
|
+
|
1395
|
+
= How to use\n(('note:使い方'))
|
1396
|
+
|
1397
|
+
# coderay console
|
1398
|
+
% curl \
|
1399
|
+
--form data=@XXX.pdf \
|
1400
|
+
http://localhost:20080/extraction.json
|
1401
|
+
|
1402
|
+
= Use cases\n(('note:利用例'))
|
1403
|
+
|
1404
|
+
* Ranguba
|
1405
|
+
* Full text search system\n
|
1406
|
+
(('note:全文検索システム'))
|
1407
|
+
* Commit e-mail\n
|
1408
|
+
(('note:コミットメール'))
|
1409
|
+
|
1410
|
+
= git-commit-mailer
|
1411
|
+
|
1412
|
+
Commit e-mail for Git\n
|
1413
|
+
(('note:Git用のコミットメール'))
|
1414
|
+
|
1415
|
+
= Features\n(('note:機能'))
|
1416
|
+
|
1417
|
+
* HTML mail\n
|
1418
|
+
(('note:HTMLメール'))
|
1419
|
+
* Highlighted diff\n
|
1420
|
+
(('note:diffをハイライト'))
|
1421
|
+
* GitLab/GitHub Web hook support\n
|
1422
|
+
(('note:GitLab/GitHubのWebフックをサポート'))
|
1423
|
+
* (('tag:xx-small'))
|
1424
|
+
By ((<"GitHub:clear-code/github-web-hooks-receiver"|URL:https://github.com/clear-code/github-web-hooks-receiver>))
|
1425
|
+
|
1426
|
+
= Users\n(('note:利用者'))
|
1427
|
+
|
1428
|
+
* tDiary
|
1429
|
+
* My products
|
1430
|
+
|
1431
|
+
= commit-email.info
|
1432
|
+
|
1433
|
+
Commit e-mail\n
|
1434
|
+
as a\n
|
1435
|
+
Service\n
|
1436
|
+
(('note:コミットメールのクラウドサービス'))
|
1437
|
+
|
1438
|
+
= How to use\n(('note:使い方'))
|
1439
|
+
|
1440
|
+
* Send a pull request to\n
|
1441
|
+
((<"GitHub:kou/commit-email.info"|URL:https://github.com/kou/commit-email.info>))\n
|
1442
|
+
(('note:pull requestを送る'))
|
1443
|
+
* Register a Web hook\n
|
1444
|
+
(('note:Webフックを登録'))
|
1445
|
+
* Subscribe your mailing list\n
|
1446
|
+
(('note:メーリングリストを購読'))
|
1447
|
+
|
1448
|
+
(('note:See also ((<URL:http://www.commit-email.info/>))'))
|
1449
|
+
|
1450
|
+
= Category5\n(('note:分類5'))
|
1451
|
+
|
1452
|
+
Data processing\n
|
1453
|
+
(('note:データ処理'))
|
1454
|
+
|
1455
|
+
= csv
|
1456
|
+
|
1457
|
+
CSV parser\n
|
1458
|
+
(('note:CSVパーサー'))
|
1459
|
+
|
1460
|
+
= csv - History\n(('note:歴史'))
|
1461
|
+
|
1462
|
+
* 2003: Import\n
|
1463
|
+
(('note:Rubyに取り込み'))
|
1464
|
+
* 2007: Replaced with FasterCSV\n
|
1465
|
+
(('note:FasterCSVで置き換え'))
|
1466
|
+
* 2018: I became a co-maintainer with mrkn\n
|
1467
|
+
(('note:mrknと一緒にメンテナーになった'))
|
1468
|
+
|
1469
|
+
= Why?\n(('note:なんで?'))
|
1470
|
+
|
1471
|
+
* There are many CSV data\n
|
1472
|
+
(('note:CSVのデータはたくさんある'))
|
1473
|
+
* Important to process data\n
|
1474
|
+
(('note:データを処理するためにCSVパーサーは重要'))
|
1475
|
+
|
1476
|
+
= CSV format problems\n(('note:CSVフォーマットの問題'))
|
1477
|
+
|
1478
|
+
* Slow to parse\n
|
1479
|
+
(('note:パースが遅い'))
|
1480
|
+
* Too wild\n
|
1481
|
+
(('note:なんでもあり'))
|
1482
|
+
|
1483
|
+
= Red Arrow
|
1484
|
+
|
1485
|
+
Apache Arrow Ruby
|
1486
|
+
|
1487
|
+
= Red Arrow - History\n(('note:歴史'))
|
1488
|
+
|
1489
|
+
* 2017-02: The first commit\n
|
1490
|
+
(('note:最初のコミット'))
|
1491
|
+
* 2018-05: Became the "official" Ruby bindings of Apache Arrow\n
|
1492
|
+
(('note:Apache Arrowの公式Rubyバインディングになった'))
|
1493
|
+
|
1494
|
+
= Apache Arrow
|
1495
|
+
|
1496
|
+
* Super fast data format\n
|
1497
|
+
(('note:すごく速いデータフォーマット'))
|
1498
|
+
* For in-memory data\n
|
1499
|
+
(('note:インメモリーデータ用'))
|
1500
|
+
* Cross-language support\n
|
1501
|
+
(('note:いろんな言語がサポート'))
|
1502
|
+
* Easy to share data with Python, Java, ...\n
|
1503
|
+
(('note:PythonやJavaなどとデータ交換がしやすい'))
|
1504
|
+
|
1505
|
+
= Apache Arrow - Position\n(('note:立ち位置'))
|
1506
|
+
|
1507
|
+
* A very important peace\n
|
1508
|
+
in recent data processing\n
|
1509
|
+
(('note:最近のデータ処理界隈ではすごく大事な1ピース'))
|
1510
|
+
* Like JIT for Ruby 3\n
|
1511
|
+
(('note:Ruby 3で例えるとJITみたいな感じ'))
|
1512
|
+
|
1513
|
+
= Red Arrow - Impl.\n(('note:実装'))
|
1514
|
+
|
1515
|
+
* Based on Ruby/GI\n
|
1516
|
+
(('note:Ruby/GIを使っている'))
|
1517
|
+
* Auto generated bindings\n
|
1518
|
+
(('note:バインディングを自動生成'))
|
1519
|
+
|
1520
|
+
= Red Data Tools
|
1521
|
+
|
1522
|
+
A project to make Ruby data processable\n
|
1523
|
+
(('note:Rubyでデータ処理できるようにするためのプロジェクト'))
|
1524
|
+
|
1525
|
+
= Red Data Tools - History\n(('note:歴史'))
|
1526
|
+
|
1527
|
+
* 2017-02: Start(('note:(開始)'))
|
1528
|
+
* 2017-11-: Develop events per month at Tokyo at Speee. Inc,\n
|
1529
|
+
(('note:東京のSpeeeさんで毎月開発イベントを開催'))
|
1530
|
+
|
1531
|
+
= The number of products\n(('note:プロダクト数'))
|
1532
|
+
|
1533
|
+
About 20\n
|
1534
|
+
(('note:20くらい'))
|
1535
|
+
|
1536
|
+
= Red Datasets
|
1537
|
+
|
1538
|
+
Dataset fetcher\n
|
1539
|
+
(('note:データセット取得'))
|
1540
|
+
|
1541
|
+
= Supported datasets\n(('note:対応データセット'))
|
1542
|
+
|
1543
|
+
* Iris
|
1544
|
+
* CIFAR
|
1545
|
+
* Wikipedia
|
1546
|
+
|
1547
|
+
= Wikipedia
|
1548
|
+
|
1549
|
+
# coderay ruby
|
1550
|
+
|
1551
|
+
require "datasets"
|
1552
|
+
|
1553
|
+
wikipedia = Datasets::WikiPedia.new
|
1554
|
+
wikipedia.each do |page|
|
1555
|
+
p page.title
|
1556
|
+
end
|
1557
|
+
|
1558
|
+
= Wikipedia search
|
1559
|
+
|
1560
|
+
# coderay ruby
|
1561
|
+
|
1562
|
+
pages = Groonga["pages"]
|
1563
|
+
wikipedia = Datasets::WikiPedia.new
|
1564
|
+
wikipedia.each do |page|
|
1565
|
+
pages.add(title: page.title,
|
1566
|
+
content: page.revision.text)
|
1567
|
+
end
|
1568
|
+
ruby_pages = pages.select do |record|
|
1569
|
+
record.match("Ruby")
|
1570
|
+
end
|
1571
|
+
p ruby_pages.n_hits
|
1572
|
+
|
1573
|
+
= jekyll-jupyter-notebook
|
1574
|
+
|
1575
|
+
Jekyll\n
|
1576
|
+
(('+'))\n
|
1577
|
+
Jupyter Notebook
|
1578
|
+
|
1579
|
+
= Usage\n(('note:使い方'))
|
1580
|
+
|
1581
|
+
{% jupyter_notebook sample.ipynb %}
|
1582
|
+
|
1583
|
+
= Red OpenCV
|
1584
|
+
|
1585
|
+
Computer vision\n
|
1586
|
+
(('note:コンピュータービジョン'))
|
1587
|
+
|
1588
|
+
= Camera(('note:(カメラ)'))
|
1589
|
+
|
1590
|
+
# coderay ruby
|
1591
|
+
|
1592
|
+
require "cv"
|
1593
|
+
camera = CV::Camera.new
|
1594
|
+
image = camera.read
|
1595
|
+
image.write("capture.jpg")
|
1596
|
+
|
1597
|
+
= Face detect(('note:(顔認識)'))
|
1598
|
+
|
1599
|
+
# coderay ruby
|
1600
|
+
|
1601
|
+
image_gray = image.convert_color(:bgr2gray)
|
1602
|
+
classifier = # Face detector
|
1603
|
+
CV::CascadeClassifier.new("frontalface_alt")
|
1604
|
+
objects = classifier.detect(image_gray)
|
1605
|
+
color = CV::Color.new(0, 0, 255)
|
1606
|
+
objects.each do |object|
|
1607
|
+
# Draw detected area
|
1608
|
+
image.draw_rectangle(object, color)
|
1609
|
+
end
|
1610
|
+
image.write("detect.jpg")
|
1611
|
+
|
1612
|
+
= Red OpenCV - Impl.\n(('note:実装'))
|
1613
|
+
|
1614
|
+
* Based on Ruby/GI\n
|
1615
|
+
(('note:Ruby/GIを使っている'))
|
1616
|
+
* Auto generated bindings\n
|
1617
|
+
(('note:バインディングを自動生成'))
|
1618
|
+
|
1619
|
+
= Ad: RubyData Workshop\n(('note:宣伝:RubyDataワークショップ'))
|
1620
|
+
|
1621
|
+
* 2018-06-01 15:50/17:20
|
1622
|
+
* Contents:(('note:(内容)'))
|
1623
|
+
* Workshop by mrkn\n
|
1624
|
+
(('note:mrknによるワークショップ'))
|
1625
|
+
* Presentations what Red Data Tools did by members\n
|
1626
|
+
(('note:Red Data ToolsメンバーによるRed Data Toolsでやってきたことの紹介'))
|
1627
|
+
|
1628
|
+
= Process data with Ruby\n(('note:Rubyでデータ処理'))
|
1629
|
+
|
1630
|
+
* We're working on it\n
|
1631
|
+
(('note:Red Data Toolsは継続して取り組んでいる'))
|
1632
|
+
* Do you want to work with us?\n
|
1633
|
+
(('note:一緒にやりたい人はいる?'))
|
1634
|
+
|
1635
|
+
= How to join1(('note:(参加方法1)'))
|
1636
|
+
|
1637
|
+
* Join our chat rooms:\n
|
1638
|
+
(('note:チャットルームに参加'))
|
1639
|
+
* en: ((<"Gitter:red-data-tools/en"|URL:https://gitter.im/red-data-tools/en>))
|
1640
|
+
* ja: ((<"Gitter:red-data-tools/ja"|URL:https://gitter.im/red-data-tools/ja>))
|
1641
|
+
* Join monthly events at Tokyo\n
|
1642
|
+
(('note:東京での毎月の開発イベントに参加'))
|
1643
|
+
* ((<URL:https://speee.connpass.com/>))
|
1644
|
+
|
1645
|
+
= How to join2(('note:(参加方法2)'))
|
1646
|
+
|
1647
|
+
* Hire a developer to work on\n
|
1648
|
+
(('note:この問題に取り組む開発者を雇う'))
|
1649
|
+
* e.g.: mrkn by Speee, Inc.\n
|
1650
|
+
(('note:例:Speeeのmrkn'))
|
1651
|
+
|
1652
|
+
= How to join3(('note:(参加方法3)'))
|
1653
|
+
|
1654
|
+
* Order ClearCode to work on it\n
|
1655
|
+
(('note:クリアコードに開発の仕事を発注'))
|
1656
|
+
* Join ClearCode to work on it\n
|
1657
|
+
(('note:クリアコードに入って仕事として開発を進める'))
|
1658
|
+
|
1659
|
+
= Wrap up\n(('note:まとめ'))
|
1660
|
+
|
1661
|
+
* I'm working on the followings as a Rubyist\n
|
1662
|
+
(('note:Rubyistとしての私の活動'))
|
1663
|
+
* Increase what Ruby can\n
|
1664
|
+
(('note:Rubyでできることを増やす'))
|
1665
|
+
* Maintain libraries\n
|
1666
|
+
(('note:ライブラリーのメンテナス'))
|
1667
|
+
* Do you want to work with me?\n
|
1668
|
+
(('note:一緒にやりたい人はいる?'))
|