metal_archives 0.8.0 → 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.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +59 -7
  3. data/.rspec +1 -0
  4. data/.rubocop.yml +14 -0
  5. data/.travis.yml +11 -0
  6. data/Gemfile +2 -0
  7. data/{LICENSE → LICENSE.md} +0 -0
  8. data/README.md +77 -9
  9. data/Rakefile +5 -3
  10. data/lib/metal_archives.rb +8 -0
  11. data/lib/metal_archives/configuration.rb +28 -7
  12. data/lib/metal_archives/error.rb +37 -30
  13. data/lib/metal_archives/http_client.rb +21 -42
  14. data/lib/metal_archives/middleware/headers.rb +38 -0
  15. data/lib/metal_archives/middleware/rewrite_endpoint.rb +38 -0
  16. data/lib/metal_archives/models/artist.rb +51 -65
  17. data/lib/metal_archives/models/band.rb +41 -39
  18. data/lib/metal_archives/models/base_model.rb +88 -59
  19. data/lib/metal_archives/models/label.rb +7 -6
  20. data/lib/metal_archives/parsers/artist.rb +110 -99
  21. data/lib/metal_archives/parsers/band.rb +168 -156
  22. data/lib/metal_archives/parsers/label.rb +54 -52
  23. data/lib/metal_archives/parsers/parser.rb +73 -71
  24. data/lib/metal_archives/utils/collection.rb +7 -1
  25. data/lib/metal_archives/utils/lru_cache.rb +11 -4
  26. data/lib/metal_archives/utils/nil_date.rb +54 -0
  27. data/lib/metal_archives/utils/range.rb +16 -8
  28. data/lib/metal_archives/version.rb +3 -1
  29. data/metal_archives.gemspec +21 -11
  30. data/spec/configuration_spec.rb +101 -0
  31. data/spec/factories/artist_factory.rb +37 -0
  32. data/spec/factories/band_factory.rb +60 -0
  33. data/spec/factories/nil_date_factory.rb +9 -0
  34. data/spec/factories/range_factory.rb +8 -0
  35. data/spec/models/artist_spec.rb +142 -0
  36. data/spec/models/band_spec.rb +179 -0
  37. data/spec/models/base_model_spec.rb +217 -0
  38. data/spec/parser_spec.rb +19 -0
  39. data/spec/spec_helper.rb +111 -0
  40. data/spec/support/factory_girl.rb +5 -0
  41. data/spec/support/metal_archives.rb +26 -0
  42. data/spec/utils/collection_spec.rb +72 -0
  43. data/spec/utils/lru_cache_spec.rb +53 -0
  44. data/spec/utils/nil_date_spec.rb +98 -0
  45. data/spec/utils/range_spec.rb +62 -0
  46. metadata +142 -57
  47. data/test/base_model_test.rb +0 -111
  48. data/test/configuration_test.rb +0 -57
  49. data/test/parser_test.rb +0 -37
  50. data/test/property/artist_property_test.rb +0 -43
  51. data/test/property/band_property_test.rb +0 -94
  52. data/test/query/artist_query_test.rb +0 -109
  53. data/test/query/band_query_test.rb +0 -152
  54. data/test/test_helper.rb +0 -25
  55. data/test/utils/collection_test.rb +0 -51
  56. data/test/utils/lru_cache_test.rb +0 -22
  57. data/test/utils/range_test.rb +0 -42
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e19af43a38aa2f5242fee7553c145f673811af35
4
- data.tar.gz: 05f2f5ad5b31fa0b8fa095f9866f6b4d148ce4c3
3
+ metadata.gz: 9c1527cbe8ea9df768ea3112b958fbba43f29dd0
4
+ data.tar.gz: 82971bd30252efb8e77badb9dfe10c71fb86a585
5
5
  SHA512:
