zipstream 0.0.3 → 0.1.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.
data/README.md CHANGED
@@ -2,6 +2,28 @@
2
2
 
3
3
  Create zip files to a stream.
4
4
 
5
+ Integration with Ruby on Rails means you can create a file, `index.zipstream`, which is a ruby file with a zip object:
6
+
7
+ @entries.each do |entry|
8
+ zip.write "entry-#{entry.id}.txt", entry.to_s
9
+ end
10
+
11
+ Which will happily implicitly render from:
12
+
13
+ class EntriesController
14
+ def index
15
+ @entries = Entry.all
16
+ end
17
+ end
18
+
19
+ Giving you a zip file when rendered. More to come!
20
+
21
+ ## Caveats
22
+
23
+ Keep in mind that this will use one of your workers/threads/processes until the file is completely downloaded. We are using an iterated rack body which streams so if rack/web servers handle this nicely then you might be in luck.
24
+
25
+ Tested with Rails 3.1 on REE 1.8.7 and MRI 1.9.3. Specs coming soon (tm).
26
+
5
27
  ## Thanks
6
28
 
7
29
  Inspired by http://pablotron.org/software/zipstream-php/
@@ -9,3 +31,5 @@ Inspired by http://pablotron.org/software/zipstream-php/
9
31
  ## License
10
32
 
11
33
  Copyright (c) 2011 Samuel Cochran (sj26@sj26.com). Released under the MIT License, see [LICENSE][license] for details.
34
+
35
+ [license]: https://github.com/sj26/zipstream/blob/master/LICENSE
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
1
+ 0.1.0
@@ -2,7 +2,7 @@ require 'date'
2
2
  require 'zlib'
3
3
 
4
4
  # Simple, streamable zip file creation
5
- class ZipStream
5
+ class Zipstream
6
6
  VERSION = File.read File.expand_path '../../VERSION', __FILE__
7
7
 
8
8
  def initialize stream, options={}
@@ -25,6 +25,7 @@ class ZipStream
25
25
  crc = Zlib.crc32 data
26
26
  zdata_length = zdata.length
27
27
  data_length = data.length
28
+ name = name.to_s
28
29
  name_length = name.length
29
30
  comment = options[:comment].to_s || ""
30
31
  comment_length = comment.length
@@ -125,3 +126,8 @@ protected
125
126
  datetime.year << 25 | datetime.month << 21 | datetime.day << 16 | datetime.hour << 11 | datetime.min << 5 | datetime.sec >> 1
126
127
  end
127
128
  end
129
+
130
+ require 'zipstream/fiber'
131
+ require 'zipstream/fiber_yielding_stream'
132
+ require 'zipstream/body'
133
+ require 'zipstream/railtie' if defined? Rails
@@ -1,32 +1,21 @@
1
- require 'zipstream'
2
- require 'zipstream-fiber-compat' unless defined? Fiber
3
-
1
+ # Stream a zipfile as a rack response body
2
+ #
4
3
  # We use Fibers to deep-yield data being written to the zip stream
5
- # to use as a rack response body (responds to #each)
6
- class ZipStream::Body
4
+ # directly to Rack
5
+ class Zipstream::Body
7
6
  def initialize &block
8
- @stream = FiberYieldingStream.new
9
- @fiber = Fiber.new do
10
- zip = ZipStream.new @stream
11
- block.call zip
12
- zip.close
7
+ @stream = Zipstream::FiberYieldingStream.new
8
+ @fiber = Zipstream::Fiber.new do
9
+ Zipstream.new(@stream).tap(&block).close
13
10
  # Make sure this returns nil as a sentinel
14
11
  nil
15
12
  end
16
13
  end
17
14
 
18
15
  def each
19
- while !(data = @fiber.resume).nil?
20
- yield data
16
+ # Yield fiber yielded data until we hit our nil sentinel
17
+ until (yielded = @fiber.resume).nil?
18
+ yield yielded.first
21
19
  end
22
20
  end
23
-
24
- # A stream that yields each write to the current fiber
25
- class FiberYieldingStream
26
- def write data
27
- tap { Fiber.yield data }
28
- end
29
-
30
- alias << write
31
- end
32
21
  end
