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.
- checksums.yaml +4 -4
- data/.gitignore +59 -7
- data/.rspec +1 -0
- data/.rubocop.yml +14 -0
- data/.travis.yml +11 -0
- data/Gemfile +2 -0
- data/{LICENSE → LICENSE.md} +0 -0
- data/README.md +77 -9
- data/Rakefile +5 -3
- data/lib/metal_archives.rb +8 -0
- data/lib/metal_archives/configuration.rb +28 -7
- data/lib/metal_archives/error.rb +37 -30
- data/lib/metal_archives/http_client.rb +21 -42
- data/lib/metal_archives/middleware/headers.rb +38 -0
- data/lib/metal_archives/middleware/rewrite_endpoint.rb +38 -0
- data/lib/metal_archives/models/artist.rb +51 -65
- data/lib/metal_archives/models/band.rb +41 -39
- data/lib/metal_archives/models/base_model.rb +88 -59
- data/lib/metal_archives/models/label.rb +7 -6
- data/lib/metal_archives/parsers/artist.rb +110 -99
- data/lib/metal_archives/parsers/band.rb +168 -156
- data/lib/metal_archives/parsers/label.rb +54 -52
- data/lib/metal_archives/parsers/parser.rb +73 -71
- data/lib/metal_archives/utils/collection.rb +7 -1
- data/lib/metal_archives/utils/lru_cache.rb +11 -4
- data/lib/metal_archives/utils/nil_date.rb +54 -0
- data/lib/metal_archives/utils/range.rb +16 -8
- data/lib/metal_archives/version.rb +3 -1
- data/metal_archives.gemspec +21 -11
- data/spec/configuration_spec.rb +101 -0
- data/spec/factories/artist_factory.rb +37 -0
- data/spec/factories/band_factory.rb +60 -0
- data/spec/factories/nil_date_factory.rb +9 -0
- data/spec/factories/range_factory.rb +8 -0
- data/spec/models/artist_spec.rb +142 -0
- data/spec/models/band_spec.rb +179 -0
- data/spec/models/base_model_spec.rb +217 -0
- data/spec/parser_spec.rb +19 -0
- data/spec/spec_helper.rb +111 -0
- data/spec/support/factory_girl.rb +5 -0
- data/spec/support/metal_archives.rb +26 -0
- data/spec/utils/collection_spec.rb +72 -0
- data/spec/utils/lru_cache_spec.rb +53 -0
- data/spec/utils/nil_date_spec.rb +98 -0
- data/spec/utils/range_spec.rb +62 -0
- metadata +142 -57
- data/test/base_model_test.rb +0 -111
- data/test/configuration_test.rb +0 -57
- data/test/parser_test.rb +0 -37
- data/test/property/artist_property_test.rb +0 -43
- data/test/property/band_property_test.rb +0 -94
- data/test/query/artist_query_test.rb +0 -109
- data/test/query/band_query_test.rb +0 -152
- data/test/test_helper.rb +0 -25
- data/test/utils/collection_test.rb +0 -51
- data/test/utils/lru_cache_test.rb +0 -22
- data/test/utils/range_test.rb +0 -42
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9c1527cbe8ea9df768ea3112b958fbba43f29dd0
|
4
|
+
data.tar.gz: 82971bd30252efb8e77badb9dfe10c71fb86a585
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64fb61f7acd105d6aa93f005cccdc1d246de4ac7b9a2fc4f944c7a3ff729698eaedd42faee4228f25549f33beedef1f5d34d3834953abe59054f16161b4dcea0
|
7
|
+
data.tar.gz: e57bc2994341940aa33f283ae028ca3cb7a51f1e634eee3041c66d3d75ff0d765ee93e87cf30d394a6cc9ade61d8458bdab08fb5e4bc5dd5d45ec146fe43d38b
|
data/.gitignore
CHANGED
@@ -1,12 +1,64 @@
|
|
1
|
-
|
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
|
-
|
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
data/.travis.yml
ADDED
data/Gemfile
CHANGED
data/{LICENSE → LICENSE.md}
RENAMED
File without changes
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Metal Archives Web Service Wrapper
|
1
|
+
# Metal Archives Web Service Wrapper [](https://travis-ci.org/floriandejonckheere/metal_archives) [](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
|
-
|
24
|
-
c.app_name =
|
25
|
-
c.app_version =
|
26
|
-
c.app_contact =
|
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
|
-
|
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
|
-
|
35
|
+
## Custom cache size per object class (optional, overrides defaults)
|
33
36
|
c.cache_size = 100
|
34
|
-
|
35
|
-
|
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 <<
|
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 =
|
13
|
-
rdoc.rdoc_files.include(
|
14
|
+
rdoc.main = 'README.md'
|
15
|
+
rdoc.rdoc_files.include('README.md', 'lib/**/*.rb')
|
14
16
|
end
|
data/lib/metal_archives.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
27
|
+
@config = MetalArchives::Configuration.new
|
28
|
+
yield @config
|
22
29
|
|
23
|
-
|
24
|
-
|
25
|
-
raise MetalArchives::Errors::InvalidConfigurationError, '
|
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
|
-
@
|
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
|
data/lib/metal_archives/error.rb
CHANGED
@@ -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
|
-
#
|
5
|
+
# MetalArchives gem specific errors
|
8
6
|
#
|
9
|
-
|
7
|
+
module Errors
|
8
|
+
##
|
9
|
+
# Generic error
|
10
|
+
#
|
11
|
+
class Error < StandardError; end
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
##
|
14
|
+
# No or invalid ID
|
15
|
+
#
|
16
|
+
class InvalidIDError < Error; end
|
15
17
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
##
|
19
|
+
# No or invalid configuration
|
20
|
+
#
|
21
|
+
class InvalidConfigurationError < Error; end
|
20
22
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
23
|
+
##
|
24
|
+
# Error parsing value
|
25
|
+
#
|
26
|
+
class ParserError < Error; end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
##
|
29
|
+
# Functionality not implemented (yet)
|
30
|
+
class NotImplementedError < Error; end
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
##
|
33
|
+
# Error in backend response
|
34
|
+
#
|
35
|
+
class APIError < Error; end
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
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
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
48
|
+
f.use :throttler,
|
49
|
+
:rate => MetalArchives.config.request_rate,
|
50
|
+
:wait => MetalArchives.config.request_timeout,
|
51
|
+
:logger => MetalArchives.config.logger
|
74
52
|
|
75
|
-
|
76
|
-
|
53
|
+
f.adapter Faraday.default_adapter
|
54
|
+
end
|
77
55
|
end
|
56
|
+
end
|
78
57
|
end
|
79
58
|
end
|