6
- metadata.gz: 73946de65fb4d67fc98591a897bd9045db3c483e39084656ec4b4e39fa49b247ccd892aeca6f7565969c3522c8772ac0ae6d577ed1d6c6a7d7797fd960dabf89
7
- data.tar.gz: 1f2bba663937069139bbd0d2a0093e9e95b7e547f1a1b7a4e0f3e4e3a40790a9f4780cecaf5804677c02fc1df44f2c3c74b938930a97c6c6c5cd29ebcd1bcc71
6
+ metadata.gz: 64fb61f7acd105d6aa93f005cccdc1d246de4ac7b9a2fc4f944c7a3ff729698eaedd42faee4228f25549f33beedef1f5d34d3834953abe59054f16161b4dcea0
7
+ data.tar.gz: e57bc2994341940aa33f283ae028ca3cb7a51f1e634eee3041c66d3d75ff0d765ee93e87cf30d394a6cc9ade61d8458bdab08fb5e4bc5dd5d45ec146fe43d38b
data/.gitignore CHANGED
@@ -1,12 +1,64 @@
1
- # Ruby version
1
+ Gemfile.lock
2
+ .idea
3
+
4
+ *.gem
5
+ *.rbc
6
+ /.config
7
+ /coverage/
8
+ /InstalledFiles
9
+ /pkg/
10
+ /spec/reports/
11
+ /spec/examples.txt
12
+ /test/tmp/
13
+ /test/version_tmp/
14
+ /tmp/
15
+
16
+ # Used by dotenv library to load environment variables.
17
+ # .env
18
+
19
+ ## Specific to RubyMotion:
20
+ .dat*
21
+ .repl_history
22
+ build/
23
+ *.bridgesupport
24
+ build-iPhoneOS/
25
+ build-iPhoneSimulator/
26
+
27
+ ## Specific to RubyMotion (use of CocoaPods):
28
+ #
29
+ # We recommend against adding the Pods directory to your .gitignore. However
30
+ # you should judge for yourself, the pros and cons are mentioned at:
31
+ # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
32
+ #
33
+ # vendor/Pods/
34
+
35
+ ## Documentation cache and generated files:
36
+ /.yardoc/
37
+ /_yardoc/
38
+ /doc/
39
+ /rdoc/
40
+
41
+ ## Environment normalization:
42
+ /.bundle/
43
+ /vendor/bundle
44
+ /lib/bundler/man/
45
+
46
+ # for a library or gem, you might want to ignore these files since the code is
47
+ # intended to run in multiple environments; otherwise, check them in:
48
+ # Gemfile.lock
49
+ # .ruby-version
50
+ # .ruby-gemset
51
+
52
+ # unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
53
+ .rvmrc
54
+
55
+ # IDE files
56
+ .idea
57
+
58
+ ## Gem files
2
59
  .ruby-version
3
60
  .ruby-gemset
4
61
 
5
- # Temp files
62
+ ## Temp files
6
63
  .byebug_history
7
-
8
- # RDoc
9
64
  html/
10
-
11
- Gemfile.lock
12
- .idea
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,14 @@
1
+ Metrics/LineLength:
2
+ Max: 120
3
+
4
+ Metrics/MethodLength:
5
+ Enabled: false
6
+
7
+ Metrics/BlockLength:
8
+ Enabled: false
9
+
10
+ Style/HashSyntax:
11
+ EnforcedStyle: hash_rockets
12
+
13
+ Style/NestedParenthesizedCalls:
14
+ Enabled: false
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.4.1
4
+ cache:
5
+ bundler: true
6
+ env:
7
+ - RAILS_ENV=test CI=true TRAVIS=true
8
+ install:
9
+ - bundle install
10
+ script:
11
+ - bundle exec rspec
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gemspec
File without changes
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # Metal Archives Web Service Wrapper
1
+ # Metal Archives Web Service Wrapper [![Travis](https://travis-ci.org/floriandejonckheere/metal_archives.svg?branch=master)](https://travis-ci.org/floriandejonckheere/metal_archives) [![Coverage Status](https://coveralls.io/repos/github/floriandejonckheere/metal_archives/badge.svg)](https://coveralls.io/github/floriandejonckheere/metal_archives)
2
2
 
3
3
  ## Installation
4
4
 
@@ -20,20 +20,29 @@ $ bundle install
20
20
 
