metal_archives 2.1.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +93 -0
  3. data/.gitignore +6 -6
  4. data/.overcommit.yml +35 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +69 -6
  7. data/CHANGELOG.md +29 -0
  8. data/Gemfile +1 -1
  9. data/LICENSE.md +17 -4
  10. data/README.md +65 -86
  11. data/Rakefile +8 -7
  12. data/bin/console +38 -0
  13. data/bin/setup +8 -0
  14. data/config/inflections.rb +7 -0
  15. data/config/initializers/.keep +0 -0
  16. data/docker-compose.yml +23 -0
  17. data/lib/metal_archives.rb +82 -25
  18. data/lib/metal_archives/cache/base.rb +40 -0
  19. data/lib/metal_archives/cache/memory.rb +68 -0
  20. data/lib/metal_archives/cache/null.rb +22 -0
  21. data/lib/metal_archives/cache/redis.rb +49 -0
  22. data/lib/metal_archives/{utils/collection.rb → collection.rb} +3 -5
  23. data/lib/metal_archives/configuration.rb +33 -50
  24. data/lib/metal_archives/{error.rb → errors.rb} +9 -1
  25. data/lib/metal_archives/http_client.rb +45 -44
  26. data/lib/metal_archives/models/artist.rb +90 -45
  27. data/lib/metal_archives/models/band.rb +80 -55
  28. data/lib/metal_archives/models/base.rb +218 -0
  29. data/lib/metal_archives/models/label.rb +14 -15
  30. data/lib/metal_archives/models/release.rb +349 -0
  31. data/lib/metal_archives/parsers/artist.rb +86 -50
  32. data/lib/metal_archives/parsers/band.rb +155 -88
  33. data/lib/metal_archives/parsers/base.rb +14 -0
  34. data/lib/metal_archives/parsers/country.rb +21 -0
  35. data/lib/metal_archives/parsers/date.rb +31 -0
  36. data/lib/metal_archives/parsers/genre.rb +67 -0
  37. data/lib/metal_archives/parsers/label.rb +39 -31
  38. data/lib/metal_archives/parsers/parser.rb +16 -63
  39. data/lib/metal_archives/parsers/release.rb +242 -0
  40. data/lib/metal_archives/parsers/year.rb +29 -0
  41. data/lib/metal_archives/version.rb +12 -1
  42. data/metal_archives.env.example +10 -0
  43. data/metal_archives.gemspec +43 -28
  44. data/nginx/default.conf +60 -0
  45. metadata +181 -72
  46. data/.travis.yml +0 -12
  47. data/lib/metal_archives/middleware/cache_check.rb +0 -20
  48. data/lib/metal_archives/middleware/encoding.rb +0 -16
  49. data/lib/metal_archives/middleware/headers.rb +0 -38
  50. data/lib/metal_archives/middleware/rewrite_endpoint.rb +0 -38
  51. data/lib/metal_archives/models/base_model.rb +0 -215
  52. data/lib/metal_archives/utils/lru_cache.rb +0 -61
  53. data/lib/metal_archives/utils/nil_date.rb +0 -99
  54. data/lib/metal_archives/utils/range.rb +0 -66
  55. data/spec/configuration_spec.rb +0 -96
  56. data/spec/factories/artist_factory.rb +0 -37
  57. data/spec/factories/band_factory.rb +0 -60
  58. data/spec/factories/nil_date_factory.rb +0 -9
  59. data/spec/factories/range_factory.rb +0 -8
  60. data/spec/models/artist_spec.rb +0 -138
  61. data/spec/models/band_spec.rb +0 -164
  62. data/spec/models/base_model_spec.rb +0 -219
  63. data/spec/parser_spec.rb +0 -19
  64. data/spec/spec_helper.rb +0 -111
  65. data/spec/support/factory_girl.rb +0 -5
  66. data/spec/support/metal_archives.rb +0 -33
  67. data/spec/utils/collection_spec.rb +0 -72
  68. data/spec/utils/lru_cache_spec.rb +0 -53
  69. data/spec/utils/nil_date_spec.rb +0 -156
  70. data/spec/utils/range_spec.rb +0 -62
