zipstream 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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'