21
21
  ```ruby
22
22
  MetalArchives.configure do |c|
23
- # Application identity (required)
24
- c.app_name = "My App"
25
- c.app_version = "1.0"
26
- c.app_contact = "support@mymusicapp.com"
23
+ ## Application identity (required)
24
+ c.app_name = 'My App'
25
+ c.app_version = '1.0'
26
+ c.app_contact = 'support@mymusicapp.com'
27
27
 
28
- # Request throttling (optional, overrides defaults)
28
+ ## Request throttling (optional, overrides defaults)
29
29
  c.request_rate = 1
30
30
  c.request_timeout = 3
31
+
32
+ ## Connect additional Faraday middleware
33
+ # c.middleware = [MyMiddleware, MyOtherMiddleware]
31
34
 
32
- # Custom cache size per object class (optional, overrides defaults)
35
+ ## Custom cache size per object class (optional, overrides defaults)
33
36
  c.cache_size = 100
34
-
35
- # Custom logger (optional)
37
+
38
+ ## Metal Archives endpoint (optional, overrides default)
39
+ # c.endpoint = 'http://www.metal-archives.com/'
40
+
41
+ ## Custom logger (optional)
36
42
  c.logger = Logger.new File.new('metal_archives.log')
43
+
44
+ ## Verbose output
45
+ # c.debug = false
37
46
  end
38
47
  ```
39
48
 
@@ -74,6 +83,65 @@ By default when an model (Artist, Band, ...) is created, no data is fetched. Thi
74
83
 
75
84
  Models can be forced to load all data by calling the `:load!` method.
76
85
 
86
+ ## Cache
87
+
88
+ In order not to stress the Metal Archives server, you can quickly set up a local proxy that caches the requests. For NGINX, adjust the following configuration:
89
+
90
+ ```
91
+ # Set cache dir
92
+ proxy_cache_path /var/cache/nginx/metal_archives levels=1:2 keys_zone=metal_archives:10m;
93
+
94
+ # Set cache key to include identifying components
95
+ proxy_cache_key $scheme$proxy_host$request_uri;
96
+
97
+ # Add cache status to log
98
+ log_format cache '$remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" cs=$upstream_cache_status';
99
+
100
+ server {
101
+ server_name metal-archives.myhost.com;
102
+ listen 443 ssl;
103
+ listen [::]:443 ssl;
104
+
105
+ ssl_certificate /path/to/ssl_certificate.crt;
106
+ ssl_certificate_key /path/to/ssl_certificate_key.key;
107
+
108
+ access_log /var/log/nginx/metal_archives_access.log;
109
+ error_log /var/log/nginx/metal_archives_error.log;
110
+
111
+ # Limit HTTP requests
112
+ limit_req_zone $binary_remote_addr zone=ma_limit_req:10m rate=2r/s;
113
+
114
+ location / {
115
+ proxy_redirect off;
116
+ proxy_set_header Host www.metal-archives.com;
117
+ proxy_set_header X-Forwarded-Host $host;
118
+ proxy_set_header X-Forwarded-Server $host;
119
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
120
+ proxy_set_header X-Real-IP $remote_addr;
121
+
122
+ proxy_pass https://www.metal-archives.com/;
123
+
124
+ limit_req zone=ma_limit_req burst=5;
125
+
126
+ proxy_ignore_headers X-Accel-Expires;
127
+ proxy_ignore_headers Expires;
128
+ proxy_ignore_headers Cache-Control;
129
+ proxy_ignore_headers Set-Cookie;
130
+
131
+ proxy_hide_header Set-Cookie;
132
+ proxy_hide_header Pragma;
133
+
134
+ # Cache valid responses for 30 days
135
+ proxy_cache metal_archives;
136
+ proxy_cache_valid 200 301 302 30d;
137
+ proxy_cache_valid 404 7d;
138
+ expires 30d;
139
+ }
140
+
141
+ add_header X-Cache-Status $upstream_cache_status;
142
+ }
143
+ ```
144
+
77
145
  ## Testing