@@ -1,219 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
-
4
- ##
5
- # Sample model without :id property or :assemble method
6
- #
7
- class ModelOne < MetalArchives::BaseModel
8
- property :property_one
9
- end
10
-
11
- ##
12
- # Sample model without :assemble method
13
- #
14
- class ModelTwo < MetalArchives::BaseModel
15
- property :id
16
- property :property_one
17
- end
18
-
19
- ##
20
- # Sample complete model
21
- #
22
- class ModelThree < MetalArchives::BaseModel
23
- property :id
24
- property :property_one
25
-
26
- def assemble
27
- { :property_one => 'Property One' }
28
- end
29
- end
30
-
31
- ##
32
- # Sample complete model
33
- #
34
- class ModelFour < MetalArchives::BaseModel
35
- property :id
36
- property :property_one
37
-
38
- def assemble
39
- { :property_one => 'Property One' }
40
- end
41
- end
42
-
43
- ##
44
- # Sample invalid model
45
- #
46
- class ModelFive < MetalArchives::BaseModel
47
- property :id
48
- property :property_one
49
-
50
- def assemble
51
- raise MetalArchives::Errors::APIError
52
- end
53
- end
54
-
55
- RSpec.describe MetalArchives::BaseModel do
56
- it 'requires an :id property' do
57
- expect(-> { ModelOne.new(:property_one => 'foo') }).to raise_error MetalArchives::Errors::NotImplementedError
58
- end
59
-
60
- it 'requires an :assemble method' do
61
- expect(-> { ModelTwo.new(:id => 'foo').property_one }).to raise_error MetalArchives::Errors::NotImplementedError
62
- end
63
-
64
- it 'defines methods' do
65
- model = ModelTwo.new :id => 'foo'
66
-
67
- expect(model).to respond_to :id
68
- expect(model).to respond_to :id=
69
- expect(model).to respond_to :id?
70
- expect(model).to respond_to :property_one
71
- expect(model).to respond_to :property_one=
72
- expect(model).to respond_to :property_one?
73
- expect(model).not_to respond_to :property_two
74
- expect(model).not_to respond_to :property_two=
75
- expect(model).not_to respond_to :property_two?
76
- end
77
-
78
- it 'returns properties' do
79
- model = ModelThree.new :id => 'foo', :property_one => 'bar'
80
-
81
- model.instance_eval { |m| @loaded = true }
82
- expect(model.id).to eq 'foo'
83
- expect(model.property_one).to eq 'bar'
84
- end
85
-
86
- it 'sets properties' do
87
- model = ModelThree.new :id => 'foo', :property_one => 'bar'
88
-
89
- model.instance_eval { |m| @loaded = true }
90
- model.id = 'baz'
91
- model.property_one = 'bat'
92
-
93
- expect(model.id).to eq 'baz'
94
- expect(model.property_one).to eq 'bat'
95
- end
96
-
97
- it 'checks properties' do
98
- model = ModelThree.new :id => 'foo', :property_one => 'bar'
99
- model2 = ModelThree.new :id => 'foo'
100
- model2.load!
101
- model2.property_one = nil
102
-
103
- expect(model.id?).to be true
104
- expect(model.property_one?).to be true
105
-
106
- expect(model2.id?).to be true
107
- expect(model2.property_one?).to be false
108
- end
109
-
110
- it 'calls assemble' do
111
- model = ModelThree.new :id => 'foo'
112
-
113
- expect(model.id).to eq 'foo'
114
- expect(model.property_one).to eq 'Property One'
115
- end
116
-
117
- it 'lazily loads' do
118
- model = ModelThree.new :id => 'foo'
119
-
120
- expect(model).to be_instance_variable_defined '@id'
121
- expect(model).not_to be_instance_variable_defined '@property_one'
122
-
123
- model.property_one
124
-
125
- expect(model).to be_instance_variable_defined '@id'
126
- expect(model).to be_instance_variable_defined '@property_one'
127
- expect(model.property_one).to eq 'Property One'
128
- end
129
-
130
-
131
- it 'implements the load! operation' do
132
- model = ModelThree.new :id => 'foo'
133
-
134
- expect(model).to be_instance_variable_defined '@id'
135
- expect(model).not_to be_instance_variable_defined '@property_one'
136
-
137
- model.load!
138
-
139
- expect(model).to be_instance_variable_defined '@id'
140
- expect(model).to be_instance_variable_defined '@property_one'
141
- expect(model.property_one).to eq 'Property One'
142
- end
143
-
144
- it 'implements the equal operator' do
145
- m1 = ModelThree.new :id => 'id_one'
146
- m2 = ModelThree.new :id => 'id_one'
147
- m3 = ModelThree.new :id => 'id_two'
148
- m4 = ModelFour.new :id => 'id_one'
149
-
150
- expect(m1).to eq m2
151
- expect(m2).not_to eq m3
152
- expect(m1).not_to eq m3
153
- expect(m1).not_to eq m4
154
- expect(m2).not_to eq m4
155
- end
156
-
157
- describe 'loaded?' do
158
- it 'has a :loaded? method' do
159
- expect(ModelThree.new).to respond_to :loaded?
160
- end
161
-
162
- it 'returns false on lazy load' do
163
- m = ModelThree.new :id => 'id_one'
164
-
165
- expect(m).not_to be_loaded
166
- end
167
-
168
- it 'returns true on load!' do
169
- m = ModelThree.new :id => 'id_one'
170
- m.load!
171
-
172
- expect(m).to be_loaded
173
- end
174
- end
175
-
176
- describe 'cached?' do
177
- context 'valid model' do
178
- it 'has a :cached? method' do
179
- expect(ModelThree.new).to respond_to :cached?
180
- end
181
-
182
- it "doesn't cache lazily loaded objects" do
183
- m = ModelThree.new :id => 'id_one'
184
-
185
- expect(m).not_to be_loaded
186
- expect(m).not_to be_cached
187
- end
188
-
189
- it 'caches loaded objects' do
190
- m = ModelThree.new :id => 'id_one'
191
- m.load!
192
-
193
- expect(m).to be_loaded
194
- expect(m).to be_cached
195
- end
196
- end
197
-
198
- context 'invalid model' do
199
- it 'has a :cached? method' do
200
- expect(ModelFive.new).to respond_to :cached?
201
- end
202
-
203
- it "doesn't cache lazily loaded objects" do
204
- m = ModelFive.new :id => 'id_one'
205
-
206
- expect(m).not_to be_loaded
207
- expect(m).not_to be_cached
208
- end
209
-
210
- it "doesn't cache loaded invalid objects" do
211
- m = ModelFive.new :id => 'id_one'
212
- expect(-> { m.load! }).to raise_error MetalArchives::Errors::APIError
213
-
214
- expect(m).not_to be_loaded
215
- expect(m).not_to be_cached
216
- end
217
- end
218
- end
219
- end
data/spec/parser_spec.rb DELETED
@@ -1,19 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe MetalArchives::Parsers::Parser do
4
- it 'parses countries' do
5
- expect(described_class.parse_country('United States')).to eq ISO3166::Country['US']
6
- expect(described_class.parse_country('Germany')).to eq ISO3166::Country['DE']
7
- expect(described_class.parse_country('Belgium')).to eq ISO3166::Country['BE']
8
- end
9
-
10
- it 'parses genres' do
11
- expect(described_class.parse_genre('Death, Power, Black')).to match_array ['Black', 'Death', 'Power']
12
- expect(described_class.parse_genre('Death, Power, Black')).to match_array ['Black', 'Death', 'Power']
13
- expect(described_class.parse_genre('Death (early), Heavy/Power Metal, Black (later)')).to match_array ['Black', 'Death', 'Heavy', 'Power']
14
- expect(described_class.parse_genre(' Death , Power Metal, Power, Power')).to match_array ['Death', 'Power']
15
- expect(described_class.parse_genre('Heavy/Speed Power Metal')).to match_array ['Heavy Power', 'Speed Power']
16
- expect(described_class.parse_genre('Traditional Heavy/Power Metal')).to match_array ['Traditional Heavy', 'Traditional Power']
17
- expect(described_class.parse_genre('Traditional/Classical Heavy/Power Metal')).to match_array ['Traditional Heavy', 'Traditional Power', 'Classical Heavy', 'Classical Power']
18
- end
19
- end
data/spec/spec_helper.rb DELETED
@@ -1,111 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # This file was generated by the `rspec --init` command. Conventionally, all
4
- # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
- # The generated `.rspec` file contains `--require spec_helper` which will cause
6
- # this file to always be loaded, without a need to explicitly require it in any
7
- # files.
8
- #
9
- # Given that it is always loaded, you are encouraged to keep this file as
10
- # light-weight as possible. Requiring heavyweight dependencies from this file
11
- # will add to the boot time of your test suite on EVERY test run, even for an
12
- # individual file that may not need all of that loaded. Instead, consider making
13
- # a separate helper file that requires the additional dependencies and performs
14
- # the additional setup, and require it from the spec files that actually need
15
- # it.
16
- #
17
- # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
18
-
19
- require 'factory_girl'
20
- require 'faker'
21
- require 'coveralls'
22
- Coveralls.wear!
23
-
24
- require 'metal_archives'
25
-
26
- Dir[File.join(__dir__, 'support/**/*.rb')].each { |f| require f }
27
- Dir[File.join(__dir__, 'factories/**/*.rb')].each { |f| require f }
28
-
29
- RSpec.configure do |config|
30
- # rspec-expectations config goes here. You can use an alternate
31
- # assertion/expectation library such as wrong or the stdlib/minitest
32
- # assertions if you prefer.
33
- config.expect_with :rspec do |expectations|
34
- # This option will default to `true` in RSpec 4. It makes the `description`
35
- # and `failure_message` of custom matchers include text for helper methods
36
- # defined using `chain`, e.g.:
37
- # be_bigger_than(2).and_smaller_than(4).description
38
- # # => "be bigger than 2 and smaller than 4"
39
- # ...rather than:
40
- # # => "be bigger than 2"
41
- expectations.include_chain_clauses_in_custom_matcher_descriptions = true
42
- end
43
-
44
- # rspec-mocks config goes here. You can use an alternate test double
45
- # library (such as bogus or mocha) by changing the `mock_with` option here.
46
- config.mock_with :rspec do |mocks|
47
- # Prevents you from mocking or stubbing a method that does not exist on
48
- # a real object. This is generally recommended, and will default to
49
- # `true` in RSpec 4.
50
- mocks.verify_partial_doubles = true
51
- end
52
-
53
- # This option will default to `:apply_to_host_groups` in RSpec 4 (and will
54
- # have no way to turn it off -- the option exists only for backwards
55
- # compatibility in RSpec 3). It causes shared context metadata to be
56
- # inherited by the metadata hash of host groups and examples, rather than
57
- # triggering implicit auto-inclusion in groups with matching metadata.
58
- config.shared_context_metadata_behavior = :apply_to_host_groups
59
-
60
- # The settings below are suggested to provide a good initial experience
61
- # with RSpec, but feel free to customize to your heart's content.
62
- # # This allows you to limit a spec run to individual examples or groups
63
- # # you care about by tagging them with `:focus` metadata. When nothing
64
- # # is tagged with `:focus`, all examples get run. RSpec also provides
65
- # # aliases for `it`, `describe`, and `context` that include `:focus`
66
- # # metadata: `fit`, `fdescribe` and `fcontext`, respectively.
67
- # config.filter_run_when_matching :focus
68
- #
69
- # # Allows RSpec to persist some state between runs in order to support
70
- # # the `--only-failures` and `--next-failure` CLI options. We recommend
71
- # # you configure your source control system to ignore this file.
72
- # config.example_status_persistence_file_path = "spec/examples.txt"
73
- #
74
- # # Limits the available syntax to the non-monkey patched syntax that is
75
- # # recommended. For more details, see:
76
- # # - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
77
- # # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
78
- # # - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
79
- # config.disable_monkey_patching!
80
- #
81
- # # This setting enables warnings. It's recommended, but in some cases may
82
- # # be too noisy due to issues in dependencies.
83
- # config.warnings = true
84
- #
85
- # # Many RSpec users commonly either run the entire suite or an individual
86
- # # file, and it's useful to allow more verbose output when running an
87
- # # individual spec file.
88
- # if config.files_to_run.one?
89
- # # Use the documentation formatter for detailed output,
90
- # # unless a formatter has already been configured
91
- # # (e.g. via a command-line flag).
92
- # config.default_formatter = "doc"
93
- # end
94
- #
95
- # # Print the 10 slowest examples and example groups at the
96
- # # end of the spec run, to help surface which specs are running
97
- # # particularly slow.
98
- # config.profile_examples = 10
99
- #
100
- # # Run specs in random order to surface order dependencies. If you find an
101
- # # order dependency and want to debug it, you can fix the order by providing
102
- # # the seed, which is printed after each run.
103
- # # --seed 1234
104
- # config.order = :random
105
- #
106
- # # Seed global randomization in this process using the `--seed` CLI option.
107
- # # Setting this allows you to use `--seed` to deterministically reproduce
108
- # # test failures related to randomization by passing the same `--seed` value
109
- # # as the one that triggered the failure.
110
- # Kernel.srand config.seed
111
- end
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.configure do |config|
4
- config.include FactoryGirl::Syntax::Methods
5
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'metal_archives'
4
-
5
- MetalArchives.configure do |c|
6
- ## Application identity (required)
7
- c.app_name = 'MetalArchivesGemTestSuite'
8
- c.app_version = MetalArchives::VERSION
9
- c.app_contact = 'user@example.com'
10
-
11
- if ENV.has_key? 'TRAVIS'
12
- ## Request throttling (optional, overrides defaults)
13
- c.request_rate = 1
14
- c.request_timeout = 3
15
- end
16
-
17
- ## Connect additional Faraday middleware
18
- # c.middleware = [MyMiddleware, MyOtherMiddleware]
19
-
20
- ## Custom cache size per object class (optional, overrides defaults)
21
- # c.cache_size = 100
22
-
23
- ## Metal Archives endpoint (optional, overrides default)
24
- c.endpoint = ENV['MA_ENDPOINT'] if ENV['MA_ENDPOINT']
25
-
26
- if ENV['MA_ENDPOINT']
27
- puts "Using '#{ENV['MA_ENDPOINT']}' as MA endpoint"
28
- end
29
-
30
- ## Custom logger (optional)
31
- c.logger = Logger.new STDOUT
32
- c.logger.level = Logger::INFO
33
- end
@@ -1,72 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- RSpec.describe MetalArchives::Collection do
4
- it 'iterates' do
5
- l = lambda do
6
- @i ||= 0
7
-
8
- next [] if @i >= 100
9
- items = (@i .. (@i + 9)).to_a
10
- @i += 10
11
-
12
- items
13
- end
14
-
15
- c = MetalArchives::Collection.new l
16
-
17
- i = 0
18
- c.each do |item|
19
- expect(item).to eq i
20
- i += 1
21
- end
22
- end
23
-
24
- it 'returns' do
25
- l = lambda do
26
- @i ||= 0
27
-
28
- raise StandardError if @i >= 100
29
- items = (@i .. (@i + 9)).to_a
30
- @i += 10
31
-
32
- items
33
- end
34
-
35
- c = MetalArchives::Collection.new l
36
-
37
- i = 0
38
- c.each do |item|
39
- break if i == 99
40
- expect(item).to eq i
41
- i += 1
42
- end
43
-
44
- expect(i).to eq 99
45
- end
46
-
47
- describe 'empty?' do
48
- it 'is not empty' do
49
- l = lambda do
50
- @i ||= 0
51
-
52
- next [] if @i >= 100
53
- items = (@i .. (@i + 9)).to_a
54
- @i += 10
55
-
56
- items
57
- end
58
-
59
- c = MetalArchives::Collection.new l
60
-
61
- i = 0
62
-
63
- expect(c).not_to be_empty
64
- end
65
-
66
- it 'is empty' do
67
- c = MetalArchives::Collection.new -> { [] }
68
-
69
- expect(c).to be_empty
70
- end
71
- end
72
- end