zipline 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9f78131919f81ca6a316cb1f1c7173515a230cee
4
- data.tar.gz: 5143037d6d038adf9af45b269f8653f4dd9c1d47
3
+ metadata.gz: 69a1498073cad22c14b800ca508220aadb0f1237
4
+ data.tar.gz: 1046ab42fb8678bcb2ad08ca4cd8b4c00f6bf8c7
5
5
  SHA512:
6
- metadata.gz: 641f00ccfa244d4a5d7e25cb99aaac1356069e9ed1bdf1ea52da7437f613ebf6cc0a31ba0c707777bf0772c899f24d556e657ee29a39a3672a8841ff5d7ef7d7
7
- data.tar.gz: bf7592dc54f890f4aadd6628d814048958308c8f20ea51ff3a34088312f497bc4b882b1b4a6fb8e8728dd03b130130cbb4c72617adc86484a738d9af810d22f6
6
+ metadata.gz: 296f7ba0ba6fa91e78a060b40edbda917ed4c839658faf639f50888d9089b9d992003a5e01348b0b3377b998a7b162bc4548c826569894f29ae6a4f0a632459b
7
+ data.tar.gz: 987a45caed0f8956172dff50e438198ddc8e36fe2f65c5a55bab67c5b24bc6df1aff7320f57bfe4c139d6f491963ca496f0e97fc292a4bdedee39ee677e0bd8b
@@ -1,4 +1,8 @@
1
1
  language: ruby
2
+ cache: bundler
2
3
  rvm:
4
+ - 2.3
3
5
  - 2.4
6
+ - 2.5
7
+ - 2.6
4
8
 
data/README.md CHANGED
@@ -1,4 +1,6 @@
1
1
  # Zipline