78
146
  ```
79
147
  $ bundle exec rake test
data/Rakefile CHANGED
@@ -1,14 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake'
2
4
  require 'rake/testtask'
3
5
 
4
6
  Rake::TestTask.new do |t|
5
- t.libs << "test"
7
+ t.libs << 'test'
6
8
  t.test_files = FileList['test/*/*_test.rb']
7
9
  t.verbose = true
8
10
  end
9
11
 
10
12
  require 'rdoc/task'
11
13
  RDoc::Task.new do |rdoc|
12
- rdoc.main = "README.md"
13
- rdoc.rdoc_files.include("README.md", "lib/**/*.rb")
14
+ rdoc.main = 'README.md'
15
+ rdoc.rdoc_files.include('README.md', 'lib/**/*.rb')
14
16
  end
@@ -1,3 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'openssl'
4
+
5
+ require 'metal_archives/middleware/headers'
6
+ require 'metal_archives/middleware/rewrite_endpoint'
7
+
1
8
  require 'metal_archives/version'
2
9
  require 'metal_archives/configuration'
3
10
  require 'metal_archives/error'
@@ -5,6 +12,7 @@ require 'metal_archives/error'
5
12
  require 'metal_archives/utils/range'
6
13
  require 'metal_archives/utils/collection'
7
14
  require 'metal_archives/utils/lru_cache'
15
+ require 'metal_archives/utils/nil_date'
8
16
 
9
17
  require 'metal_archives/models/base_model'
10
18
  require 'metal_archives/models/label'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MetalArchives
2
4
  class << self
3
5
  ##
@@ -5,7 +7,11 @@ module MetalArchives
5
7
  #
6
8
  # Instance of rdoc-ref:MetalArchives::Configuration
7
9
  #
8
- attr_accessor :config
10
+ def config
11
+ raise MetalArchives::Errors::InvalidConfigurationError, 'Gem has not been configured' unless @config
12
+
13
+ @config
14
+ end
9
15
 
10
16
  ##
11
17
  # Configure API options.
@@ -18,11 +24,14 @@ module MetalArchives
18
24
  #
19
25
  def configure
20
26
  raise MetalArchives::Errors::InvalidConfigurationError, 'No configuration block given' unless block_given?
21
- yield MetalArchives.config ||= MetalArchives::Configuration.new
27
+ @config = MetalArchives::Configuration.new
28
+ yield @config
22
29
 
23
- raise MetalArchives::Errors::InvalidConfigurationError, 'app_name has not been configured' unless MetalArchives.config.app_name and not MetalArchives.config.app_name.empty?
24
- raise MetalArchives::Errors::InvalidConfigurationError, 'app_version has not been configured' unless MetalArchives.config.app_version and not MetalArchives.config.app_version.empty?
25
- raise MetalArchives::Errors::InvalidConfigurationError, 'app_contact has not been configured' unless MetalArchives.config.app_contact and not MetalArchives.config.app_contact.empty?
30
+ @config.logger.level = @config.debug ? Logger::DEBUG : Logger::WARN
31
+
32
+ raise MetalArchives::Errors::InvalidConfigurationError, 'app_name has not been configured' unless MetalArchives.config.app_name && !MetalArchives.config.app_name.empty?
33
+ raise MetalArchives::Errors::InvalidConfigurationError, 'app_version has not been configured' unless MetalArchives.config.app_version && !MetalArchives.config.app_version.empty?
34
+ raise MetalArchives::Errors::InvalidConfigurationError, 'app_contact has not been configured' unless MetalArchives.config.app_contact && !MetalArchives.config.app_contact.empty?
26
35
  end
27
36
  end
28
37
 
@@ -46,9 +55,15 @@ module MetalArchives
46
55
  attr_accessor :app_contact
47
56
 
48
57
  ##
49
- # Metal Archives endpoint (defaults to http://www.metal-archives.com/)
58
+ # Override Metal Archives endpoint (defaults to http://www.metal-archives.com/)
50
59
  #
51
60
  attr_accessor :endpoint
61
+ attr_reader :default_endpoint
62
+
63
+ ##
64
+ # Additional Faraday middleware
65
+ #
66
+ attr_accessor :middleware
52
67
 
53
68
  ##
54
69
  # Request throttling rate (in seconds per request per path)
@@ -65,6 +80,11 @@ module MetalArchives
65
80
  #
66
81
  attr_accessor :logger
67
82
 
83
+ ##
84
+ # Verbose output
85
+ #
86
+ attr_accessor :debug
87
+
68
88
  ##
69
89
  # Cache size (per object class)
70
90
  #
@@ -74,10 +94,11 @@ module MetalArchives
74
94
  # Default configuration values
75
95
  #
76
96
  def initialize
77
- @endpoint = 'http://www.metal-archives.com/'
97
+ @default_endpoint = 'https://www.metal-archives.com/'
78
98
  @throttle_rate = 1
79
99
  @throttle_wait = 3
80
100
  @logger = Logger.new STDOUT
101
+ @debug = false
81
102
  @cache_size = 100
82
103
  end
83
104
  end
@@ -1,40 +1,47 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module MetalArchives
2
- ##
3
- # MetalArchives gem specific errors
4
- #
5
- module Errors
6
4
  ##
7
- # Generic error
5
+ # MetalArchives gem specific errors
8
6
  #
9
- class Error < StandardError; end
7
+ module Errors
8
+ ##
9
+ # Generic error
10
+ #
11
+ class Error < StandardError; end
10
12
 
11
- ##
12
- # No or invalid ID
13
- #
14
- class InvalidIDError < Error; end
13
+ ##
14
+ # No or invalid ID
15
+ #
16
+ class InvalidIDError < Error; end
15
17
 
16
- ##
17
- # No or invalid configuration
18
- #
19
- class InvalidConfigurationError < Error; end
18
+ ##
19
+ # No or invalid configuration
20
+ #
21
+ class InvalidConfigurationError < Error; end
20
22
 
21
- ##
22
- # Error parsing value
23
- #
24
- class ParserError < Error; end
23
+ ##
24
+ # Error parsing value
25
+ #
26
+ class ParserError < Error; end
25
27
 
26
- ##
27
- # Functionality not implemented (yet)
28
- class NotImplementedError < Error; end
28
+ ##
29
+ # Functionality not implemented (yet)
30
+ class NotImplementedError < Error; end
29
31
 
30
- ##
31
- # Error in backend response
32
- #
33
- class APIError < Error; end
32
+ ##
33
+ # Error in backend response
34
+ #
35
+ class APIError < Error; end
34
36
 
35
- ##
36
- # Error in method argument
37
- #
38
- class ArgumentError < Error; end
39
- end
37
+ ##
38
+ # Error in method argument
39
+ #
40
+ class ArgumentError < Error; end
41
+
42
+ ##
43
+ # Incorrect type
44
+ #
45
+ class TypeError < Error; end
46
+ end
40
47
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'faraday_throttler'
3
5
 
@@ -7,7 +9,6 @@ module MetalArchives
7
9
  #
8
10
  class HTTPClient # :nodoc:
9
11
  class << self
10
-
11
12
  ##
12
13
  # Retrieve a HTTP resource
13
14
  #
@@ -27,53 +28,31 @@ module MetalArchives
27
28
  end
28
29
 
29
30
  private
30
- ##
31
- # Retrieve a HTTP client
32
- #
33
- #
34
- def client
35
- raise Errors::InvalidConfigurationError, 'Not configured yet' unless MetalArchives.config
36
31
 
37
- @faraday ||= Faraday.new do |f|
38
- f.request :url_encoded # form-encode POST params
39
- f.response :logger, MetalArchives.config.logger
40
-
41
- f.use MetalArchives::Middleware
42
- f.use :throttler,
43
- :rate => MetalArchives.config.request_rate,
44
- :wait => MetalArchives.config.request_timeout,
45
- :logger => MetalArchives.config.logger
32
+ ##
33
+ # Retrieve a HTTP client
34
+ #
35
+ #
36
+ def client
37
+ raise Errors::InvalidConfigurationError, 'Not configured yet' unless MetalArchives.config
46
38
 
47
- f.adapter Faraday.default_adapter
48
- end
49
- end
50
- end
51
- end
39
+ @faraday ||= Faraday.new do |f|
40
+ f.request :url_encoded # form-encode POST params
41
+ f.response :logger, MetalArchives.config.logger
52
42
 
53
- ##
54
- # Faraday middleware
55
- #
56
- class Middleware < Faraday::Middleware # :nodoc:
57
- def call(env)
58
- env[:request_headers].merge!(
59
- 'User-Agent' => user_agent_string,
60
- 'Via' => via_string,
61
- 'Accept' => accept_string
62
- )
63
- @app.call(env)
64
- end
43
+ f.use MetalArchives::Middleware::Headers
44
+ f.use MetalArchives::Middleware::RewriteEndpoint
65
45
 
66
- private
67
- def user_agent_string
68
- "#{MetalArchives.config.app_name}/#{MetalArchives.config.app_version} ( #{MetalArchives.config.app_contact} )"
69
- end
46
+ MetalArchives.config.middleware.each { |m| f.use m } if MetalArchives.config.middleware
70
47
 
71
- def accept_string
72
- 'application/json'
73
- end
48
+ f.use :throttler,
49
+ :rate => MetalArchives.config.request_rate,
50
+ :wait => MetalArchives.config.request_timeout,
51
+ :logger => MetalArchives.config.logger
74
52
 
75
- def via_string
76
- "gem metal_archives/#{VERSION}"
53
+ f.adapter Faraday.default_adapter
54
+ end
77
55
  end
56
+ end
78
57
  end
79
58
  end