upload_juicer 0.9.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.
- data/CHANGELOG.md +0 -0
- data/LICENSE +20 -0
- data/README.md +155 -0
- data/app/controllers/upload_juicer/uploads_controller.rb +8 -0
- data/app/helpers/uploads_helper.rb +43 -0
- data/app/models/upload_juicer/upload.rb +30 -0
- data/config/routes.rb +5 -0
- data/lib/generators/upload_juicer/templates/initializer.rb +1 -0
- data/lib/generators/upload_juicer/templates/migration.rb +20 -0
- data/lib/generators/upload_juicer/upload_juicer_generator.rb +40 -0
- data/lib/upload_juicer/engine.rb +7 -0
- data/lib/upload_juicer/extensions/string.rb +8 -0
- data/lib/upload_juicer/railtie.rb +16 -0
- data/lib/upload_juicer.rb +29 -0
- metadata +101 -0
data/CHANGELOG.md
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Juicer LLC
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
# Welcome!
|
2
|
+
|
3
|
+
This is a rather simple gem for working the the [Juicer
|
4
|
+
API](http://www.uploadjuicer.com) for resizing images. It's currently pretty
|
5
|
+
rough around the edges (no tests! ack!) but it works. :)
|
6
|
+
|
7
|
+
# The basics
|
8
|
+
|
9
|
+
## Submitting jobs
|
10
|
+
|
11
|
+
The Job class provides two class-level methods for you to interact with the
|
12
|
+
API. First, the `submit` method takes an API key, a source URL, and a array
|
13
|
+
of output hashes. This is POSTed to the API as JSON and a hash is returned to
|
14
|
+
you with the results of the API call. You'll get back a job id, the source URL
|
15
|
+
and the outputs you defined, and an indication of the status ("queued" or
|
16
|
+
"failed").
|
17
|
+
|
18
|
+
Here's an example request to create a job:
|
19
|
+
|
20
|
+
UploadJuicer::Job.submit("your api key",
|
21
|
+
"http://farm3.static.flickr.com/2084/2222523486_5e1894e314.jpg",
|
22
|
+
[{"size" => "100x100>"}])
|
23
|
+
|
24
|
+
=> {"id" => "a string", "outputs" => [{"size" => "100x100>"}], "status" => "queued"}
|
25
|
+
|
26
|
+
You can specify your own destination URLs as S3 locations:
|
27
|
+
|
28
|
+
UploadJuicer::Job.submit("your api key",
|
29
|
+
"http://farm3.static.flickr.com/2084/2222523486_5e1894e314.jpg",
|
30
|
+
[{"size" => "100x100>", "url" => "s3://mybucket/path/to/destfile.jpg"}])
|
31
|
+
|
32
|
+
=> {"id" => "a string", "outputs" => [{"size" => "100x100>", "url" => "s3://mybucket/path/to/destfile.jpg"}], "status" => "queued"}
|
33
|
+
|
34
|
+
When you specify output URLs, those URLs show up in the hash returned when
|
35
|
+
queuing the job. For this to work, you'll need to grant access to Juicer to
|
36
|
+
write to your bucket. You can find Juicer's S3 ID in the documentation at the
|
37
|
+
Juicer site.
|
38
|
+
|
39
|
+
Though size is the only required key in the outputs hashes, you can add other
|
40
|
+
keys (e.g., a label, or your own ids) to the hashes and they will be passed
|
41
|
+
back to you. This could be useful if you aren't specifying output URLs and you
|
42
|
+
want to associate some data with the URLs you'll get back.
|
43
|
+
|
44
|
+
## Querying jobs
|
45
|
+
|
46
|
+
You can use the id that was returned to you as the second argument (after your
|
47
|
+
API key) to the `info` method. The return hash would look exactly like the
|
48
|
+
hash you got back from `submit`, but hopefully the status will now be
|
49
|
+
"finished" rather than "queued" (or "failed").
|
50
|
+
|
51
|
+
# Using Juicer with Rails 3
|
52
|
+
|
53
|
+
The intended usage is to have your users upload files directly to S3 via
|
54
|
+
swfupload, create an UploadJuicer::Upload record via ajax once the upload is
|
55
|
+
complete, and then associate that UploadJuicer::Upload record and call the
|
56
|
+
Juicer API when the record your using is working with (e.g., a Project or a
|
57
|
+
Contact) is created or updated.
|
58
|
+
|
59
|
+
A Rails Engine and a generator is included with this gem to make it easy to
|
60
|
+
integrate Juicer with your Rails application. The engine provides an
|
61
|
+
UploadJuicer::Upload model, an UploadJuicer::Uploads controller, and a helper
|
62
|
+
to use in your app. The generator creates a migration, creates a configuration
|
63
|
+
file, and copies swfupload in place for you to use in your forms.
|
64
|
+
|
65
|
+
To use the generator, either specify your API key that you got from the Juicer
|
66
|
+
site with the --api-key option, or you specify that your API key will be
|
67
|
+
loaded in your Heroku environment (if you are using Juicer as a Heroku add-on)
|
68
|
+
with the --heroku option. After running the generator you'll need to run the
|
69
|
+
migration and edit the config/upload\_juicer.yml file to add your S3
|
70
|
+
credentials and specify which bucket you want to use for your uploads.
|
71
|
+
|
72
|
+
For swfupload to be able to upload to your bucket, you'll need to upload a
|
73
|
+
crossdomain.xml to the top-level of your bucket. A sample crossdomain.xml file
|
74
|
+
is placed in your public directory by the generator.
|
75
|
+
|
76
|
+
## Example
|
77
|
+
|
78
|
+
Once you are all set up, here's an example of how you'd use the gem in a Rails
|
79
|
+
view and model:
|
80
|
+
|
81
|
+
### app/views/people/new.html.erb
|
82
|
+
|
83
|
+
<%= form_for @person do |p| %>
|
84
|
+
<%= p.hidden_field :image_key, :id => :image_key %>
|
85
|
+
<%= p.hidden_field :image_id, :id => :image_id %>
|
86
|
+
|
87
|
+
<p>
|
88
|
+
<%= p.label :name %>
|
89
|
+
<%= p.text_field :name %>
|
90
|
+
</p>
|
91
|
+
|
92
|
+
<div id="file_container"></div>
|
93
|
+
<p id="upload_placeholder" class="uploadify"></p>
|
94
|
+
|
95
|
+
<p><%= p.submit %></p>
|
96
|
+
<% end %>
|
97
|
+
|
98
|
+
<% content_for :head do %>
|
99
|
+
<%= stylesheet_link_tag('swfupload.css') %>
|
100
|
+
<% end %>
|
101
|
+
|
102
|
+
<% content_for :foot do %>
|
103
|
+
<%= javascript_include_tag('swfupload.js', 'uploader.js') %>
|
104
|
+
<script type="text/javascript">
|
105
|
+
$('#upload_placeholder').uploadify(<%= swfupload_params %>);
|
106
|
+
</script>
|
107
|
+
<% end %>
|
108
|
+
|
109
|
+
This view just has two fields, the name and the file that is being uploaded.
|
110
|
+
the reference javascripts are copied into your public directory by the
|
111
|
+
generator. Once the file is selected, the upload begins (and the form is
|
112
|
+
disabled). Once the file is finished uploading, an ajax request is made to the
|
113
|
+
UploadJuicer::Uploads controller to create an UploadJuicer::Upload record, the
|
114
|
+
form is enabled, and the image\_key and image\_id fields are populated with
|
115
|
+
the JSON response from the UploadJuicer::Uploads controller with info about
|
116
|
+
the UploadJuicer::Upload model that was just created. This info is used when
|
117
|
+
the form is submitted to associated the UploadJuicer::Upload with the Person.
|
118
|
+
The Uploads helper provides the `swfupload_params` method, which does all the
|
119
|
+
request signing, etc. that S3 requires.
|
120
|
+
|
121
|
+
### app/models/person.rb
|
122
|
+
|
123
|
+
class Person < ActiveRecord::Base
|
124
|
+
has_one :image, :class_name => 'UploadJuicer::Upload', :as => :uploadable
|
125
|
+
|
126
|
+
after_save :process_image
|
127
|
+
|
128
|
+
attr_accessor :image_key, :image_id
|
129
|
+
|
130
|
+
def process_image
|
131
|
+
return if @image_key.blank? || @image_id.blank?
|
132
|
+
if self.image = UploadJuicer::Upload.first(:conditions => { :key => @image_key, :id => @image_id, :uploadable_id => nil })
|
133
|
+
image.juice_upload(:avatar => { :size => '40x40>' }, :thumb => { :size => '100x100>' })
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
This model simply associates the UploadJuicer::Upload that was created via the
|
139
|
+
AJAX call, then calls the `juice_upload` method with a hash of labels and size
|
140
|
+
info to pass on to the Juicer API. The UploadJuicer::Upload model creates
|
141
|
+
partitioned paths for the files in your S3 bucket like so:
|
142
|
+
|
143
|
+
Original: http://s3.amazonaws.com/your_bucket/34j/e8r/9fu/file_name.jpg
|
144
|
+
Avatar: http://s3.amazonaws.com/your_bucket/34j/e8r/9fu/avatar/file_name.jpg
|
145
|
+
Thumb: http://s3.amazonaws.com/your_bucket/34j/e8r/9fu/thumb/file_name.jpg
|
146
|
+
|
147
|
+
### app/views/person/show.html.erb
|
148
|
+
|
149
|
+
<h1><%= @person.name %></h1>
|
150
|
+
<p>Avatar: <%= image_tag(@person.image.url(:avatar)) %></p>
|
151
|
+
<p>Thumb: <%= image_tag(@person.image.url(:thumb)) %></p>
|
152
|
+
<p>Full image: <%= image_tag(@person.image.url) %></p>
|
153
|
+
|
154
|
+
This view shows how to get the publicly-readable S3 URLs from the
|
155
|
+
UploadJuicer::Upload record associated with the Person.
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module UploadsHelper
|
2
|
+
def s3_post_params(options = {})
|
3
|
+
acl = options[:acl] || 'public-read'
|
4
|
+
expiration = options[:expiration] || 6.hours.from_now.utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
5
|
+
max_filesize = options[:max_filesize] || 2.gigabyte
|
6
|
+
|
7
|
+
policy = Base64.encode64(
|
8
|
+
{ 'expiration' => expiration,
|
9
|
+
'conditions' => [
|
10
|
+
{'bucket' => UploadJuicer::Config.s3['bucket']},
|
11
|
+
['starts-with', '$key', s3_key],
|
12
|
+
{'acl' => acl},
|
13
|
+
{'success_action_status' => '201'},
|
14
|
+
['starts-with', '$Filename', ''],
|
15
|
+
['content-length-range', 0, max_filesize]
|
16
|
+
]
|
17
|
+
}.to_json)
|
18
|
+
|
19
|
+
signature = Base64.encode64(OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), UploadJuicer::Config.s3['secret_access_key'], policy)).gsub("\n", "")
|
20
|
+
|
21
|
+
{
|
22
|
+
"key" => "#{s3_key}/${filename}",
|
23
|
+
"AWSAccessKeyId" => "#{UploadJuicer::Config.s3['access_key_id']}",
|
24
|
+
"acl" => "#{acl}",
|
25
|
+
"policy" => "#{policy}",
|
26
|
+
"signature" => "#{signature}",
|
27
|
+
"success_action_status" => "201"
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
def s3_key
|
32
|
+
@s3_key ||= SecureRandom.hex(8).scan(/..../).join('/')
|
33
|
+
end
|
34
|
+
|
35
|
+
def s3_upload_url
|
36
|
+
@s3_upload_url ||= "http://#{UploadJuicer::Config.s3['bucket']}.s3.amazonaws.com/"
|
37
|
+
end
|
38
|
+
|
39
|
+
def swfupload_params
|
40
|
+
{ :upload_url => s3_upload_url, :post_params => s3_post_params }.to_json.html_safe
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'upload_juicer'
|
2
|
+
|
3
|
+
class UploadJuicer::Upload < ActiveRecord::Base
|
4
|
+
set_table_name 'upload_juicer_uploads'
|
5
|
+
|
6
|
+
belongs_to :uploadable, :polymorphic => :true
|
7
|
+
|
8
|
+
def url(style = nil)
|
9
|
+
"http://#{UploadJuicer::Config.s3['bucket']}.s3.amazonaws.com/#{s3_path(style)}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def s3_url(style = nil)
|
13
|
+
"s3://#{UploadJuicer::Config.s3['bucket']}/#{s3_path(style)}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def s3_path(style = nil)
|
17
|
+
style = style.to_s
|
18
|
+
style << '/' unless style.blank? || style.ends_with?('/')
|
19
|
+
"#{key}/#{style}#{file_name}"
|
20
|
+
end
|
21
|
+
|
22
|
+
# The outputs var goes from this:
|
23
|
+
# { :avatar => { :size => '40x40>' } }
|
24
|
+
# to this:
|
25
|
+
# [ { :label => 'avatar', :size => '40x40>', :url => s3_url('avatar') } ]
|
26
|
+
def juice_upload(outputs)
|
27
|
+
output_array = outputs.collect {|style, opts| { :label => style.to_s, :url => s3_url(style) }.merge(opts) }
|
28
|
+
UploadJuicer::Job.submit(UploadJuicer::Config.api_key, s3_url, output_array)
|
29
|
+
end
|
30
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
UploadJuicer::Config.api_key = <%= api_key_fetcher %>
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class CreateUploadTables < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :upload_juicer_uploads do |t|
|
4
|
+
t.string :file_name
|
5
|
+
t.string :key
|
6
|
+
t.integer :size
|
7
|
+
t.integer :uploadable_id
|
8
|
+
t.string :uploadable_type
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
add_index :upload_juicer_uploads, :key
|
14
|
+
add_index :upload_juicer_uploads, [:uploadable_id, :uploadable_type]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.down
|
18
|
+
drop_table :upload_juicer_uploads
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class UploadJuicerGenerator < Rails::Generators::Base
|
2
|
+
include Rails::Generators::Migration
|
3
|
+
|
4
|
+
desc <<-EOD
|
5
|
+
This generator creates a configuration and migration to use the API at
|
6
|
+
http://uploadjuicer.com in your Rails application. If you signed up for
|
7
|
+
Juicer via Heroku, use the --heroku option to have the API key loaded
|
8
|
+
from your Heroku environment. Otherwise, use the --api_key option to
|
9
|
+
supply the API key you received after signing up at the Juicer site.
|
10
|
+
|
11
|
+
EOD
|
12
|
+
|
13
|
+
class_option :api_key, :type => :string, :desc => "Your Juicer API key"
|
14
|
+
class_option :heroku, :type => :boolean, :desc => "Use the Heroku addon to provide your Juicer API key"
|
15
|
+
|
16
|
+
def self.source_root
|
17
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.next_migration_number(dirname)
|
21
|
+
Time.now.utc.strftime("%Y%m%d%H%M%S")
|
22
|
+
end
|
23
|
+
|
24
|
+
def doit
|
25
|
+
if !options[:api_key] && !options[:heroku] && !File.exists?(File.join('config', 'upload_juicer.yml'))
|
26
|
+
puts "Please use --api-key or --heroku or create config/upload_juicer.yml"
|
27
|
+
exit
|
28
|
+
end
|
29
|
+
migration_template 'migration.rb', File.join('db', 'migrate', 'create_upload_tables.rb')
|
30
|
+
template 'config.yml', File.join('config', 'upload_juicer.yml')
|
31
|
+
directory 'public'
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def api_key_fetcher
|
37
|
+
options[:api_key] ? options[:api_key] : "<%= ENV['JUICER_API_KEY'] %>"
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module UploadJuicer
|
2
|
+
def self.rails_init
|
3
|
+
YAML::load(ERB.new(File.read(Rails.root.join('config', 'upload_juicer.yml'))).result)[Rails.env].each { |k, v| UploadJuicer::Config.send("#{k}=", v) } rescue nil
|
4
|
+
end
|
5
|
+
|
6
|
+
if defined?(::Rails::Railtie)
|
7
|
+
class Railtie < ::Rails::Railtie
|
8
|
+
config.after_initialize do |app|
|
9
|
+
UploadJuicer.rails_init
|
10
|
+
end
|
11
|
+
end
|
12
|
+
else
|
13
|
+
rails_init
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest_client'
|
3
|
+
require 'ostruct'
|
4
|
+
|
5
|
+
module UploadJuicer
|
6
|
+
API_URL = 'http://app.uploadjuicer.com/jobs'
|
7
|
+
VERSION = '0.9.1'
|
8
|
+
|
9
|
+
Config = OpenStruct.new
|
10
|
+
|
11
|
+
class Job
|
12
|
+
def self.submit(api_key, url, outputs)
|
13
|
+
JSON.parse(RestClient.post("#{UploadJuicer::API_URL}?token=#{api_key}&gem=#{UploadJuicer::VERSION}",
|
14
|
+
{ :url => url, :outputs => outputs }.to_json, { :content_type => :json, :accept => :json }))
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.info(api_key, id)
|
18
|
+
JSON.parse(RestClient.get("#{UploadJuicer::API_URL}/#{id}?token=#{api_key}&gem=#{UploadJuicer::VERSION}",
|
19
|
+
{ :content_type => :json, :accept => :json }))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
if defined?(Rails)
|
26
|
+
require 'upload_juicer/extensions/string'
|
27
|
+
require 'upload_juicer/railtie'
|
28
|
+
require 'upload_juicer/engine'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: upload_juicer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 9
|
8
|
+
- 1
|
9
|
+
version: 0.9.1
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Benjamin Curtis
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-07-20 00:00:00 -07:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rest-client
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
version: "0"
|
30
|
+
type: :runtime
|
31
|
+
version_requirements: *id001
|
32
|
+
- !ruby/object:Gem::Dependency
|
33
|
+
name: json
|
34
|
+
prerelease: false
|
35
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
segments:
|
40
|
+
- 0
|
41
|
+
version: "0"
|
42
|
+
type: :runtime
|
43
|
+
version_requirements: *id002
|
44
|
+
description:
|
45
|
+
email:
|
46
|
+
- ben@uploadjuicer.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files: []
|
52
|
+
|
53
|
+
files:
|
54
|
+
- lib/generators/upload_juicer/templates/initializer.rb
|
55
|
+
- lib/generators/upload_juicer/templates/migration.rb
|
56
|
+
- lib/generators/upload_juicer/upload_juicer_generator.rb
|
57
|
+
- lib/upload_juicer/engine.rb
|
58
|
+
- lib/upload_juicer/extensions/string.rb
|
59
|
+
- lib/upload_juicer/railtie.rb
|
60
|
+
- lib/upload_juicer.rb
|
61
|
+
- app/controllers/upload_juicer/uploads_controller.rb
|
62
|
+
- app/helpers/uploads_helper.rb
|
63
|
+
- app/models/upload_juicer/upload.rb
|
64
|
+
- config/routes.rb
|
65
|
+
- LICENSE
|
66
|
+
- CHANGELOG.md
|
67
|
+
- README.md
|
68
|
+
has_rdoc: true
|
69
|
+
homepage: http://www.uploadjuicer.com
|
70
|
+
licenses: []
|
71
|
+
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
|
75
|
+
require_paths:
|
76
|
+
- lib
|
77
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - ">="
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
segments:
|
82
|
+
- 0
|
83
|
+
version: "0"
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
segments:
|
89
|
+
- 1
|
90
|
+
- 3
|
91
|
+
- 6
|
92
|
+
version: 1.3.6
|
93
|
+
requirements: []
|
94
|
+
|
95
|
+
rubyforge_project:
|
96
|
+
rubygems_version: 1.3.6
|
97
|
+
signing_key:
|
98
|
+
specification_version: 3
|
99
|
+
summary: UploadJuicer juices up your images!
|
100
|
+
test_files: []
|
101
|
+
|