2
+ [![Build Status](https://travis-ci.org/fringd/zipline.svg?branch=master)](https://travis-ci.org/fringd/zipline)
3
+ [![Gem Version](https://badge.fury.io/rb/zipline.svg)](https://badge.fury.io/rb/zipline)
2
4
 
3
5
  A gem to stream dynamically generated zip files from a rails application. Unlike other solutions that generate zips for user download, zipline does not wait for the entire zip file to be created (or even for the entire input file in the cloud to be downloaded) before it begins sending the zip file to the user. It does this by never seeking backwards during zip creation, and streaming the zip file over http as it is constructed. The advantages of this are:
4
6
 
@@ -28,37 +30,42 @@ supported with [shrine](https://github.com/janko-m/shrine).
28
30
 
29
31
  You'll need to be using puma or some other server that supports streaming output.
30
32
 
31
- class MyController < ApplicationController
32
- # enable streaming responses
33
- include ActionController::Streaming
34
- # enable zipline
35
- include Zipline
36
-
37
- def index
38
- users = User.all
39
- # you can replace user.avatar with any stream or any object that
40
- # responds to :url
41
- files = users.map{ |user| [user.avatar, "#{user.username}.png"] }
42
- zipline( files, 'avatars.zip')
43
- end
44
- end
33
+ ```Ruby
34
+ class MyController < ApplicationController
35
+ # enable streaming responses
36
+ include ActionController::Streaming
37
+ # enable zipline
38
+ include Zipline
39
+
40
+ def index
41
+ users = User.all
42
+ # you can replace user.avatar with any stream or any object that
43
+ # responds to :url.
44
+ # :modification_time is an optional third argument you can use.
45
+ files = users.map{ |user| [user.avatar, "#{user.username}.png", modification_time: 1.day.ago] }
46
+ zipline(files, 'avatars.zip')
47
+ end
48
+ end
49
+ ```
45
50
 
46
51
  For directories, just give the files names like "directory/file".
47
52
 
48
53
  To stream files from a remote URL, use open-uri with a [lazy enumerator](http://ruby-doc.org/core-2.0.0/Enumerator/Lazy.html):
49
54
 
50
- require 'open-uri'
51
- avatars = [
52
- # remote_url zip_path
53
- [ 'http://www.example.com/user1.png', 'avatars/user1.png' ]
54
- [ 'http://www.example.com/user2.png', 'avatars/user2.png' ]
55
- [ 'http://www.example.com/user3.png', 'avatars/user3.png' ]
56
- ]
57
- file_mappings = avatars
58
- .lazy # Lazy allows us to begin sending the download immediately instead of waiting to download everything
59
- .map { |url, path| [open(url), path] }
60
- zipline(file_mappings, 'avatars.zip')
61
-
55
+ ```Ruby
56
+ require 'open-uri'
57
+ avatars = [
58
+ # remote_url zip_path
59
+ [ 'http://www.example.com/user1.png', 'avatars/user1.png', modification_time: Time.now.utc ]
60
+ [ 'http://www.example.com/user2.png', 'avatars/user2.png', modification_time: 1.day.ago ]
61
+ [ 'http://www.example.com/user3.png', 'avatars/user3.png' ]
62
+ ]
63
+ file_mappings = avatars
64
+ .lazy # Lazy allows us to begin sending the download immediately instead of waiting to download everything
65
+ .map { |url, path| [open(url), path] }
66
+ zipline(file_mappings, 'avatars.zip')
67
+ ```
68
+
62
69
  ## Contributing
63
70
 
64
71
  1. Fork it
@@ -6,9 +6,9 @@ require "zipline/zip_generator"
6
6
  # class MyController < ApplicationController
7
7
  # include Zipline
8
8
  # def index
9
- # users= User.all
10
- # files = users.map{ |user| [user.avatar, "#{user.username}.png"] }
11
- # zipline( files, 'avatars.zip')
9
+ # users = User.all
10
+ # files = users.map{ |user| [user.avatar, "#{user.username}.png", modification_time: 1.day.ago] }
11
+ # zipline(files, 'avatars.zip')
12
12
  # end
13
13
  # end
14
14
  module Zipline
@@ -1,3 +1,3 @@
1
1
  module Zipline
2
- VERSION = "1.0.2"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -15,13 +15,15 @@ module Zipline
15
15
  def each(&block)
16
16
  fake_io_writer = ZipTricks::BlockWrite.new(&block)
17
17
  ZipTricks::Streamer.open(fake_io_writer) do |streamer|
18
- @files.each {|file, name| handle_file(streamer, file, name) }
18
+ @files.each do |file, name, options = {}|
19
+ handle_file(streamer, file, name, options)
20
+ end
19
21
  end
20
22
  end
21
23
 
22
- def handle_file(streamer, file, name)
24
+ def handle_file(streamer, file, name, options)
23
25
  file = normalize(file)
24
- write_file(streamer, file, name)
26
+ write_file(streamer, file, name, options)
25
27
  end
26
28
 
27
29
  # This extracts either a url or a local file from the provided file.
@@ -46,6 +48,8 @@ module Zipline
46
48
  {file: file}
47
49
  elsif defined?(ActiveStorage::Blob) && file.is_a?(ActiveStorage::Blob)
48
50
  {url: file.service_url}
51
+ elsif is_active_storage_attachment?(file) || is_active_storage_one?(file)
52
+ {url: file.blob.service_url}
49
53
  elsif file.respond_to? :url
50
54
  {url: file.url}
51
55
  elsif file.respond_to? :path
@@ -57,8 +61,8 @@ module Zipline
57
61
  end
58
62
  end
59
63
 
60
- def write_file(streamer, file, name)
61
- streamer.write_deflated_file(name) do |writer_for_file|
64
+ def write_file(streamer, file, name, options)
65
+ streamer.write_deflated_file(name, options) do |writer_for_file|
62
66
  if file[:url]
63
67
  the_remote_url = file[:url]
64
68
  c = Curl::Easy.new(the_remote_url) do |curl|
@@ -80,5 +84,15 @@ module Zipline
80
84
  def is_io?(io_ish)
81
85
  io_ish.respond_to? :read
82
86
  end
87
+
88
+ private
89
+
90
+ def is_active_storage_attachment?(file)
91
+ defined?(ActiveStorage::Attachment) && file.is_a?(ActiveStorage::Attachment)
92
+ end
93
+
94
+ def is_active_storage_one?(file)
95
+ defined?(ActiveStorage::Attached::One) && file.is_a?(ActiveStorage::Attached::One)
96
+ end
83
97
  end
84
98
  end
@@ -84,29 +84,70 @@ describe Zipline::ZipGenerator do
84
84
  end
85
85
  end
86
86
  end
87
- context "ActiveStorage::Blob" do
87
+ context "ActiveStorage" do
88
88
  module ActiveStorage
89
- class Filename; end
89
+ class Attached
90
+ class One < Attached
91
+ end
92
+ end
93
+ class Attachment; end
90
94
  class Blob; end
91
95
  end
92
96
 
93
- let(:tempfile){ Tempfile.new('t').read }
94
- let(:filename) do
95
- fn = ActiveStorage::Filename.new()
96
- allow(fn).to receive(:to_s).and_return('spec/fakefile.txt')
97
- fn
97
+ context "Attached::One" do
98
+ it "extracts url" do
99
+ attached = create_attached_one
100
+ allow_any_instance_of(Object).to receive(:defined?).and_return(true)
101
+
102
+ normalized = generator.normalize(attached)
103
+
104
+ expect(normalized.keys).to include(:url)
105
+ expect(normalized[:url]).to eq('fakeurl')
106
+ end
107
+ end
108
+
109
+ context "Attachment" do
110
+ it "extracts url" do
111
+ attachment = create_attachment
112
+ allow_any_instance_of(Object).to receive(:defined?).and_return(true)
113
+
114
+ normalized = generator.normalize(attachment)
115
+
116
+ expect(normalized.keys).to include(:url)
117
+ expect(normalized[:url]).to eq('fakeurl')
118
+ end
119
+ end
120
+
121
+ context "Blob" do
122
+ it "extracts url" do
123
+ blob = create_blob
124
+ allow_any_instance_of(Object).to receive(:defined?).and_return(true)
125
+
126
+ normalized = generator.normalize(blob)
127
+
128
+ expect(normalized.keys).to include(:url)
129
+ expect(normalized[:url]).to eq('fakeurl')
130
+ end
131
+ end
132
+
133
+ def create_attached_one
134
+ attached = ActiveStorage::Attached::One.new
135
+ blob = create_blob
136
+ allow(attached).to receive(:blob).and_return(blob)
137
+ attached
98
138
  end
99
- let(:file) do
100
- f = ActiveStorage::Blob.new()
101
- allow(f).to receive(:filename).and_return(filename)
102
- allow(f).to receive(:service_url).and_return('fakeurl')
103
- f
139
+
140
+ def create_attachment
141
+ attachment = ActiveStorage::Attachment.new
142
+ blob = create_blob
143
+ allow(attachment).to receive(:blob).and_return(blob)
144
+ attachment
104
145
  end
105
- it "creates a File" do
106
- allow_any_instance_of(Object).to receive(:defined?).and_return(true)
107
- normalized = generator.normalize(file)
108
- expect(normalized.keys).to include(:url)
109
- expect(normalized[:url]).to eq('fakeurl')
146
+
147
+ def create_blob
148
+ blob = ActiveStorage::Blob.new
149
+ allow(blob).to receive(:service_url).and_return('fakeurl')
150
+ blob
110
151
  end
111
152
  end
112
153
  context "Fog" do
@@ -130,4 +171,46 @@ describe Zipline::ZipGenerator do
130
171
  end
131
172
  end
132
173
 
174
+ describe 'passing an options hash' do
175
+ let(:file) { StringIO.new('passthrough') }
176
+
177
+ context 'with optional arguments' do
178
+ let(:mtime) { 1.day.ago }
179
+ let(:generator) do
180
+ Zipline::ZipGenerator.new([[file, 'test', modification_time: mtime]])
181
+ end
182
+
183
+ it 'passes the options hash through handle_file' do
184
+ expect(generator).to receive(:handle_file)
185
+ .with(anything, anything, anything, modification_time: mtime)
186
+ generator.each { |_| 'Test' }
187
+ end
188
+
189
+ it 'passes the options hash to ZipTricks' do
190
+ allow(file).to receive(:url).and_return('fakeurl')
191
+ expect_any_instance_of(ZipTricks::Streamer).to receive(:write_deflated_file)
192
+ .with(anything, modification_time: mtime)
193
+ generator.each { |_| 'Test' }
194
+ end
195
+ end
196
+
197
+ context 'without optional arguments' do
198
+ let(:generator) do
199
+ Zipline::ZipGenerator.new([[file, 'test']])
200
+ end
201
+
202
+ it 'passes the options hash through handle_file' do
203
+ expect(generator).to receive(:handle_file)
204
+ .with(anything, anything, anything, {})
205
+ generator.each { |_| 'Test' }
206
+ end
207
+
208
+ it 'passes the options hash to ZipTricks' do
209
+ allow(file).to receive(:url).and_return('fakeurl')
210
+ expect_any_instance_of(ZipTricks::Streamer).to receive(:write_deflated_file)
211
+ .with(anything, {})
212
+ generator.each { |_| 'Test' }
213
+ end
214
+ end
215
+ end
133
216
  end
@@ -16,6 +16,6 @@ Gem::Specification.new do |gem|
16
16
  gem.version = Zipline::VERSION
17
17
 
18
18
  gem.add_dependency 'zip_tricks', ['>= 4.2.1', '<= 5.0.0']
19
- gem.add_dependency 'rails', ['>= 3.2.1', '< 5.3']
19
+ gem.add_dependency 'rails', ['>= 3.2.1', '< 6.1']
20
20
  gem.add_dependency 'curb', ['>= 0.8.0', '< 0.10']
21
21
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zipline
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ram Dobson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-24 00:00:00.000000000 Z
11
+ date: 2019-02-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: zip_tricks
@@ -39,7 +39,7 @@ dependencies:
39
39
  version: 3.2.1
40
40
  - - "<"
41
41
  - !ruby/object:Gem::Version
42
- version: '5.3'
42
+ version: '6.1'
43
43
  type: :runtime
44
44
  prerelease: false
45
45
  version_requirements: !ruby/object:Gem::Requirement
@@ -49,7 +49,7 @@ dependencies:
49
49
  version: 3.2.1
50
50
  - - "<"
51
51
  - !ruby/object:Gem::Version
52
- version: '5.3'
52
+ version: '6.1'
53
53
  - !ruby/object:Gem::Dependency
54
54
  name: curb
55
55
  requirement: !ruby/object:Gem::Requirement