IronDigital-zippy 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/README +19 -0
  2. data/lib/zippy.rb +216 -0
  3. data/rails/README +18 -0
  4. data/rails/init.rb +23 -0
  5. metadata +66 -0
data/README ADDED
@@ -0,0 +1,19 @@
1
+ Zippy.create 'awsum.zip' do |zip|
2
+ zip['README'] = 'In Soviet Russia, README READSYOU'
3
+ zip['porn.mpeg'] = File.open('rick astley - never gonna give you up.mpg')
4
+ end
5
+
6
+ Zippy.list('awsum.zip') #=> ['README', 'porn.mpeg']
7
+
8
+ Zippy.open('awsum.zip') do |zip|
9
+ zip['bin/hello_world'] = "#!/usr/bin/env ruby\n\nputs 'hello, zip world'"
10
+ end
11
+
12
+
13
+
14
+ #Your params as a zip
15
+ #It's SAAS!
16
+ require 'sinatra'
17
+ get '/' do
18
+ Zippy.new{|z| params.each{|k,v| z[k] = v } }.data
19
+ end
@@ -0,0 +1,216 @@
1
+ require 'zip/zip'
2
+
3
+ class Zippy
4
+
5
+ include Enumerable
6
+ #extend Enumerable
7
+
8
+
9
+ #Make an archive
10
+ #Filename is optional; if none is provided, a generated, temporary
11
+ #filename will be used.
12
+ #If a block is provided, the archive is yielded
13
+ #Takes an optional second parameter which is a hash of entries that will
14
+ #be added after initialization
15
+ def initialize(entries_and_options={})
16
+ entries_and_options.each{|k,v| send("#{k}=", v) if respond_to?("#{k}=") && k.is_a?(Symbol) }
17
+ without_autocommit do
18
+ entries_and_options.each{|k,v| self[k] = v if k.is_a?(String) }
19
+ end
20
+ yield self if block_given?
21
+ end
22
+
23
+
24
+ def each
25
+ zipfile.each{|e| yield e.name }
26
+ end
27
+
28
+ def size
29
+ zipfile.size
30
+ end
31
+
32
+ def empty?
33
+ size.zero?
34
+ end
35
+
36
+ #Returns the full path to all entries in the archive
37
+ def paths
38
+ map
39
+ end
40
+
41
+
42
+ #Read an entry
43
+ def [](entry)
44
+ return nil unless include?(entry)
45
+ zipfile.read(entry)
46
+ end
47
+
48
+ #Add or change an entry with the name +entry+
49
+ #+contents+ can be a string or an IO
50
+ def []=(entry, contents)
51
+ zipfile.get_output_stream entry do |s|
52
+ if contents.is_a?(String)
53
+ s.write contents
54
+ elsif contents.respond_to?(:read)
55
+ s.write contents.read(1024) until contents.eof?
56
+ elsif contents.respond_to?(:to_s)
57
+ s.write contents.to_s
58
+ else#Not sure these last two are different
59
+ s.write "#{contents}"
60
+ end
61
+ end
62
+ zipfile.commit if autocommit?
63
+ true
64
+ end
65
+
66
+
67
+ #Delete an entry
68
+ def delete(*entries)
69
+ entries.each do |entry|
70
+ zipfile.remove(entry)
71
+ end
72
+ zipfile.commit if autocommit?
73
+ entries
74
+ end
75
+
76
+ #Rename an entry
77
+ def rename(old_name, new_name)
78
+ zipfile.rename(old_name, new_name)
79
+ zipfile.commit if autocommit?
80
+ old_name
81
+ end
82
+
83
+
84
+ #Close the archive for writing
85
+ def close
86
+ write(filename)
87
+ zipfile.close
88
+ end
89
+
90
+ #Write the archive to +filename+
91
+ #If a filename is not provided, it will write
92
+ #to the default filename (self.filename)
93
+ def write(filename)
94
+ return false if empty?
95
+ zipfile.commit
96
+ unless filename == self.filename
97
+ FileUtils.cp(self.filename, filename)
98
+ end
99
+ true
100
+ end
101
+
102
+ #Returns the entire archive as a string
103
+ def data
104
+ return nil if empty?
105
+ zipfile.commit
106
+ File.read(filename)
107
+ end
108
+
109
+
110
+ def filename
111
+ @filename ||= random_filename
112
+ end
113
+
114
+ def filename=(filename)
115
+ rename_file(filename)
116
+ @filename = filename
117
+ end
118
+
119
+
120
+ def zipfile
121
+ @zipfile ||= Zip::ZipFile.new(filename, true)
122
+ end
123
+
124
+
125
+ #Create a new archive with the name +filename+, populate it
126
+ #and then close it
127
+ #
128
+ #Warning: Will overwrite existing file
129
+ def self.create(filename, options_and_entries={}, &b)
130
+ File.unlink(filename) if File.exists?(filename)
131
+ z = new({:filename => filename}.merge(options_and_entries), &b)
132
+ z.close
133
+ z
134
+ end
135
+
136
+ #Works the same as new, but require's an explicit filename
137
+ #If a block is provided, it will be closed at the end of the block
138
+ def self.open(filename, options_and_entries={})
139
+ raise(ArgumentError, "file \"#{filename}\" does not exist") unless File.exists?(filename)
140
+ z = new({:filename => filename}.merge(options_and_entries))
141
+ if block_given?
142
+ yield z
143
+ z.close
144
+ end
145
+ z
146
+ end
147
+
148
+ #Iterate each entry name _and_ its contents in the archive +filename+
149
+ def self.each(filename)
150
+ open(filename) do |zip|
151
+ zip.each do |name|
152
+ yield name, zip[name]
153
+ end
154
+ end
155
+ end
156
+
157
+ #Returns an array of entry names from the archive +filename+
158
+ #
159
+ #Zippy.list('my.zip') #=> ['foo', 'bar']
160
+ def self.list(filename)
161
+ list = nil
162
+ open(filename){|z| list = z.paths }
163
+ list
164
+ end
165
+
166
+
167
+ #Read the contents of a single entry in +filename+
168
+ def self.read(filename, entry)
169
+ content = nil
170
+ open(filename){|z| content = z[entry] }
171
+ content
172
+ end
173
+
174
+
175
+ def self.[](filename, entry=nil)
176
+ entry ? read(filename, entry) : list(filename)
177
+ end
178
+
179
+ def self.[]=(filename, entry, content)
180
+ open(filename){|z| z[entry] = content }
181
+ end
182
+
183
+
184
+ private
185
+
186
+ def random_filename
187
+ File.join(Dir.tmpdir, "zippy_#{Time.now.to_f.to_s}.zip")
188
+ end
189
+
190
+
191
+ def rename_file(new_name)
192
+ if @filename && @zipfile && File.exists?(@filename)
193
+ zipfile.close
194
+ File.rename(@filename, new_name)
195
+ end
196
+ @zipfile = nil #Force reload
197
+ end
198
+
199
+
200
+ def autocommit?
201
+ @autocommit.nil? ? true : @autocommit
202
+ end
203
+
204
+ def autocommit=(b)
205
+ @autocommit = !!b
206
+ end
207
+
208
+ def without_autocommit
209
+ ac = autocommit?
210
+ self.autocommit = false
211
+ yield
212
+ self.autocommit = ac
213
+ end
214
+
215
+
216
+ end
@@ -0,0 +1,18 @@
1
+ This plugin adds a template handler for the extension "zipper", so you
2
+ could for example have a view show.zip.zipper which returns a zip file.
3
+ The view file is evaluated as Ruby, inside a Zippy.new{|zip|} block.
4
+
5
+ Example controller:
6
+ def show
7
+ @gallery = Gallery.find(params[:id])
8
+ respond_to do |format|
9
+ format.html
10
+ format.zip
11
+ end
12
+ end
13
+
14
+ Example view:
15
+ zip['description.txt'] = @gallery.description
16
+ @gallery.photos.each do |photo|
17
+ zip["photo_#{photo.id}.png"] = File.open(photo.url)
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'zippy'
2
+
3
+ Mime::Type.register 'application/zip', :zip
4
+
5
+ module ::ActionView
6
+ module TemplateHandlers
7
+ class Zipper < TemplateHandler
8
+ include Compilable
9
+
10
+ def compile(template)
11
+ "Zippy.new do |zip|" +
12
+ (template.respond_to?(:source) ? template.source : template) +
13
+ "end.data"
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ if defined? ::ActionView::Template and ::ActionView::Template.respond_to? :register_template_handler
20
+ ::ActionView::Template
21
+ else
22
+ ::ActionView::Base
23
+ end.register_template_handler(:zipper, ::ActionView::TemplateHandlers::Zipper)
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: IronDigital-zippy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Tore Darell
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-07-25 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: IronDigital-rubyzip
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.9.1
24
+ version:
25
+ description: Zippy reads and writes zip files
26
+ email: toredarell@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files: []
32
+
33
+ files:
34
+ - lib/zippy.rb
35
+ - README
36
+ - rails/init.rb
37
+ - rails/README
38
+ has_rdoc: false
39
+ homepage: http://github.com/toretore/zippy
40
+ licenses:
41
+ post_install_message:
42
+ rdoc_options: []
43
+
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: "0"
51
+ version:
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ requirements: []
59
+
60
+ rubyforge_project:
61
+ rubygems_version: 1.3.5
62
+ signing_key:
63
+ specification_version: 2
64
+ summary: rubyzip for dummies
65
+ test_files: []
66
+