bestchange-api 0.7 → 1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a4519573ffcd91610bf68a30544ebd17c00506ab8c052b5412b74ff348f07d8a
4
- data.tar.gz: c6e1e36c2ed0d7c35a374e00576c8c5de2f433e86edb986a0ceaf5e17a04e167
3
+ metadata.gz: 5dbecec983d7bc4299795c4ef489c5c63c6e90c33ef70144c8521bd2420fd067
4
+ data.tar.gz: 2e2196a4c4c458d42ec13dd530e423db8b0a9016636be8a1b074a5bfc771a395
5
5
  SHA512:
6
- metadata.gz: 8677e25eb2333d11e437e0b06eb64bcc122994b12fba0b81693e10dee37a6f31ce71d47a3f124929dafd865d72280db7e37df2c3109c7f0c4d2231c7b7d89c84
7
- data.tar.gz: 5459ab729ad2777e2981b8ba1b55fd37a88a8720d85ddbf18167dcb2587c095b0c5ba6e85f1a2583cad53446545ad569e77fcbc53491f71134cc53d867285e02
6
+ metadata.gz: 61a22cb80ad3c8f6abec0da2dcca59f3a5829b0be7211b14e45e432196d6fc1c581b80420351d9dad1b2cff154a1755a67a3b92355be4d182f63096a6cd58bda
7
+ data.tar.gz: b837ec968c2959340e7363f7ea3c6f40f1c47e2b991f729df190fe67dc2d0d27fa6394b1f2933581a1055f810c7b1a81f00afbf6bd1b9d0587faff2436686e8a
data/.rubocop.yml CHANGED
@@ -1,3 +1,5 @@
1
+ AllCops:
2
+ TargetRubyVersion: 3.1.3
1
3
  Style/Documentation:
2
4
  Enabled: false
3
5
  Metrics/MethodLength:
data/CHANGELOG.md CHANGED
@@ -1,7 +1,13 @@
1
1
  # Change log
2
2
 
3
+ ## [1.1]
4
+ Fix tempfile location
5
+
6
+ ## [1.0]
7
+ Add new Api interface, introduce Zip objects
8
+
3
9
  ## [0.7]
4
- Small improvements
10
+ Minor improvements
5
11
 
6
12
  ## [0.6]
7
13
  Pass zip entry via before_extract block
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bestchange-api (0.7)
4
+ bestchange-api (1.0)
5
5
  rubyzip (= 2.3.2)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -1,3 +1,4 @@
1
+
1
2
  # bestchange-api
2
3
 
3
4
  bestchange-api is a simple library for getting data from Bestchange aggregator
@@ -21,31 +22,61 @@ Or install it yourself as:
21
22
  ## Usage
