qiita_matome 0.0.1

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.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +22 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +0 -0
  6. data/.travis.yml +8 -0
  7. data/CONTRIBUTING.md +44 -0
  8. data/Gemfile +13 -0
  9. data/LICENSE.txt +22 -0
  10. data/README.md +210 -0
  11. data/Rakefile +8 -0
  12. data/bin/qiitam +34 -0
  13. data/lib/display.rb +10 -0
  14. data/lib/display/display_consts.rb +35 -0
  15. data/lib/display/displayer.rb +81 -0
  16. data/lib/file_writer.rb +19 -0
  17. data/lib/models/article.rb +38 -0
  18. data/lib/models/articles.rb +40 -0
  19. data/lib/qiita_json_loader.rb +43 -0
  20. data/lib/qiita_matome/version.rb +4 -0
  21. data/lib/qiita_matome_core.rb +121 -0
  22. data/lib/qiita_matome_dsl.rb +31 -0
  23. data/lib/qiita_matome_dsl_model.rb +37 -0
  24. data/lib/sort.rb +10 -0
  25. data/lib/sort/sort_consts.rb +28 -0
  26. data/lib/sort/sorter.rb +51 -0
  27. data/lib/validators.rb +13 -0
  28. data/lib/validators/article_validator.rb +19 -0
  29. data/lib/validators/articles_validator.rb +16 -0
  30. data/lib/validators/display_columns_validator.rb +41 -0
  31. data/lib/validators/sort_type_validator.rb +19 -0
  32. data/manual_test_docs/.gitkeep +0 -0
  33. data/qiita_matome.gemspec +28 -0
  34. data/samples/matome_title_asc.md +25 -0
  35. data/spec/display/displayer_spec.rb +341 -0
  36. data/spec/file_writer_spec.rb +92 -0
  37. data/spec/models/article_spec.rb +131 -0
  38. data/spec/models/articles_spec.rb +305 -0
  39. data/spec/qiita_matome_core_spec.rb +46 -0
  40. data/spec/sort/sorter_spec.rb +392 -0
  41. data/spec/spec_helper.rb +16 -0
  42. data/spec/validators/article_validator_spec.rb +53 -0
  43. data/spec/validators/articles_validator_spec.rb +54 -0
  44. data/spec/validators/display_columns_validator_spec.rb +58 -0
  45. data/spec/validators/sort_type_validator_spec.rb +54 -0
  46. metadata +202 -0
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+
3
+ module QiitaMatome
4
+ # QiitaMatome::Validators
5
+ module Validators
6
+ # ArticleValidator
7
+ class ArticleValidator
8
+ ARTICLE_CLASS_ERROR = "invalid argument class '%s'.article must be Array"
9
+
10
+ def self.validate(articles)
11
+ return if articles.empty?
12
+ articles.each do |article|
13
+ next if article.is_a?(Article)
14
+ fail ArgumentError, format(ARTICLE_CLASS_ERROR, article.class)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ module QiitaMatome
4
+ # QiitaMatome::Validators
5
+ module Validators
6
+ # ArticlesValidator
7
+ class ArticlesValidator
8
+ ARTICLES_CLASS_ERROR = "invalid argument class '%s'. articles must be Array" # rubocop:disable LineLength
9
+
10
+ def self.validate(articles)
11
+ return if articles.is_a?(Array)
12
+ fail ArgumentError, format(ARTICLES_CLASS_ERROR, articles.class)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ require 'display/display_consts'
3
+
4
+ module QiitaMatome
5
+ # QiitaMatome::Validators
6
+ module Validators
7
+ # DisplayColumnsValidator
8
+ class DisplayColumnsValidator
9
+ # rubocop:disable LineLength
10
+ DISPLAY_COLUMNS_TO_SYM_ERROR = "Invalid display_columns. Display_columns's class must be implement 'to_sym' method."
11
+ DISPLAY_COLUMNS_ERROR = "Invalid display_columns '%s'. Display_columns must be :title, :created_at, :updated_at, :stock_count or :no"
12
+ # rubocop:enable LineLength
13
+ DCC = Display::Consts::COLUMNS
14
+
15
+ class << self
16
+ def validate(display_columns)
17
+ display_columns.each do |display_column|
18
+ validate_each(display_column)
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def validate_each(display_column)
25
+ validate_to_sym(display_column)
26
+ validate_display_column(display_column.to_sym)
27
+ end
28
+
29
+ def validate_to_sym(display_column)
30
+ return if display_column.respond_to?(:to_sym)
31
+ fail ArgumentError, DISPLAY_COLUMNS_TO_SYM_ERROR
32
+ end
33
+
34
+ def validate_display_column(display_column)
35
+ return if DCC.include?(display_column)
36
+ fail ArgumentError, format(DISPLAY_COLUMNS_ERROR, display_column)
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ require 'sort/sort_consts'
3
+
4
+ module QiitaMatome
5
+ # QiitaMatome::Validators
6
+ module Validators
7
+ # SortTypeValidator
8
+ class SortTypeValidator
9
+ # rubocop:disable LineLength
10
+ SORT_TYPE_ERROR = "invalid sort_type '%s'. sort_type must be 'created_at_asc', 'created_at_desc', 'updated_at_asc', 'updated_at_desc', 'title_date_asc', 'title_date_desc', 'stock_count_asc' or 'stock_count_desc'"
11
+ # rubocop:enable LineLength
12
+
13
+ def self.validate(sort_type)
14
+ return if Sort::Consts::ALL_TYPES.include?(sort_type)
15
+ fail ArgumentError, format(SORT_TYPE_ERROR, sort_type)
16
+ end
17
+ end
18
+ end
19
+ end
File without changes
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'qiita_matome/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'qiita_matome'
8
+ spec.version = QiitaMatome::VERSION
9
+ spec.authors = ['tbpgr']
10
+ spec.email = ['tbpgr@tbpgr.jp']
11
+ spec.summary = %q(Qiita article matome generator)
12
+ spec.description = %q(Qiita article matome generator)
13
+ spec.homepage = 'https://github.com/tbpgr/qiita_matome'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'activemodel', '~> 4.0', '>= 4.0.2'
22
+ spec.add_runtime_dependency 'thor', '~> 0.18.1'
23
+
24
+ spec.add_development_dependency 'rspec', '~> 2.14', '>= 2.14.1'
25
+ spec.add_development_dependency 'simplecov', '~> 0.8', '>= 0.8.2'
26
+ spec.add_development_dependency 'bundler', '~> 1.6'
27
+ spec.add_development_dependency 'rake', '~> 0'
28
+ end
@@ -0,0 +1,25 @@
1
+ # RuboCop まとめ タイトル昇順
2
+
3
+ 更新日: 2014/07/01 22:51:13
4
+
5
+ |No.|タイトル|作成日|ストック数|
6
+ |--:|:--|:--:|--:|
7
+ |1|[RuboCop Style/AccessModifierIndentation](http://qiita.com/tbpgr/items/706d2b93052154772f18)|2014/06/15 00:53:36|4|
8
+ |2|[RuboCop Style/AlignHash EnforcedColonStyle](http://qiita.com/tbpgr/items/b23d30a3b6284e800b60)|2014/06/16 21:41:26|4|
9
+ |3|[RuboCop Style/AlignHash EnforcedHashRocketStyle](http://qiita.com/tbpgr/items/36788d9da32e7a6d6f43)|2014/06/15 23:19:06|3|
10
+ |4|[RuboCop Style/AlignHash EnforcedLastArgumentHashStyle](http://qiita.com/tbpgr/items/e07749ec716247f0a409)|2014/06/17 21:25:54|4|
11
+ |5|[RuboCop Style/AlignParameters EnforcedStyle](http://qiita.com/tbpgr/items/414e3aad8c3b56d2ce04)|2014/06/18 22:44:12|4|
12
+ |6|[RuboCop Style/BlockNesting](http://qiita.com/tbpgr/items/21cca635527eb03e64f2)|2014/06/19 21:48:37|3|
13
+ |7|[RuboCop Style/BracesAroundHashParameters EnforcedStyle](http://qiita.com/tbpgr/items/8932a19d154fc3d7c142)|2014/06/20 21:27:07|3|
14
+ |8|[RuboCop Style/CaseIndentation Indent One Step](http://qiita.com/tbpgr/items/d14e825f6eb9c9175d6a)|2014/06/22 21:18:23|2|
15
+ |9|[RuboCop Style/CaseIndentation IndentWhenRelativeTo](http://qiita.com/tbpgr/items/7323c764e3ae046a0fde)|2014/06/21 13:31:37|2|
16
+ |10|[RuboCop Style/ClassAndModuleChildren EnforcedStyle](http://qiita.com/tbpgr/items/61b9da235701df919ae5)|2014/06/23 22:12:53|2|
17
+ |11|[RuboCop Style/ClassLength](http://qiita.com/tbpgr/items/44087a9f4c6548043ace)|2014/06/24 20:28:50|2|
18
+ |12|[RuboCop Style/CollectionMethods PreferredMethods](http://qiita.com/tbpgr/items/a982166bbd473fcd4e6e)|2014/06/26 00:06:37|1|
19
+ |13|[RuboCop Style/CommentAnnotation](http://qiita.com/tbpgr/items/5b0cee75305cef801851)|2014/06/26 21:29:33|2|
20
+ |14|[RuboCop Style/CyclomaticComplexity](http://qiita.com/tbpgr/items/693f37d763c6ea5f9e9b)|2014/06/27 21:55:52|2|
21
+ |15|[RuboCop Style/DotPosition](http://qiita.com/tbpgr/items/c53f86c876f73c1aa5a8)|2014/06/28 23:08:32|2|
22
+ |16|[RuboCop Style/EmptyLineBetweenDefs](http://qiita.com/tbpgr/items/2872f2a27430372d43e4)|2014/06/29 19:49:56|2|
23
+ |17|[RuboCop Style/FileName](http://qiita.com/tbpgr/items/97fc9186e59d607b1ecf)|2014/06/30 21:56:25|1|
24
+ |18|[RuboCopの警告をコメントで無効化する方法](http://qiita.com/tbpgr/items/a9000c5c6fa92a46c206)|2014/06/08 21:27:21|6|
25
+
@@ -0,0 +1,341 @@
1
+ # encoding: utf-8
2
+ require 'spec_helper'
3
+ require 'display/display_consts'
4
+ require 'display/displayer'
5
+ require 'models/article'
6
+ require 'models/articles'
7
+
8
+ # rubocop:disable LineLength, UnusedMethodArgument
9
+ describe QiitaMatome::Display::Displayer do
10
+ context :new do
11
+ cases = [
12
+ {
13
+ case_no: 1,
14
+ case_title: 'valid args',
15
+ articles: [QiitaMatome::Article.new, QiitaMatome::Article.new],
16
+ display_columns: [:no, :title],
17
+ expected_display_columns: [:no, :title]
18
+ },
19
+ {
20
+ case_no: 2,
21
+ case_title: 'invalid articles class "String"',
22
+ articles: 'String',
23
+ display_columns: [:no, :title],
24
+ expect_error: true
25
+ },
26
+ {
27
+ case_no: 3,
28
+ case_title: 'invalid article class "String"',
29
+ articles: [QiitaMatome::Article.new, 'String'],
30
+ display_columns: [:no, :title],
31
+ expect_error: true
32
+ },
33
+ {
34
+ case_no: 4,
35
+ case_title: 'invalid display_columns "invalid"',
36
+ articles: [QiitaMatome::Article.new, QiitaMatome::Article.new],
37
+ display_columns: 'invalid',
38
+ expect_error: true
39
+ },
40
+ {
41
+ case_no: 5,
42
+ case_title: 'valid args(auto convert display_columns)',
43
+ articles: [QiitaMatome::Article.new, QiitaMatome::Article.new],
44
+ display_columns: 'title',
45
+ expected_display_columns: [:title]
46
+ },
47
+ {
48
+ case_no: 6,
49
+ case_title: 'invalid display_columns than haven\'t to_sym method.',
50
+ articles: [QiitaMatome::Article.new, QiitaMatome::Article.new],
51
+ display_columns: 1,
52
+ expect_error: true
53
+ },
54
+ {
55
+ case_no: 7,
56
+ case_title: 'valid args(updated_at)',
57
+ articles: [QiitaMatome::Article.new, QiitaMatome::Article.new],
58
+ display_columns: [:created_at, :updated_at],
59
+ expected_display_columns: [:created_at, :updated_at]
60
+ }
61
+ ]
62
+
63
+ cases.each do |c|
64
+ it "|case_no=#{c[:case_no]}|case_title=#{c[:case_title]}" do
65
+ begin
66
+ case_before c
67
+
68
+ # -- given --
69
+ if c[:expect_error]
70
+ -> { QiitaMatome::Display::Displayer.new('title', c[:articles], c[:display_columns]) }.should raise_error(ArgumentError)
71
+ next
72
+ end
73
+ qdd = QiitaMatome::Display::Displayer.new('title', c[:articles], c[:display_columns])
74
+
75
+ # -- when --
76
+ actual_articles = qdd.articles
77
+ actual_display_columns = qdd.display_columns
78
+
79
+ # -- then --
80
+ expect(actual_articles).to eq(c[:articles])
81
+ expect(actual_display_columns).to eq(c[:expected_display_columns])
82
+ ensure
83
+ case_after c
84
+ end
85
+ end
86
+
87
+ def case_before(c)
88
+ # implement each case before
89
+ end
90
+
91
+ def case_after(c)
92
+ # implement each case after
93
+ end
94
+ end
95
+ end
96
+
97
+ context :display_title do
98
+ cases = [
99
+ {
100
+ case_no: 1,
101
+ case_title: 'valid args',
102
+ articles: [QiitaMatome::Article.new, QiitaMatome::Article.new],
103
+ title: 'title1',
104
+ expected: '# title1'
105
+ }
106
+ ]
107
+
108
+ cases.each do |c|
109
+ it "|case_no=#{c[:case_no]}|case_title=#{c[:case_title]}" do
110
+ begin
111
+ case_before c
112
+
113
+ # -- given --
114
+ qdd = QiitaMatome::Display::Displayer.new(c[:title], c[:articles])
115
+
116
+ # -- when --
117
+ actual = qdd.display_title
118
+
119
+ # -- then --
120
+ expect(actual).to eq(c[:expected])
121
+ ensure
122
+ case_after c
123
+ end
124
+ end
125
+
126
+ def case_before(c)
127
+ # implement each case before
128
+ end
129
+
130
+ def case_after(c)
131
+ # implement each case after
132
+ end
133
+ end
134
+ end
135
+
136
+ context :table_header do
137
+ TABLE_HEADER_ARTICLE = QiitaMatome::Article.new(
138
+ 'user' => { 'id' => 99_999, 'url_name' => 'tbpgr', 'profile_image_url' => '' },
139
+ 'title' => 'title1',
140
+ 'created_at' => '2014-06-18 22:37:54 +0900',
141
+ 'updated_at' => '2014-06-26 02:25:11 +0900',
142
+ 'tags' => [{ 'name' => 'Ruby', 'url_name' => 'ruby', 'icon_url' => '', 'versions' => [] }],
143
+ 'stock_count' => 2
144
+ )
145
+
146
+ cases = [
147
+ {
148
+ case_no: 1,
149
+ case_title: 'valid args',
150
+ articles: [TABLE_HEADER_ARTICLE, QiitaMatome::Article.new],
151
+ display_columns: [:no, :title],
152
+ expected: <<-EOS
153
+ |No.|タイトル|
154
+ |--:|:--|
155
+ EOS
156
+ },
157
+ {
158
+ case_no: 2,
159
+ case_title: 'full display args',
160
+ articles: [TABLE_HEADER_ARTICLE, QiitaMatome::Article.new],
161
+ display_columns: [:no, :title, :created_at, :stock_count],
162
+ expected: <<-EOS
163
+ |No.|タイトル|作成日|ストック数|
164
+ |--:|:--|:--:|--:|
165
+ EOS
166
+ }
167
+ ]
168
+
169
+ cases.each do |c|
170
+ it "|case_no=#{c[:case_no]}|case_title=#{c[:case_title]}" do
171
+ begin
172
+ case_before c
173
+
174
+ # -- given --
175
+ qdd = QiitaMatome::Display::Displayer.new(c[:title], c[:articles], c[:display_columns])
176
+
177
+ # -- when --
178
+ actual = qdd.table_header
179
+
180
+ # -- then --
181
+ expect(actual).to eq(c[:expected])
182
+ ensure
183
+ case_after c
184
+ end
185
+ end
186
+
187
+ def case_before(c)
188
+ # implement each case before
189
+ end
190
+
191
+ def case_after(c)
192
+ # implement each case after
193
+ end
194
+ end
195
+ end
196
+
197
+ context :display_article do
198
+ DISPLAY_ARTICLE = QiitaMatome::Article.new(
199
+ 'uuid' => 'd1ed617093609ccedbee',
200
+ 'user' => { 'id' => 99_999, 'url_name' => 'tbpgr', 'profile_image_url' => '' },
201
+ 'title' => 'title1',
202
+ 'created_at' => '2014-06-18 22:37:54 +0900',
203
+ 'updated_at' => '2014-06-26 02:25:11 +0900',
204
+ 'tags' => [{ 'name' => 'Ruby', 'url_name' => 'ruby', 'icon_url' => '', 'versions' => [] }],
205
+ 'stock_count' => 2
206
+ )
207
+
208
+ cases = [
209
+ {
210
+ case_no: 1,
211
+ case_title: 'valid args',
212
+ articles: [DISPLAY_ARTICLE, QiitaMatome::Article.new],
213
+ article: DISPLAY_ARTICLE,
214
+ no: 1,
215
+ display_columns: [:no, :title],
216
+ expected: '|1|[title1](http://qiita.com/tbpgr/items/d1ed617093609ccedbee)|'
217
+ },
218
+ {
219
+ case_no: 2,
220
+ case_title: 'full display args',
221
+ articles: [DISPLAY_ARTICLE, QiitaMatome::Article.new],
222
+ article: DISPLAY_ARTICLE,
223
+ no: 1,
224
+ display_columns: [:no, :title, :created_at, :stock_count],
225
+ expected: '|1|[title1](http://qiita.com/tbpgr/items/d1ed617093609ccedbee)|2014/06/18 22:37:54|2|'
226
+ }
227
+ ]
228
+
229
+ cases.each do |c|
230
+ it "|case_no=#{c[:case_no]}|case_title=#{c[:case_title]}" do
231
+ begin
232
+ case_before c
233
+
234
+ # -- given --
235
+ qdd = QiitaMatome::Display::Displayer.new('title', c[:articles], c[:display_columns])
236
+
237
+ # -- when --
238
+ actual = qdd.display_article(c[:no], c[:article])
239
+
240
+ # -- then --
241
+ expect(actual).to eq(c[:expected])
242
+ ensure
243
+ case_after c
244
+ end
245
+ end
246
+
247
+ def case_before(c)
248
+ # implement each case before
249
+ end
250
+
251
+ def case_after(c)
252
+ # implement each case after
253
+ end
254
+ end
255
+ end
256
+
257
+ context :display_articles do
258
+ DISPLAY_ARTICLES = [
259
+ QiitaMatome::Article.new(
260
+ 'uuid' => 'd1ed617093609ccedbee',
261
+ 'user' => { 'id' => 99_999, 'url_name' => 'tbpgr', 'profile_image_url' => '' },
262
+ 'title' => 'title1',
263
+ 'created_at' => '2014-06-18 22:37:54 +0900',
264
+ 'updated_at' => '2014-06-26 02:25:11 +0900',
265
+ 'tags' => [{ 'name' => 'Ruby', 'url_name' => 'ruby', 'icon_url' => '', 'versions' => [] }],
266
+ 'stock_count' => 2
267
+ ),
268
+ QiitaMatome::Article.new(
269
+ 'uuid' => 'd1ed617093609ccedbef',
270
+ 'user' => { 'id' => 99_999, 'url_name' => 'tbpgr', 'profile_image_url' => '' },
271
+ 'title' => 'title2',
272
+ 'created_at' => '2014-06-18 22:37:53 +0900',
273
+ 'updated_at' => '2014-06-26 02:25:09 +0900',
274
+ 'tags' => [{ 'name' => 'Ruby', 'url_name' => 'ruby', 'icon_url' => '', 'versions' => [] }],
275
+ 'stock_count' => 3
276
+ ),
277
+ QiitaMatome::Article.new(
278
+ 'uuid' => 'd1ed617093609ccedbeg',
279
+ 'user' => { 'id' => 99_999, 'url_name' => 'tbpgr', 'profile_image_url' => '' },
280
+ 'title' => 'title3',
281
+ 'created_at' => '2014-06-18 22:37:52 +0900',
282
+ 'updated_at' => '2014-06-26 02:25:10 +0900',
283
+ 'tags' => [{ 'name' => 'Ruby', 'url_name' => 'ruby', 'icon_url' => '', 'versions' => [] }],
284
+ 'stock_count' => 10
285
+ )
286
+ ]
287
+
288
+ cases = [
289
+ {
290
+ case_no: 1,
291
+ case_title: 'valid args',
292
+ articles: DISPLAY_ARTICLES,
293
+ display_columns: [:no, :title],
294
+ expected: <<-EOS
295
+ |1|[title1](http://qiita.com/tbpgr/items/d1ed617093609ccedbee)|
296
+ |2|[title2](http://qiita.com/tbpgr/items/d1ed617093609ccedbef)|
297
+ |3|[title3](http://qiita.com/tbpgr/items/d1ed617093609ccedbeg)|
298
+ EOS
299
+ },
300
+ {
301
+ case_no: 2,
302
+ case_title: 'full display args',
303
+ articles: DISPLAY_ARTICLES,
304
+ display_columns: [:no, :title, :created_at, :updated_at, :stock_count],
305
+ expected: <<-EOS
306
+ |1|[title1](http://qiita.com/tbpgr/items/d1ed617093609ccedbee)|2014/06/18 22:37:54|2014/06/26 02:25:11|2|
307
+ |2|[title2](http://qiita.com/tbpgr/items/d1ed617093609ccedbef)|2014/06/18 22:37:53|2014/06/26 02:25:09|3|
308
+ |3|[title3](http://qiita.com/tbpgr/items/d1ed617093609ccedbeg)|2014/06/18 22:37:52|2014/06/26 02:25:10|10|
309
+ EOS
310
+ }
311
+ ]
312
+
313
+ cases.each do |c|
314
+ it "|case_no=#{c[:case_no]}|case_title=#{c[:case_title]}" do
315
+ begin
316
+ case_before c
317
+
318
+ # -- given --
319
+ qdd = QiitaMatome::Display::Displayer.new('title', c[:articles], c[:display_columns])
320
+
321
+ # -- when --
322
+ actual = qdd.display_articles
323
+
324
+ # -- then --
325
+ expect(actual).to eq(c[:expected])
326
+ ensure
327
+ case_after c
328
+ end
329
+ end
330
+
331
+ def case_before(c)
332
+ # implement each case before
333
+ end
334
+
335
+ def case_after(c)
336
+ # implement each case after
337
+ end
338
+ end
339
+ end
340
+ end
341
+ # rubocop:enable LineLength, UnusedMethodArgument