@@ -0,0 +1,45 @@
1
+ if defined? Fiber
2
+ # Use native Fibers if available
3
+ Zipstream::Fiber = Fiber
4
+ else
5
+ # Minimal compatibility layer for Fibers
6
+ # Doesn't seem very comprehensive nor resilient, but it does the job
7
+ # Credit: http://www.khjk.org/log/2010/jun/fibr.html
8
+ class Zipstream::Fiber
9
+ @@fibers = [] # a stack of fibers corresponding to calls of 'resume'
10
+
11
+ def initialize &block
12
+ # lambda makes 'return' work as expected
13
+ @body = lambda &block
14
+ end
15
+
16
+ def resume *args
17
+ @@fibers.push self
18
+ # jumping into fiber
19
+ jump *args
20
+ end
21
+
22
+ def self.current
23
+ @@fibers.last
24
+ end
25
+
26
+ def self.yield *args
27
+ if fiber = @@fibers.pop
28
+ # jumping out of fiber
29
+ fiber.send :jump, args
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def jump *args
36
+ callcc do |continuation|
37
+ destination, @body = @body, continuation
38
+ destination.call *args
39
+ @@fibers.pop
40
+ # return from the last 'resume'
41
+ @body.call
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,8 @@
1
+ # A super-simple stream that yields each write to the current fiber
2
+ class Zipstream::FiberYieldingStream
3
+ def write data
4
+ tap { Zipstream::Fiber.yield data }
5
+ end
6
+
7
+ alias << write
8
+ end
@@ -0,0 +1,24 @@
1
+ # Adds zip rendering support to Rails
2
+ class Zipstream::Railtie < Rails::Railtie
3
+ initializer "zipstream" do
4
+ # Register Mime::ZIP
5
+ Mime::Type.register "application/zip", :zip
6
+
7
+ # Mark our template handler as rendering zip files
8
+ Zipstream::Railtie::Template.default_format = Mime::ZIP
9
+
10
+ # Tell ActionView we can handle templates
11
+ ActionView::Template.register_template_handler :zipstream, Zipstream::Railtie::Template
12
+ end
13
+
14
+ # Create a zipstream as a rails template
15
+ class Template
16
+ class_attribute :default_format
17
+
18
+ def self.call template
19
+ "Zipstream::Body.new do |zip|
20
+ #{template.source}
21
+ end"
22
+ end
23
+ end
24
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zipstream
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-11-04 00:00:00.000000000 Z
12
+ date: 2011-11-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rspec
16
- requirement: &70230380021020 !ruby/object:Gem::Requirement
16
+ requirement: &70190926780580 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,7 +21,7 @@ dependencies:
21
21
  version: 2.7.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70230380021020
24
+ version_requirements: *70190926780580
25
25
  description:
26
26
  email: sj26@sj26.com
27
27
  executables: []
@@ -34,7 +34,9 @@ files:
34
34
  - LICENSE
35
35
  - VERSION
36
36
  - lib/zipstream/body.rb
37
- - lib/zipstream-fiber-compat.rb
37
+ - lib/zipstream/fiber.rb
38
+ - lib/zipstream/fiber_yielding_stream.rb
39
+ - lib/zipstream/railtie.rb
38
40
  - lib/zipstream.rb
39
41
  homepage: http://github.com/sj26/zipstream
40
42
  licenses: []
@@ -1,35 +0,0 @@
1
- # Credit: http://www.khjk.org/log/2010/jun/fibr.html
2
-
3
- class Fiber
4
- @@fibers = [] # a stack of fibers corresponding to calls of 'resume'
5
-
6
- def initialize &block
7
- @body = lambda &block # lambda makes 'return' work as expected
8
- end
9
-
10
- def resume *args
11
- @@fibers.push self
12
- jump *args # jumping into fiber
13
- end
14
-
15
- def self.current
16
- @@fibers.last
17
- end
18
-
19
- def self.yield *args
20
- if fiber = @@fibers.pop
21
- fiber.send :jump, args # jumping out of fiber
22
- end
23
- end
24
-
25
- private
26
-
27
- def jump *args
28
- callcc do |continuation|
29
- destination, @body = @body, continuation
30
- destination.call *args
31
- @@fibers.pop
32
- @body.call # return from the last 'resume'
33
- end
34
- end
35
- end if RUBY_VERSION < '1.9'