attachinary 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -14,6 +14,7 @@ Why is Attachinary different:
14
14
  * **Files are uploaded directly to Cloudinary** completely bypassing your app (without affecting its performance).
15
15
  * **Very easy to use**. Once set up, 1 line is enough to add attachment support to your model. **No migrations, no Uploaders**.
16
16
  * **Lightweight form submission**. Attachinary handles file upload asynchronously and the only thing that is passed to your server is metadata. That makes form postbacks fast and reliable.
17
+ * Benefits of [jQuery File Upload](https://github.com/blueimp/jQuery-File-Upload/) (**drag'n'drop**, **selecting multiple files**, **progress indicators**.. etc)
17
18
  * All the [benefits of Cloudinary](http://cloudinary.com/documentation/image_transformations) (resizing, cropping, rotating, rounding corners, **face detection**...).
18
19
 
19
20
  Attachinary uses [Cloudinary](http://cloudinary.com) service. Gem is structured as mountable rails engine.
@@ -52,35 +53,52 @@ Finally, make sure that you have following line in head section of your applicat
52
53
 
53
54
  Lets say that we want all of our **users** to have single **avatar** and many **photos** in their gallery. We also want *avatar* to be required. We also want to limit the number of photos user can upload to 10. We can declare it like this:
54
55
 
55
- class User < ActiveRecord::Base
56
- ...
57
- has_attachment :avatar, accept: [:jpg, :png, :gif]
58
- has_attachments :photos, maximum: 10
56
+ ```ruby
57
+ class User < ActiveRecord::Base
58
+ ...
59
+ has_attachment :avatar, accept: [:jpg, :png, :gif]
60
+ has_attachments :photos, maximum: 10
59
61
 
60
- validates :avatar, presence: true
61
- ...
62
- end
62
+ validates :avatar, presence: true
63
+ # ...
64
+ end
65
+ ```
63
66
 
64
67
  In our `_form.html.erb` template, we need to add only this:
65
68
 
66
- <%= f.attachinary_file_field :avatar %>
67
- <%= f.attachinary_file_field :photos %>
69
+ ```erb
70
+ <%= f.attachinary_file_field :avatar %>
71
+ <%= f.attachinary_file_field :photos %>
72
+ ```
68
73
 
69
74
  If you're using [SimpleForm](https://github.com/plataformatec/simple_form), you can even shorten this to:
70
75
 
71
- <%= f.input :avatar, as: :attachinary %>
72
- <%= f.input :photos, as: :attachinary %>
76
+ ```erb
77
+ <%= f.input :avatar, as: :attachinary %>
78
+ <%= f.input :photos, as: :attachinary %>
79
+ ```
73
80
 
74
- Finally, you have to include both `cloudinary` and `attachinary` into your asset pipeline. In your `application.js`, add following lines:
81
+ Finally, you have to include both required javascript files. In your `application.js`, add following lines:
75
82
 
76
- ...
77
- //= require cloudinary
78
- //= require attachinary
79
- ...
83
+ ```javascript
84
+ //= require jquery.ui.widget
85
+ //= require jquery.iframe-transport
86
+ //= require jquery.fileupload
87
+ //= require cloudinary/jquery.cloudinary
88
+ //= require attachinary
89
+ ```
90
+
91
+ If you don't have the jQuery File Upload files, you can use following rake task to fetch (or update) them:
92
+
93
+ ```
94
+ rake attachinary:fetch_fileupload
95
+ ```
80
96
 
81
97
  And, add this code on document ready:
82
98
 
83
- $('.attachinary-input').attachinary()
99
+ ```javascript
100
+ $('.attachinary-input').attachinary()
101
+ ```
84
102
 
85
103
  Attachinary jquery plugin is based upon [jQuery File Upload plugin](https://github.com/blueimp/jQuery-File-Upload) but without any fancy UI (it leaves it up to you to decorate it).
86
104
 
@@ -91,24 +109,50 @@ Plugin is fully customizable. It uses John Resig's micro templating in the backg
91
109
 
92
110
  Here comes the good part. There is no need to transform images on your server. Instead, you can request image transformations directly from Cloudinary. First time you request image, it is created and cached on the Cloudinary server for later use. Here is sample code that you can use in your `_user.html.erb` partial:
93
111
 
94
- <% if @user.avatar? %>
95
- <%= cl_image_tag(@user.avatar.path, { size: '50x50', crop: :face }) %>
96
- <% end %>
112
+ ```erb
113
+ <% if @user.avatar? %>
114
+ <%= cl_image_tag(@user.avatar.path, { size: '50x50', crop: :fit, gravity: :face }) %>
115
+ <% end %>
97
116
 
98
- <% @user.photos.each do |photo| %>
99
- <%= cl_image_tag(photo.path, { size: '125x125', crop: :fit }) %>
100
- <% end %>
117
+ <% @user.photos.each do |photo| %>
118
+ <%= cl_image_tag(photo.path, { size: '125x125', crop: :fit }) %>
119
+ <% end %>
120
+ ```
101
121
 
102
122
  Avatar will be automatically cropped to 50x50px to show only user face. You read it right: **face detection** :) All other user photos are just cropped to fit within 125x125.
103
123
 
104
124
  Whenever you feel like changing image sizes, you don't need to set rake task that will take forever to re-process thousands of photos. You just change the dimension in your partial and thats it.
105
125
 
106
126
 
127
+ ### Additional methods
128
+
129
+ ```ruby
130
+ # uploading avatar by passing url
131
+ user.avatar_url = "http://path/to/avatar.jpg"
132
+
133
+ # uploading photos by passing multiple urls
134
+ user.photo_urls = %w[ http://path/to/photo1.jpg http://path/to/photo2.jpg]
135
+
136
+ # uploading by passing IO object (e.g. direct file upload)
137
+ user.avatar = File.open("/path/to/file", 'r')
138
+ ```
139
+
140
+
141
+ ### No-JS usage
142
+
143
+ If you don't want fancy JS features, all you have to do is just switch to `:input` file field:
144
+
145
+ ```erb
146
+ <%= f.input :photo, as: :file %>
147
+ <%= f.input :images, as: :file, input_html: { multiple: true } %>
148
+ ```
149
+
150
+
107
151
  ## Conventions
108
152
 
109
153
  * always use singular identifier after `has_attachment` (e.g. `has_attachment :photo`)
110
154
  * always use plural identifier after `has_attachments` (e.g. `has_attachments :images`)
111
- * you can't use colliding identifiers (e.g. `has_attachment :photo` and `has_attachments :photos`) on same model.
155
+ * do not use colliding identifiers (e.g. `has_attachment :photo` and `has_attachments :photos`) on same model.
112
156
 
113
157
 
114
158
  ## Requirements and Compatibility
@@ -1,4 +1,3 @@
1
1
  Attachinary::Engine.routes.draw do
2
2
  get '/cors' => 'cors#show', format: 'json', as: 'cors'
3
- get '/callback' => 'files#callback', format: 'json', as: 'callback'
4
3
  end
@@ -4,6 +4,7 @@
4
4
  index: 0
5
5
  config:
6
6
  disableWith: 'Uploading...'
7
+ indicateProgress: true
7
8
  invalidFormatMessage: 'Invalid file format'
8
9
  template: """
9
10
  <ul>
@@ -37,6 +38,9 @@
37
38
  @options = @$input.data('attachinary')
38
39
  @files = @options.files
39
40
 
41
+ @$form = @$input.closest('form')
42
+ @$submit = @$form.find('input[type=submit]')
43
+
40
44
  @initFileUpload()
41
45
  @addFilesContainer()
42
46
  @bindEventHandlers()
@@ -47,46 +51,55 @@
47
51
  @options.field_name = @$input.attr('name')
48
52
 
49
53
  options =
50
- maxFileSize: 10000000
51
54
  dataType: 'json'
52
55
  paramName: 'file'
53
56
  headers: {"X-Requested-With": "XMLHttpRequest"}
57
+ dropZone: @$input
58
+ sequentialUploads: true
54
59
 
55
60
  if @$input.attr('accept')
56
61
  options.acceptFileTypes = new RegExp("^#{@$input.attr('accept').split(",").join("|")}$", "i")
57
62
 
58
63
  @$input.fileupload(options)
59
64
 
60
-
61
65
  bindEventHandlers: ->
62
- @$input.bind 'fileuploaddone', (event, data) =>
63
- setTimeout (=> @addFile(data.result)), 0 # let 'fileuploadalways' finish
64
-
65
- @$input.bind 'fileuploadstart', (event) =>
66
- @$input = $(event.target) # important! changed on every file upload
67
- $form = @$input.closest('form')
68
- $submit = $form.find('input[type=submit]')
69
-
66
+ @$input.bind 'fileuploadsend', (event, data) =>
70
67
  @$input.addClass 'uploading'
71
- $form.addClass 'uploading'
68
+ @$form.addClass 'uploading'
72
69
 
73
70
  @$input.prop 'disabled', true
74
71
  if @config.disableWith
75
- $submit.data 'old-val', $submit.val()
76
- $submit.val @config.disableWith
77
- $submit.prop 'disabled', true
72
+ @$submit.data 'old-val', @$submit.val()
73
+ @$submit.val @config.disableWith
74
+ @$submit.prop 'disabled', true
75
+
76
+ !@maximumReached()
77
+
78
+
79
+ @$input.bind 'fileuploaddone', (event, data) =>
80
+ @addFile(data.result)
78
81
 
79
- @$input.bind 'fileuploadalways', (event) =>
80
- $form = @$input.closest('form')
81
- $submit = $form.find('input[type=submit]')
82
82
 
83
+ @$input.bind 'fileuploadstart', (event) =>
84
+ # important! changed on every file upload
85
+ @$input = $(event.target)
86
+
87
+
88
+ @$input.bind 'fileuploadalways', (event) =>
83
89
  @$input.removeClass 'uploading'
84
- $form.removeClass 'uploading'
90
+ @$form.removeClass 'uploading'
85
91
 
86
- @$input.prop 'disabled', false
92
+ @checkMaximum()
87
93
  if @config.disableWith
88
- $submit.val $submit.data('old-val')
89
- $submit.prop 'disabled', false
94
+ @$submit.val @$submit.data('old-val')
95
+ @$submit.prop 'disabled', false
96
+
97
+
98
+ @$input.bind 'fileuploadprogressall', (e, data) =>
99
+ progress = parseInt(data.loaded / data.total * 100, 10)
100
+ if @config.disableWith && @config.indicateProgress
101
+ @$submit.val "[#{progress}%] #{@config.disableWith}"
102
+
90
103
 
91
104
  addFile: (file) ->
92
105
  if !@options.accept || $.inArray(file.format, @options.accept) != -1
@@ -102,11 +115,16 @@
102
115
  @checkMaximum()
103
116
 
104
117
  checkMaximum: ->
105
- if @options.maximum && @files.length >= @options.maximum
118
+ if @maximumReached()
106
119
  @$input.prop('disabled', true)
107
120
  else
108
121
  @$input.prop('disabled', false)
109
122
 
123
+ maximumReached: ->
124
+ @options.maximum && @files.length >= @options.maximum
125
+
126
+
127
+
110
128
  addFilesContainer: ->
111
129
  @$filesContainer = $('<div class="attachinary_container">')
112
130
  @$input.after @$filesContainer
@@ -1,4 +1,5 @@
1
1
  require_relative 'file_mixin'
2
+ require_relative 'base_extension'
2
3
  require_relative 'active_record/extension'
3
4
  require_relative 'active_record/file'
4
5
 
@@ -1,94 +1,37 @@
1
+ require 'attachinary/utils'
2
+
1
3
  module Attachinary
2
4
  module Extension
5
+ include Base
3
6
 
4
- def has_attachment(scope, options={})
5
- options[:single] = true
6
- attachinary scope, options
7
- end
8
-
9
- def has_attachments(scope, options={})
10
- options[:single] = false
11
- attachinary scope, options
12
- end
13
-
14
- def attachinary(scope, options)
15
- options.reverse_merge!({
16
- accessible: true
17
- })
18
-
19
- if options[:single]
20
- singular = scope.to_s
21
- plural = scope.to_s.pluralize
22
- else
23
- plural = scope.to_s
24
- singular = scope.to_s.singularize
25
- end
26
-
27
- relation = "#{singular}_files"
7
+ def attachinary_orm_definition(options)
8
+ relation = "#{options[:singular]}_files"
28
9
 
29
10
  # has_many :photo_files, ...
30
11
  # has_many :image_files, ...
31
12
  has_many :"#{relation}",
32
13
  as: :attachinariable,
33
14
  class_name: '::Attachinary::File',
34
- conditions: { scope: scope.to_s },
15
+ conditions: { scope: options[:scope].to_s },
35
16
  dependent: :destroy
36
17
 
37
- # attr_accessible :photo
38
- # attr_accessible :images
39
- attr_accessible :"#{scope}" if options[:accessible]
40
-
41
-
42
- # def photo?
43
- # photo.present?
44
- # end
45
- # def images?
46
- # images.present?
47
- # end
48
- define_method :"#{scope}?" do
49
- send(:"#{scope}").present?
50
- end
51
-
52
- # def photo_metadata
53
- # options[:scope] = 'photo'
54
- # options[:maximum] = 1 if options[:single]
55
- # options
56
- # end
57
- define_method :"#{scope}_metadata" do
58
- options[:scope] = scope
59
- options[:maximum] = 1 if options[:single]
60
- options
61
- end
62
18
 
63
19
  # def photo=(file)
64
- # if file.blank?
65
- # self.photo_files.clear
20
+ # input = Attachinary::Utils.process_input(input)
21
+ # if input.blank?
22
+ # photo_files.clear
66
23
  # else
67
- # case file
68
- # when String
69
- # files = ... parse JSON and MAP to array of Attachinary::File ..
70
- # self.photo_files = files
71
- # else
72
- # self.photo_files = [file].flatten
73
- # end
24
+ # files = [input].flatten
25
+ # self.photo_files = files
74
26
  # end
75
27
  # end
76
- define_method "#{scope}=" do |file|
77
- if file.blank?
28
+ define_method "#{options[:scope]}=" do |input|
29
+ input = Attachinary::Utils.process_input(input, options[:scope])
30
+ if input.nil?
78
31
  send("#{relation}").clear
79
32
  else
80
- case file
81
- when String
82
- files = [JSON.parse(file)].flatten.map do |data|
83
- data = data.slice(*Attachinary::File.attr_accessible[:default].to_a)
84
- Attachinary::File.new(data) do |f|
85
- f.scope = scope.to_s
86
- end
87
- end
88
- send("#{relation}=", files)
89
- else
90
- send("#{relation}=", [file].flatten)
91
- end
33
+ files = [input].flatten
34
+ send("#{relation}=", files)
92
35
  end
93
36
  end
94
37
 
@@ -97,7 +40,7 @@ module Attachinary
97
40
  # def photo
98
41
  # photo_files.first
99
42
  # end
100
- define_method "#{scope}" do
43
+ define_method "#{options[:scope]}" do
101
44
  send("#{relation}").first
102
45
  end
103
46
 
@@ -105,7 +48,7 @@ module Attachinary
105
48
  # def images
106
49
  # image_files
107
50
  # end
108
- define_method "#{scope}" do
51
+ define_method "#{options[:scope]}" do
109
52
  send("#{relation}")
110
53
  end
111
54
  end
@@ -0,0 +1,63 @@
1
+ require 'attachinary/utils'
2
+
3
+ module Attachinary
4
+ module Extension
5
+ module Base
6
+
7
+ def has_attachment(scope, options={})
8
+ attachinary options.merge(single: true, scope: scope)
9
+ end
10
+
11
+ def has_attachments(scope, options={})
12
+ attachinary options.merge(single: false, scope: scope)
13
+ end
14
+
15
+ private
16
+ def attachinary(options)
17
+ options = Attachinary::Utils.process_options(options)
18
+
19
+ attachinary_orm_definition(options)
20
+
21
+ # attr_accessible :photo
22
+ # attr_accessible :images
23
+ attr_accessible :"#{options[:scope]}" if options[:accessible]
24
+
25
+ # def photo?
26
+ # photo.present?
27
+ # end
28
+ # def images?
29
+ # images.present?
30
+ # end
31
+ define_method :"#{options[:scope]}?" do
32
+ send(:"#{options[:scope]}").present?
33
+ end
34
+
35
+ # def photo_metadata
36
+ # options
37
+ # end
38
+ define_method :"#{options[:scope]}_metadata" do
39
+ options
40
+ end
41
+
42
+ if options[:single]
43
+ # def photo_url=(url)
44
+ # ...
45
+ # end
46
+ define_method :"#{options[:scope]}_url=" do |url|
47
+ send(:"#{options[:scope]}=", Cloudinary::Uploader.upload(url))
48
+ end
49
+
50
+ else
51
+ # def image_urls=(urls)
52
+ # ...
53
+ # end
54
+ define_method :"#{options[:singular]}_urls=" do |urls|
55
+ send(:"#{options[:scope]}=", urls.map { |url| Cloudinary::Uploader.upload(url) })
56
+ end
57
+ end
58
+
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -1,4 +1,5 @@
1
1
  require_relative 'file_mixin'
2
+ require_relative 'base_extension'
2
3
  require_relative 'mongoid/extension'
3
4
  require_relative 'mongoid/file'
4
5
 
@@ -1,93 +1,43 @@
1
+ require 'attachinary/utils'
2
+
1
3
  module Attachinary
2
4
  module Extension
5
+ include Base
3
6
 
4
- def has_attachment(scope, options={})
5
- options[:single] = true
6
- attachinary scope, options
7
- end
8
-
9
- def has_attachments(scope, options={})
10
- options[:single] = false
11
- attachinary scope, options
12
- end
13
-
14
- def attachinary(scope, options)
15
- options.reverse_merge!({
16
- accessible: true
17
- })
18
-
19
- if options[:single]
20
- singular = scope.to_s
21
- plural = scope.to_s.pluralize
22
- else
23
- plural = scope.to_s
24
- singular = scope.to_s.singularize
25
- end
26
-
7
+ def attachinary_orm_definition(options)
27
8
  if options[:single]
28
9
  # embeds_on :photo, ...
29
- embeds_one :"#{scope}",
10
+ embeds_one :"#{options[:scope]}",
30
11
  as: :attachinariable,
31
12
  class_name: '::Attachinary::File',
32
13
  cascade_callbacks: true
33
14
  else
34
15
  # embeds_many :images, ...
35
- embeds_many :"#{scope}",
16
+ embeds_many :"#{options[:scope]}",
36
17
  as: :attachinariable,
37
18
  class_name: '::Attachinary::File',
38
19
  cascade_callbacks: true
39
20
  end
40
21
 
41
-
42
- # attr_accessible :photo
43
- # attr_accessible :images
44
- attr_accessible :"#{scope}" if options[:accessible]
45
-
46
- # def photo?
47
- # photo.present?
48
- # end
49
- # def images?
50
- # images.present?
51
- # end
52
- define_method :"#{scope}?" do
53
- send(:"#{scope}").present?
54
- end
55
-
56
- # def photo_metadata
57
- # options[:scope] = 'photo'
58
- # options[:maximum] = 1 if options[:single]
59
- # options
60
- # end
61
- define_method :"#{scope}_metadata" do
62
- options[:scope] = scope
63
- options[:maximum] = 1 if options[:single]
64
- options
65
- end
66
-
67
-
68
22
  # alias_method :orig_photo=, :photo=
69
- # def photo=(arg)
70
- # arg = nil if arg.empty?
71
- # if arg.is_a?(String)
72
- # files = ... parse JSON and MAP to array of Attachinary::File ..
73
- # files = files[0] if options[:singular]
74
- # super files
23
+ # def photo=(input)
24
+ # input = Attachinary::Utils.process_input(input)
25
+ # if input.nil?
26
+ # self.orig_photo = nil
75
27
  # else
76
- # super
28
+ # files = [input].flatten
29
+ # self.orig_photo = options[:single] ? files[0] : files
77
30
  # end
78
31
  # end
79
- alias_method "orig_#{scope}=", "#{scope}="
80
- define_method "#{scope}=" do |arg|
81
- arg = nil if arg.respond_to?(:empty?) && arg.empty?
82
-
83
- if arg.is_a?(String)
84
- files = [JSON.parse(arg)].flatten.map do |data|
85
- data = data.slice(*Attachinary::File.attr_accessible[:default].to_a)
86
- Attachinary::File.new(data)
87
- end
88
- send("orig_#{scope}=", options[:single] ? files[0] : files)
32
+ # end
33
+ alias_method "orig_#{options[:scope]}=", "#{options[:scope]}="
34
+ define_method "#{options[:scope]}=" do |input|
35
+ input = Attachinary::Utils.process_input(input)
36
+ if input.nil?
37
+ send("orig_#{options[:scope]}=", nil)
89
38
  else
90
- send("orig_#{scope}=", arg)
39
+ files = [input].flatten
40
+ send("orig_#{options[:scope]}=", options[:single] ? files[0] : files)
91
41
  end
92
42
  end
93
43
  end
@@ -0,0 +1,54 @@
1
+ module Attachinary
2
+ module Utils
3
+
4
+ def self.process_json(json, scope=nil)
5
+ [JSON.parse(json)].flatten.map do |data|
6
+ process_hash(data, scope)
7
+ end
8
+ end
9
+
10
+ def self.process_hash(hash, scope=nil)
11
+ file = Attachinary::File.new hash.slice(*Attachinary::File.attr_accessible[:default].to_a)
12
+ file.scope = scope.to_s if scope && file.respond_to?(:scope=)
13
+ file
14
+ end
15
+
16
+
17
+ def self.process_input(input, scope=nil)
18
+ case input
19
+ when :blank?.to_proc
20
+ nil
21
+ when lambda { |e| e.respond_to?(:read) }
22
+ process_hash Cloudinary::Uploader.upload(input), scope
23
+ when String
24
+ process_json(input, scope)
25
+ when Hash
26
+ process_hash(input, scope)
27
+ when Array
28
+ input = input.map{ |el| process_input(el, scope) }.flatten.compact
29
+ input = nil if input.empty?
30
+ input
31
+ else
32
+ input
33
+ end
34
+ end
35
+
36
+ def self.process_options(options)
37
+ options = options.reverse_merge({
38
+ accessible: true
39
+ })
40
+ options[:maximum] = 1 if options[:single]
41
+
42
+ if options[:single]
43
+ options[:singular] = options[:scope].to_s
44
+ options[:plural] = options[:scope].to_s.pluralize
45
+ else
46
+ options[:plural] = options[:scope].to_s
47
+ options[:singular] = options[:scope].to_s.singularize
48
+ end
49
+
50
+ options
51
+ end
52
+
53
+ end
54
+ end
@@ -1,3 +1,3 @@
1
1
  module Attachinary
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -42,6 +42,8 @@ module Attachinary
42
42
  options[:html][:accept] = accept.join(',') unless accept.empty?
43
43
  end
44
44
 
45
+ options[:html][:multiple] = true unless options[:attachinary][:single]
46
+
45
47
  options[:html][:data] ||= {}
46
48
  options[:html][:data][:attachinary] = options[:attachinary] || {}
47
49
  options[:html][:data][:attachinary][:files] = [model.send(relation)].compact.flatten
@@ -0,0 +1,28 @@
1
+ namespace :attachinary do
2
+
3
+ desc 'fetches required jQuery File Upload files from github'
4
+ task :fetch_fileupload do
5
+ require 'open-uri'
6
+ require 'uri'
7
+
8
+ urls = %w[
9
+ https://raw.github.com/blueimp/jQuery-File-Upload/master/js/vendor/jquery.ui.widget.js
10
+ https://raw.github.com/blueimp/jQuery-File-Upload/master/js/jquery.iframe-transport.js
11
+ https://raw.github.com/blueimp/jQuery-File-Upload/master/js/jquery.fileupload.js
12
+ ]
13
+
14
+ dir = Rails.root.join("vendor/assets/javascripts")
15
+ FileUtils.mkdir_p dir.to_s
16
+
17
+ urls.each do |url|
18
+ uri = URI.parse(url)
19
+ filename = uri.path.split('/').last
20
+ puts "Getting #{filename}"
21
+
22
+ dest = File.open(dir.join(filename), "w")
23
+ dest.puts open(url).read
24
+ dest.close
25
+ end
26
+ end
27
+
28
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attachinary
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.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: 2012-10-12 00:00:00.000000000 Z
12
+ date: 2012-10-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70157177562020 !ruby/object:Gem::Requirement
16
+ requirement: &70366625912520 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.2'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70157177562020
24
+ version_requirements: *70366625912520
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: cloudinary
27
- requirement: &70157177561080 !ruby/object:Gem::Requirement
27
+ requirement: &70366625911980 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 1.0.40
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *70157177561080
35
+ version_requirements: *70366625911980
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: sqlite3
38
- requirement: &70157177560440 !ruby/object:Gem::Requirement
38
+ requirement: &70366625911560 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70157177560440
46
+ version_requirements: *70366625911560
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rspec-rails
49
- requirement: &70157177559380 !ruby/object:Gem::Requirement
49
+ requirement: &70366625910780 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ~>
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '2.5'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70157177559380
57
+ version_requirements: *70366625910780
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: valid_attribute
60
- requirement: &70157177558600 !ruby/object:Gem::Requirement
60
+ requirement: &70366625910340 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70157177558600
68
+ version_requirements: *70366625910340
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: capybara
71
- requirement: &70157177557880 !ruby/object:Gem::Requirement
71
+ requirement: &70366625909740 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,21 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70157177557880
79
+ version_requirements: *70366625909740
80
+ - !ruby/object:Gem::Dependency
81
+ name: capybara-webkit
82
+ requirement: &70366625909100 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *70366625909100
80
91
  - !ruby/object:Gem::Dependency
81
92
  name: factory_girl_rails
82
- requirement: &70157177557120 !ruby/object:Gem::Requirement
93
+ requirement: &70366625908420 !ruby/object:Gem::Requirement
83
94
  none: false
84
95
  requirements:
85
96
  - - ~>
@@ -87,10 +98,10 @@ dependencies:
87
98
  version: '3.0'
88
99
  type: :development
89
100
  prerelease: false
90
- version_requirements: *70157177557120
101
+ version_requirements: *70366625908420
91
102
  - !ruby/object:Gem::Dependency
92
103
  name: launchy
93
- requirement: &70157177556460 !ruby/object:Gem::Requirement
104
+ requirement: &70366625907260 !ruby/object:Gem::Requirement
94
105
  none: false
95
106
  requirements:
96
107
  - - ! '>='
@@ -98,10 +109,10 @@ dependencies:
98
109
  version: '0'
99
110
  type: :development
100
111
  prerelease: false
101
- version_requirements: *70157177556460
112
+ version_requirements: *70366625907260
102
113
  - !ruby/object:Gem::Dependency
103
114
  name: database_cleaner
104
- requirement: &70157177555700 !ruby/object:Gem::Requirement
115
+ requirement: &70366625906760 !ruby/object:Gem::Requirement
105
116
  none: false
106
117
  requirements:
107
118
  - - ! '>='
@@ -109,10 +120,10 @@ dependencies:
109
120
  version: '0'
110
121
  type: :development
111
122
  prerelease: false
112
- version_requirements: *70157177555700
123
+ version_requirements: *70366625906760
113
124
  - !ruby/object:Gem::Dependency
114
125
  name: guard-rspec
115
- requirement: &70157177555260 !ruby/object:Gem::Requirement
126
+ requirement: &70366625906080 !ruby/object:Gem::Requirement
116
127
  none: false
117
128
  requirements:
118
129
  - - ! '>='
@@ -120,7 +131,7 @@ dependencies:
120
131
  version: '0'
121
132
  type: :development
122
133
  prerelease: false
123
- version_requirements: *70157177555260
134
+ version_requirements: *70366625906080
124
135
  description: Attachments handler for Rails that uses Cloudinary for storage.
125
136
  email:
126
137
  - milovan.zogovic@gmail.com
@@ -130,7 +141,6 @@ extra_rdoc_files: []
130
141
  files:
131
142
  - app/controllers/attachinary/application_controller.rb
132
143
  - app/controllers/attachinary/cors_controller.rb
133
- - app/controllers/attachinary/files_controller.rb
134
144
  - config/routes.rb
135
145
  - db/migrate/20120612112526_create_attachinary_tables.rb
136
146
  - lib/assets/javascripts/attachinary.js.coffee
@@ -139,14 +149,17 @@ files:
139
149
  - lib/attachinary/orm/active_record/extension.rb
140
150
  - lib/attachinary/orm/active_record/file.rb
141
151
  - lib/attachinary/orm/active_record.rb
152
+ - lib/attachinary/orm/base_extension.rb
142
153
  - lib/attachinary/orm/file_mixin.rb
143
154
  - lib/attachinary/orm/mongoid/extension.rb
144
155
  - lib/attachinary/orm/mongoid/file.rb
145
156
  - lib/attachinary/orm/mongoid.rb
146
157
  - lib/attachinary/simple_form.rb
158
+ - lib/attachinary/utils.rb
147
159
  - lib/attachinary/version.rb
148
160
  - lib/attachinary/view_helpers.rb
149
161
  - lib/attachinary.rb
162
+ - lib/tasks/attachinary.rake
150
163
  - MIT-LICENSE
151
164
  - Rakefile
152
165
  - README.md
@@ -164,7 +177,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
177
  version: '0'
165
178
  segments:
166
179
  - 0
167
- hash: -1210217158710923500
180
+ hash: -3737432047722910225
168
181
  required_rubygems_version: !ruby/object:Gem::Requirement
169
182
  none: false
170
183
  requirements:
@@ -173,11 +186,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
186
  version: '0'
174
187
  segments:
175
188
  - 0
176
- hash: -1210217158710923500
189
+ hash: -3737432047722910225
177
190
  requirements: []
178
191
  rubyforge_project:
179
192
  rubygems_version: 1.8.11
180
193
  signing_key:
181
194
  specification_version: 3
182
- summary: attachinary-1.1.0
195
+ summary: attachinary-1.2.0
183
196
  test_files: []
@@ -1,21 +0,0 @@
1
- module Attachinary
2
- class FilesController < Attachinary::ApplicationController
3
- respond_to :json
4
-
5
- def callback
6
- success = valid_cloudinary_response?
7
- if success && !params[:error].present?
8
- @file = File.create(file_params)
9
- respond_with @file
10
- else
11
- render nothing: true, status: 400
12
- end
13
- end
14
-
15
- private
16
- def file_params
17
- request.query_parameters.slice(:public_id, :version, :width, :height, :format, :resource_type, :scope)
18
- end
19
-
20
- end
21
- end