22
23
  [Bestchange api description](https://github.com/karpinovsky/bestchange-api/blob/master/API_DOC.txt)
23
24
 
24
- Add your own configuration or use the default one
25
+ ### info.zip
25
26
 
26
27
  ```ruby
27
28
  require 'bestchange'
28
29
 
29
- Bestchange.configure do |config|
30
- config.dir = "path/to/your/custom/folder" # default is Dir.pwd
31
- config.timeout = 20 # Timeout for getting & parsing data, default is 40
32
- end
30
+ api_client = Bestchange::Api.new
31
+ response = api_client.request # this will call api.bestchange.ru/info.zip by default
32
+ archive = Bestchange::ZipBuilder.new(response.body).call
33
+ tempfile = Bestchange::ZipExtractor.new(archive).call('bm_rates.dat')
33
34
  ```
34
35
 
35
- Fetch data
36
+ **NOTE**: Do not forget to close and unlink files at the end
36
37
  ```ruby
37
- Bestchange::Api.get_files(['bm_rates.dat']) # => [File]
38
+ archive.close
39
+ tempfile.close
38
40
  ```
39
- ### &before_extract
40
- You can also pass a block that will be called before `Zip::Entry#extract`. It might be helpful if you need to remove existed files or change files destination for example
41
+
42
+ ### Using blocks
43
+ The `Bestchange::ZipBuilder` and `Bestchange::ZipExtractor` classes support using blocks to ensure that tempfiles are closed automatically. This is useful when you want to avoid manual file management and prevent possible leaks
41
44
  ```ruby
42
- before_extract = ->(_zip_entry, pathname) do
43
- pathname.delete if pathname.exist?
45
+ response = Bestchange::Api.new.request
46
+
47
+ Bestchange::ZipBuilder.new(response.body).call do |archive|
48
+ # Work with archive here
49
+ # archive will be closed automatically when the block finishes
50
+ Bestchange::ZipExtractor.new(archive).call('bm_rates.dat') do |bm_rates|
51
+ # Work with bm_rates here
52
+ # bm_rates will be closed automatically when the block finishes
53
+ end
44
54
  end
55
+ ```
56
+
57
+ ### Custom connection
58
+ You can pass your own http connection object while initializing an api client. This can be useful if you want to set custom timeouts, for example
59
+ ```ruby
60
+ require 'bestchange'
45
61
 
46
- Bestchange::Api.get_files(['bm_rates.dat'], &before_extract)
62
+ uri = URI(Bestchange::Api::BASE_URI)
63
+ conn = Net::HTTP.new(uri.host, uri.port)
64
+ conn.open_timeout = 5
65
+ conn.read_timeout = 10
66
+ api_client = Bestchange::Api.new(conn)
47
67
  ```
48
68
 
69
+ ### Custom request
70
+ You can provide your own http request object to the `#request` method
71
+ ```ruby
72
+ require 'bestchange'
73
+
74
+ request = Net::HTTP::Head.new(URI(Bestchange::Api::BASE_URI))
75
+ response = api_client.request(request)
76
+ created_at = response['Date']
77
+ ```
78
+
79
+
49
80
  ## License
50
81
 
51
82
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -7,49 +7,27 @@ require 'timeout'
7
7
  require 'zip'
8
8
 
9
9
  module Bestchange
10
- module Api
11
- extend self
10
+ class Api
11
+ BASE_URI = 'http://api.bestchange.ru/info.zip'
12
12
 
13
- def get_files(filenames, &before_extract)
14
- Timeout.timeout(Bestchange.configuration.timeout) do
15
- fetch_files(filenames, &before_extract)
16
- end
13
+ def initialize(conn = default_conn)
14
+ @conn = conn
17
15
  end
18
16
 
19
- private
17
+ attr_reader :conn
20
18
 
21
- def fetch_files(filenames, &before_extract)
22
- response = make_request
23
- archive = make_archive(response)
24
- extract_files(archive, filenames, &before_extract)
25
- ensure
26
- archive.close if defined?(archive)
19
+ def request(request = default_request)
20
+ conn.request(request)
27
21
  end
28
22
 
29
- def make_request
30
- Net::HTTP.get(URI(BASE_URI))
31
- end
23
+ private
32
24
 
33
- def make_archive(response)
34
- archive = Tempfile.new(ARCHIVE_DATA_FILENAME, encoding: ARCHIVE_DATA_ENCODING)
35
- archive.write(response)
36
- archive
25
+ def default_conn
26
+ Net::HTTP.new(URI(BASE_URI).host, URI(BASE_URI).port)
37
27
  end
38
28
 
39
- def extract_files(archive, filenames, &before_extract)
40
- Zip::File.open(archive) do |zip_file|
41
- filenames.map do |filename|
42
- entry = zip_file.find_entry(filename)
43
-
44
- pathname = Pathname.new(Bestchange.configuration.dir).join(filename)
45
-
46
- before_extract&.call(entry, pathname)
47
-
48
- zip_file.extract(entry, pathname)
49
-
50
- pathname.open
51
- end
52
- end
29
+ def default_request
30
+ Net::HTTP::Get.new(URI(BASE_URI))
53
31
  end
54
32
  end
55
33
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Bestchange
4
- VERSION = '0.7'
4
+ VERSION = '1.1'
5
5
  end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Bestchange
4
+ class ZipBuilder
5
+ ARCHIVE_DATA_ENCODING = 'ASCII-8BIT'
6
+
7
+ def initialize(response_body)
8
+ @response_body = response_body
9
+ end
10
+
11
+ def call
12
+ zip_file = Tempfile.new('', encoding: ARCHIVE_DATA_ENCODING)
13
+ zip_file.write(@response_body)
14
+ zip_file.rewind
15
+
16
+ if block_given?
17
+ begin
18
+ yield zip_file
19
+ ensure
20
+ zip_file.close
21
+ end
22
+ else
23
+ zip_file
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'zip'
4
+
5
+ module Bestchange
6
+ class ZipExtractor
7
+ def initialize(zip_file)
8
+ @zip_file = zip_file
9
+ end
10
+
11
+ def call(filename)
12
+ tempfile = Tempfile.new(filename)
13
+
14
+ Zip::File.open(@zip_file) do |zip_file|
15
+ entry = zip_file.find_entry(filename)
16
+
17
+ entry.extract(tempfile) { true }
18
+ end
19
+
20
+ tempfile.rewind
21
+
22
+ if block_given?
23
+ begin
24
+ yield tempfile
25
+ ensure
26
+ tempfile.close
27
+ end
28
+ else
29
+ tempfile
30
+ end
31
+ end
32
+ end
33
+ end
data/lib/bestchange.rb CHANGED
@@ -1,24 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'bestchange/api'
4
- require_relative 'bestchange/configuration'
4
+ require_relative 'bestchange/zip_builder'
5
+ require_relative 'bestchange/zip_extractor'
5
6
 
6
7
  module Bestchange
7
- ARCHIVE_DATA_FILENAME = 'info.zip'
8
- ARCHIVE_DATA_ENCODING = 'ASCII-8BIT'
9
-
10
- BASE_URI = "http://api.bestchange.ru/#{ARCHIVE_DATA_FILENAME}".freeze
11
-
12
- DIRECTORY = Dir.pwd
13
- TIMEOUT = 40
14
-
15
- def self.configuration
16
- @configuration ||= Configuration.new
17
- end
18
-
19
- def self.configure
20
- return configuration unless block_given?
21
-
22
- yield(configuration)
23
- end
24
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bestchange-api
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.7'
4
+ version: '1.1'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kirill Karpinovsky
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-17 00:00:00.000000000 Z
11
+ date: 2023-04-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rubyzip
@@ -89,8 +89,9 @@ files:
89
89
  - bin/setup
90
90
  - lib/bestchange.rb
91
91
  - lib/bestchange/api.rb
92
- - lib/bestchange/configuration.rb
93
92
  - lib/bestchange/version.rb
93
+ - lib/bestchange/zip_builder.rb
94
+ - lib/bestchange/zip_extractor.rb
94
95
  homepage: https://github.com/karpinovsky/bestchange-api
95
96
  licenses:
96
97
  - MIT
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Bestchange
4
- class Configuration
5
- def dir
6
- @dir || Bestchange::DIRECTORY
7
- end
8
-
9
- def timeout
10
- @timeout || Bestchange::TIMEOUT
11
- end
12
-
13
- attr_writer :dir, :timeout
14
- end
15
- end