fileclip 0.1.0 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +18 -0
- data/.rspec +1 -0
- data/.ruby-gemset +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +10 -0
- data/Gemfile.lock +22 -3
- data/README.md +33 -6
- data/TODO.md +28 -0
- data/fileclip.gemspec +14 -27
- data/lib/fileclip.rb +55 -50
- data/lib/fileclip/action_view/helpers.rb +69 -0
- data/lib/fileclip/configuration.rb +42 -0
- data/lib/fileclip/engine.rb +11 -0
- data/lib/fileclip/jobs/resque.rb +11 -0
- data/lib/fileclip/railtie.rb +11 -0
- data/lib/fileclip/validators.rb +24 -0
- data/lib/fileclip/version.rb +1 -1
- data/spec/fileclip/configuration_spec.rb +17 -0
- data/spec/fileclip/engine_spec.rb +16 -0
- data/spec/fileclip/railtie_spec.rb +11 -0
- data/spec/fileclip/validators_spec.rb +57 -0
- data/spec/fileclip_spec.rb +214 -0
- data/spec/schema.rb +10 -0
- data/spec/spec_helper.rb +34 -0
- data/vendor/assets/javascripts/fileclip.js.coffee.erb +57 -0
- metadata +47 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f40a90259ac27e876f6cf56f326ab18279b476f5
|
4
|
+
data.tar.gz: decfde8e4d6ac8580cb2d86ec1c3394f37ca9333
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b1f34aef2c3516b4db6e14ae09ab4c6d1a08ade820374c71b9e64d33224b7336028f8104d4aa435095a367f6660619a174d92df3c65cc967cd3bf1d431aee96
|
7
|
+
data.tar.gz: 5b1c57b57955c4b3253dd8362d18b6c9b30ef0df73ef010cd3888ed9303ee59c5edb5d6996c108ef29d7fb4715bd4ef283f95caf843189788121b4b9c95d0b21
|
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.ruby-gemset
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
fileclip
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0-p247
|
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
fileclip (0.
|
4
|
+
fileclip (0.2.1)
|
5
5
|
paperclip
|
6
|
-
paperclip (>= 3.
|
6
|
+
paperclip (>= 3.5.1)
|
7
7
|
railties (>= 3.0)
|
8
8
|
rest-client
|
9
9
|
|
@@ -53,8 +53,9 @@ GEM
|
|
53
53
|
mime-types (~> 1.16)
|
54
54
|
treetop (~> 1.4.8)
|
55
55
|
mime-types (1.23)
|
56
|
+
mono_logger (1.1.0)
|
56
57
|
multi_json (1.7.7)
|
57
|
-
paperclip (3.5.
|
58
|
+
paperclip (3.5.1)
|
58
59
|
activemodel (>= 3.0.0)
|
59
60
|
activesupport (>= 3.0.0)
|
60
61
|
cocaine (~> 0.5.0)
|
@@ -63,6 +64,8 @@ GEM
|
|
63
64
|
rack (1.4.5)
|
64
65
|
rack-cache (1.2)
|
65
66
|
rack (>= 0.4)
|
67
|
+
rack-protection (1.5.0)
|
68
|
+
rack
|
66
69
|
rack-ssl (1.3.3)
|
67
70
|
rack
|
68
71
|
rack-test (0.6.2)
|
@@ -85,6 +88,15 @@ GEM
|
|
85
88
|
rake (10.1.0)
|
86
89
|
rdoc (3.12.2)
|
87
90
|
json (~> 1.4)
|
91
|
+
redis (3.0.4)
|
92
|
+
redis-namespace (1.3.0)
|
93
|
+
redis (~> 3.0.0)
|
94
|
+
resque (1.24.1)
|
95
|
+
mono_logger (~> 1.0)
|
96
|
+
multi_json (~> 1.0)
|
97
|
+
redis-namespace (~> 1.2)
|
98
|
+
sinatra (>= 0.9.2)
|
99
|
+
vegas (~> 0.1.2)
|
88
100
|
rest-client (1.6.7)
|
89
101
|
mime-types (>= 1.16)
|
90
102
|
rspec (2.14.1)
|
@@ -95,6 +107,10 @@ GEM
|
|
95
107
|
rspec-expectations (2.14.0)
|
96
108
|
diff-lcs (>= 1.1.3, < 2.0)
|
97
109
|
rspec-mocks (2.14.1)
|
110
|
+
sinatra (1.4.3)
|
111
|
+
rack (~> 1.4)
|
112
|
+
rack-protection (~> 1.4)
|
113
|
+
tilt (~> 1.3, >= 1.3.4)
|
98
114
|
sprockets (2.2.2)
|
99
115
|
hike (~> 1.2)
|
100
116
|
multi_json (~> 1.0)
|
@@ -107,6 +123,8 @@ GEM
|
|
107
123
|
polyglot
|
108
124
|
polyglot (>= 0.3.1)
|
109
125
|
tzinfo (0.3.37)
|
126
|
+
vegas (0.1.11)
|
127
|
+
rack (>= 1.0.0)
|
110
128
|
|
111
129
|
PLATFORMS
|
112
130
|
ruby
|
@@ -114,5 +132,6 @@ PLATFORMS
|
|
114
132
|
DEPENDENCIES
|
115
133
|
fileclip!
|
116
134
|
rails (= 3.2.14)
|
135
|
+
resque
|
117
136
|
rspec
|
118
137
|
sqlite3
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
FileClip
|
1
|
+
FileClip [![Build Status](https://travis-ci.org/ScotterC/fileclip.png?branch=master)](https://travis-ci.org/ScotterC/fileclip)
|
2
2
|
========
|
3
3
|
|
4
4
|
A FilePicker / PaperClip mashup. Use Filepicker for uploads and paperclip to process them.
|
@@ -28,6 +28,22 @@ end
|
|
28
28
|
# config/initializers/fileclip.rb
|
29
29
|
FileClip.configure do |config|
|
30
30
|
config.filepicker_key = 'XXXXXXXXXXXXXXXXXXX'
|
31
|
+
config.services = ["COMPUTER", "DROPBOX"] # Defaults to ["COMPUTER"]
|
32
|
+
config.max_size = 20 # Megabytes, defaults to 20
|
33
|
+
config.storage_path = "/assets/" # Defaults to "/fileclip/"
|
34
|
+
config.mime_types = "images/jpeg" # Defaults to "images/*"
|
35
|
+
config.file_access = "private" # Defaults to "public"
|
36
|
+
end
|
37
|
+
````
|
38
|
+
|
39
|
+
### In Model
|
40
|
+
````
|
41
|
+
# models/image.rb
|
42
|
+
class Image << ActiveRecord::Base
|
43
|
+
|
44
|
+
has_attached_file :attachment
|
45
|
+
|
46
|
+
fileclip :attachment
|
31
47
|
end
|
32
48
|
````
|
33
49
|
|
@@ -48,10 +64,21 @@ end
|
|
48
64
|
````
|
49
65
|
|
50
66
|
#### Current FilePicker options hardcoded
|
51
|
-
* mimetypes are image/*
|
52
67
|
* container modal
|
53
|
-
* service Computer
|
54
|
-
* maxsize is 20 mb
|
55
68
|
* location is S3
|
56
|
-
|
57
|
-
|
69
|
+
|
70
|
+
Features:
|
71
|
+
* Unobtrusive. Normal paperclip uploads still work
|
72
|
+
|
73
|
+
|
74
|
+
#### Gotchas
|
75
|
+
|
76
|
+
This paperclip validation will return errors even if filepicker url is present:
|
77
|
+
````
|
78
|
+
validates :attachment, :attachment_presence => true
|
79
|
+
````
|
80
|
+
|
81
|
+
However, this will work fine. It'll skip the attachment check if a filepicker url is present and validate if it's not.
|
82
|
+
````
|
83
|
+
validates_attachment :attachment, :size => { :in => 0..1000 }, :presence => true
|
84
|
+
````
|
data/TODO.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
TODO:
|
2
|
+
|
3
|
+
Backend:
|
4
|
+
* handle multiple attachments on a model, prefix column with attachment name
|
5
|
+
* create generator for migration
|
6
|
+
* create generator for intializer
|
7
|
+
* Normalize filenames
|
8
|
+
* Change keys as an option. defaults to filepicker_url
|
9
|
+
|
10
|
+
Frontend:
|
11
|
+
* Allow overriding of filepicker options
|
12
|
+
* Fileclip link to automatically set fields and call it
|
13
|
+
* link should act like a normal link helper
|
14
|
+
* Minimal amount of JS
|
15
|
+
* Loader for filepicker js only if needed
|
16
|
+
* Eliminate need for jQuery
|
17
|
+
* make it a form builder function that can accept a different url name
|
18
|
+
|
19
|
+
Extra features:
|
20
|
+
* Work with Delayed Paperclip
|
21
|
+
* Work with Resque
|
22
|
+
* Work with DelayedJob
|
23
|
+
* Work with Sidekiq
|
24
|
+
* Fallback to filepicker url if paperclip url doesn't exist
|
25
|
+
* Filepicker converts to match paperclip styles
|
26
|
+
* Configure Filepicker options
|
27
|
+
* FilePicker droppane support
|
28
|
+
|
data/fileclip.gemspec
CHANGED
@@ -2,41 +2,28 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
2
2
|
require "fileclip/version"
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
|
-
s.name
|
6
|
-
s.version
|
5
|
+
s.name = "fileclip"
|
6
|
+
s.version = FileClip::VERSION
|
7
|
+
s.platform = Gem::Platform::RUBY
|
8
|
+
s.authors = ["Scott Carleton"]
|
9
|
+
s.summary = "A FilePicker / PaperClip mashup."
|
10
|
+
s.description = "A FilePicker / PaperClip mashup. Use Filepicker for uploads and paperclip to process them."
|
11
|
+
s.email = "scott@artsicle.com"
|
12
|
+
s.license = "MIT"
|
13
|
+
s.files = `git ls-files`.split("\n")
|
14
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
15
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
16
|
+
s.homepage = "http://github.com/ScotterC/fileclip"
|
7
17
|
|
8
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
9
|
-
s.authors = ["Scott Carleton"]
|
10
|
-
s.date = "2013-07-26"
|
11
|
-
s.description = "A FilePicker / PaperClip mashup. Use Filepicker for uploads and paperclip to process them."
|
12
|
-
s.email = "scott@artsicle.com"
|
13
|
-
s.extra_rdoc_files = [
|
14
|
-
"LICENSE",
|
15
|
-
"README.md"
|
16
|
-
]
|
17
|
-
s.files = [
|
18
|
-
".document",
|
19
|
-
"Gemfile",
|
20
|
-
"Gemfile.lock",
|
21
|
-
"LICENSE",
|
22
|
-
"README.md",
|
23
|
-
"Rakefile",
|
24
|
-
"fileclip.gemspec",
|
25
|
-
"lib/fileclip.rb",
|
26
|
-
"lib/fileclip/version.rb"
|
27
|
-
]
|
28
|
-
s.homepage = "http://github.com/ScotterC/fileclip"
|
29
|
-
s.licenses = ["MIT"]
|
30
|
-
s.require_paths = ["lib"]
|
31
18
|
s.rubygems_version = "2.0.3"
|
32
|
-
s.summary = "A FilePicker / PaperClip mashup."
|
33
19
|
|
34
|
-
s.add_dependency 'paperclip', [">= 3.
|
20
|
+
s.add_dependency 'paperclip', [">= 3.5.1"]
|
35
21
|
s.add_dependency 'rest-client'
|
36
22
|
|
37
23
|
s.add_development_dependency "rspec"
|
38
24
|
s.add_development_dependency 'sqlite3'
|
39
25
|
s.add_development_dependency "rails"
|
26
|
+
s.add_development_dependency 'resque'
|
40
27
|
s.add_runtime_dependency(%q<railties>, [">= 3.0"])
|
41
28
|
|
42
29
|
s.add_runtime_dependency "paperclip"
|
data/lib/fileclip.rb
CHANGED
@@ -1,75 +1,66 @@
|
|
1
|
-
# TODO
|
2
|
-
#
|
3
|
-
# Allowance for normal attached images through file_field:
|
4
|
-
# only do attachment validation if it's there if remote url is not present
|
5
|
-
# only do process_in_background if remote_url is not present
|
6
|
-
#
|
7
|
-
# Expose FilePicked to all classes that have Paperclip images
|
8
|
-
#
|
9
|
-
# Handle multiple attachments in single model
|
10
|
-
# Crux of this is finding the name of the attachment we're dealing with
|
11
|
-
#
|
12
|
-
# Fallback if none are defined
|
13
|
-
#
|
14
|
-
# What can we separate out into it's own class
|
15
|
-
# What should be a part of attachment
|
16
|
-
#
|
17
|
-
# Migration generator
|
18
|
-
#
|
19
|
-
# Configuration to take Filepicker API key
|
20
|
-
#
|
21
|
-
# Javascript inclusion
|
22
|
-
#
|
23
|
-
# Add delayed aspect
|
24
|
-
#
|
25
|
-
# Queue job for image assignment
|
26
1
|
require 'fileclip/configuration'
|
27
2
|
require 'fileclip/action_view/helpers'
|
3
|
+
require 'fileclip/validators'
|
28
4
|
require 'fileclip/engine'
|
29
5
|
require 'fileclip/railtie'
|
6
|
+
require 'fileclip/jobs/resque'
|
30
7
|
require 'rest-client'
|
31
8
|
|
32
9
|
module FileClip
|
33
10
|
|
11
|
+
mattr_accessor :change_keys
|
12
|
+
|
13
|
+
def self.change_keys
|
14
|
+
@@change_keys ||= [:filepicker_url]
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.delayed?
|
18
|
+
defined?(DelayedPaperclip)
|
19
|
+
# TODO: replace with checking for delayed options?
|
20
|
+
end
|
21
|
+
|
22
|
+
class << self
|
23
|
+
|
24
|
+
def resque_enabled?
|
25
|
+
!!(defined? Resque)
|
26
|
+
end
|
27
|
+
|
28
|
+
def process(klass, instance_id)
|
29
|
+
klass.constantize.find(instance_id).process_from_filepicker
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
34
|
module Glue
|
35
35
|
def self.included(base)
|
36
|
-
base.extend
|
36
|
+
base.extend ClassMethods
|
37
|
+
base.extend FileClip::Validators::HelperMethods
|
37
38
|
base.send :include, InstanceMethods
|
38
|
-
base.add_callbacks
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
module ClassMethods
|
43
|
-
def
|
43
|
+
def fileclip(name)
|
44
44
|
attr_accessible :filepicker_url
|
45
|
+
after_commit :update_from_filepicker!
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
# else
|
49
|
-
# after_save :update_from_filepicker!
|
50
|
-
# end
|
47
|
+
set_fileclipped(name)
|
48
|
+
end
|
51
49
|
|
52
|
-
|
53
|
-
|
54
|
-
# Save without this particular vaildation
|
50
|
+
def fileclipped
|
51
|
+
@attachment_name
|
55
52
|
end
|
56
53
|
|
57
|
-
def
|
58
|
-
@
|
59
|
-
attachment_definitions
|
60
|
-
elsif Paperclip::VERSION == "3.5.0"
|
61
|
-
Paperclip::Tasks::Attachments.definitions_for(self)
|
62
|
-
else
|
63
|
-
Paperclip::AttachmentRegistry.definitions_for(self)
|
64
|
-
end
|
54
|
+
def set_fileclipped(name)
|
55
|
+
@attachment_name = name
|
65
56
|
end
|
66
57
|
end
|
67
58
|
|
68
59
|
module InstanceMethods
|
69
60
|
|
70
|
-
# TODO: can't handle multiples, just
|
61
|
+
# TODO: can't handle multiples, just given
|
71
62
|
def attachment_name
|
72
|
-
@attachment_name ||= self.class.
|
63
|
+
@attachment_name ||= self.class.fileclipped
|
73
64
|
end
|
74
65
|
|
75
66
|
def attachment_object
|
@@ -77,14 +68,28 @@ module FileClip
|
|
77
68
|
end
|
78
69
|
|
79
70
|
def update_from_filepicker!
|
80
|
-
|
71
|
+
if update_from_filepicker?
|
72
|
+
if FileClip.resque_enabled?
|
73
|
+
# TODO: self.class.name is webrick ???
|
74
|
+
delay_process!
|
75
|
+
else
|
76
|
+
process_from_filepicker
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def delay_process!
|
82
|
+
update_column(:"#{attachment_name}_processing", true) if FileClip.delayed?
|
83
|
+
Resque.enqueue(FileClip::Jobs::Resque, self.class.name, self.id)
|
81
84
|
end
|
82
85
|
|
83
86
|
def process_from_filepicker
|
84
87
|
self.class.skip_callback :commit, :after, :update_from_filepicker!
|
85
88
|
self.send(:"#{attachment_name}=", URI.parse(filepicker_url))
|
86
89
|
self.set_metadata
|
90
|
+
self.attachment_object.save_with_prepare_enqueueing if FileClip.delayed?
|
87
91
|
self.save
|
92
|
+
self.enqueue_delayed_processing if FileClip.delayed?
|
88
93
|
self.class.set_callback :commit, :after, :update_from_filepicker!
|
89
94
|
end
|
90
95
|
|
@@ -97,7 +102,7 @@ module FileClip
|
|
97
102
|
end
|
98
103
|
|
99
104
|
def update_from_filepicker?
|
100
|
-
|
105
|
+
fileclip_previously_changed? &&
|
101
106
|
filepicker_url.present? &&
|
102
107
|
!filepicker_only?
|
103
108
|
end
|
@@ -106,8 +111,8 @@ module FileClip
|
|
106
111
|
!filepicker_url.present?
|
107
112
|
end
|
108
113
|
|
109
|
-
def
|
110
|
-
previous_changes.keys.
|
114
|
+
def fileclip_previously_changed?
|
115
|
+
!(previous_changes.keys.map(&:to_sym) & FileClip.change_keys).empty?
|
111
116
|
end
|
112
117
|
|
113
118
|
# To be overridden in model if specific logic for not
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module FileClip
|
2
|
+
module ActionView
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
# Include relevant JS
|
6
|
+
def fileclip_js_include_tag
|
7
|
+
javascript_include_tag "//api.filepicker.io/v1/filepicker.js", "fileclip"
|
8
|
+
end
|
9
|
+
|
10
|
+
# Options
|
11
|
+
# js to activate it on the spot, defaults to true
|
12
|
+
# class to add css classes
|
13
|
+
def link_to_fileclip(text, form_object, options={}, &block)
|
14
|
+
form_object, options = text, form_object if block_given?
|
15
|
+
|
16
|
+
id = fileclip_id(form_object)
|
17
|
+
classes = fileclip_css_classes(options[:class])
|
18
|
+
|
19
|
+
# Got to be a cleaner way to do this
|
20
|
+
link = if block_given?
|
21
|
+
link_to "javascript:void(0)", class: classes, id: id, &block
|
22
|
+
else
|
23
|
+
link_to text, "javascript:void(0)", class: classes, id: id
|
24
|
+
end
|
25
|
+
|
26
|
+
fileclip_link_builder(link, form_object, options, id)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Add js-fileclip to existing classes
|
30
|
+
def fileclip_css_classes(given_classes)
|
31
|
+
return "js-fileclip" if given_classes.nil?
|
32
|
+
css_classes = [].push(given_classes.split)
|
33
|
+
css_classes << "js-fileclip"
|
34
|
+
css_classes
|
35
|
+
end
|
36
|
+
|
37
|
+
# Object id for link
|
38
|
+
def fileclip_id(form_object)
|
39
|
+
new_object = form_object.object
|
40
|
+
attachment_name = new_object.attachment_name
|
41
|
+
"#{attachment_name}_#{new_object.object_id}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return empty tag if it's nil or true
|
45
|
+
def activation(js, id)
|
46
|
+
return javascript_tag unless js.nil? || js
|
47
|
+
|
48
|
+
javascript_tag("(function() {
|
49
|
+
(new FileClip).button('##{id}');
|
50
|
+
})();")
|
51
|
+
end
|
52
|
+
|
53
|
+
# Options
|
54
|
+
# Activate (defaults to true) to set own javascript
|
55
|
+
def fileclip_link_builder(link, form_object, options, id)
|
56
|
+
# Get attachment name
|
57
|
+
attachment_name = form_object.object.attachment_name
|
58
|
+
|
59
|
+
js = activation(options[:js], id)
|
60
|
+
|
61
|
+
js + link +
|
62
|
+
form_object.hidden_field(:filepicker_url,
|
63
|
+
class: "js-fileclip_url",
|
64
|
+
data: { type: attachment_name })
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module FileClip
|
2
|
+
class Configuration
|
3
|
+
attr_writer :filepicker_key, :services,
|
4
|
+
:max_size, :storage_path,
|
5
|
+
:mime_types, :file_access
|
6
|
+
|
7
|
+
def filepicker_key
|
8
|
+
@filepicker_key or raise "Set Filepicker api_key"
|
9
|
+
end
|
10
|
+
|
11
|
+
def services
|
12
|
+
@services or ["COMPUTER"]
|
13
|
+
end
|
14
|
+
|
15
|
+
def max_size
|
16
|
+
@max_size or 20
|
17
|
+
end
|
18
|
+
|
19
|
+
def storage_path
|
20
|
+
@storage_path or "/fileclip/"
|
21
|
+
end
|
22
|
+
|
23
|
+
def mime_types
|
24
|
+
@mime_types or "image/*"
|
25
|
+
end
|
26
|
+
|
27
|
+
def file_access
|
28
|
+
@file_access or "public"
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
class << self
|
34
|
+
def configure
|
35
|
+
yield configuration
|
36
|
+
end
|
37
|
+
|
38
|
+
def configuration
|
39
|
+
@configuration ||= FileClip::Configuration.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module FileClip
|
2
|
+
class Railtie
|
3
|
+
# Glue includes FileClip into ActiveRecord
|
4
|
+
# TODO: only include it in models that have paperclip attachments
|
5
|
+
# Will require restart of server for it to pick up the class on edit
|
6
|
+
def self.insert
|
7
|
+
::ActiveRecord::Base.send(:include, FileClip::Glue)
|
8
|
+
::ActionView::Base.send(:include, FileClip::ActionView::Helpers)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module FileClip
|
2
|
+
module Validators
|
3
|
+
|
4
|
+
module HelperMethods
|
5
|
+
|
6
|
+
def validates_attachment_content_type(*attr_names)
|
7
|
+
attr_names.last.merge!({ :if => :filepicker_url_not_present? })
|
8
|
+
super(*attr_names)
|
9
|
+
end
|
10
|
+
|
11
|
+
def validates_attachment_presence(*attr_names)
|
12
|
+
attr_names.last.merge!({ :if => :filepicker_url_not_present? })
|
13
|
+
super(*attr_names)
|
14
|
+
end
|
15
|
+
|
16
|
+
def validates_attachment_size(*attr_names)
|
17
|
+
attr_names.last.merge!({ :if => :filepicker_url_not_present? })
|
18
|
+
super(*attr_names)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
data/lib/fileclip/version.rb
CHANGED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FileClip::Configuration do
|
4
|
+
|
5
|
+
describe "filepicker_key" do
|
6
|
+
it "should be nil to start" do
|
7
|
+
expect { FileClip.configuration.filepicker_key }.to raise_error
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should be set by block" do
|
11
|
+
FileClip.configure do |config|
|
12
|
+
config.filepicker_key = "XXX-XXX"
|
13
|
+
end
|
14
|
+
FileClip.configuration.filepicker_key.should == "XXX-XXX"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rails/initializable'
|
3
|
+
|
4
|
+
|
5
|
+
describe FileClip::Rails::Engine do
|
6
|
+
|
7
|
+
describe "include on initialzation" do
|
8
|
+
it "should insert fileclip and include view helpers on rails initialzation" do
|
9
|
+
pending
|
10
|
+
FileClip::Railtie.should_receive(:insert)
|
11
|
+
::ActionView::Base.should_receive(:send).with(:include, FileClip::ActionView::Helpers)
|
12
|
+
FileClip::Rails::Engine.run_initializers
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FileClip::Railtie do
|
4
|
+
describe "insert" do
|
5
|
+
it "should include the glue" do
|
6
|
+
ActiveRecord::Base.should_receive(:send).with(:include, FileClip::Glue)
|
7
|
+
ActionView::Base.should_receive(:send).with(:include, FileClip::ActionView::Helpers)
|
8
|
+
FileClip::Railtie.insert
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FileClip::Validators do
|
4
|
+
let(:image) { Image.new }
|
5
|
+
|
6
|
+
describe "validations" do
|
7
|
+
before :each do
|
8
|
+
Image.reset_callbacks(:validate)
|
9
|
+
Image._validators.clear
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "if no filepicker_url" do
|
13
|
+
it "observes attachment presence" do
|
14
|
+
Image.validates :attachment, :attachment_presence => true
|
15
|
+
image.save.should be_false
|
16
|
+
image.errors.first.last.should == "can't be blank"
|
17
|
+
end
|
18
|
+
|
19
|
+
it "observes attachment size" do
|
20
|
+
Image.validates_attachment :attachment, :size => { :in => 0..1000 }, :presence => true
|
21
|
+
image.save.should be_false
|
22
|
+
image.errors.should_not be_empty
|
23
|
+
end
|
24
|
+
|
25
|
+
it "observes attachment content" do
|
26
|
+
Image.validates_attachment :attachment, :content_type => { :content_type => "image/jpg" }, :presence => true
|
27
|
+
image.save.should be_false
|
28
|
+
image.errors.should_not be_empty
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "with filepicker url" do
|
33
|
+
before :each do
|
34
|
+
image.filepicker_url = "image.com"
|
35
|
+
end
|
36
|
+
|
37
|
+
it "observes attachment presence" do
|
38
|
+
pending
|
39
|
+
Image.validates :attachment, :attachment_presence => true
|
40
|
+
image.save.should be_true
|
41
|
+
image.errors.should be_empty
|
42
|
+
end
|
43
|
+
|
44
|
+
it "observes attachment size" do
|
45
|
+
Image.validates_attachment :attachment, :size => { :in => 0..1000 }, :presence => true
|
46
|
+
image.save.should be_true
|
47
|
+
image.errors.should be_empty
|
48
|
+
end
|
49
|
+
|
50
|
+
it "observes attachment content" do
|
51
|
+
Image.validates_attachment :attachment, :content_type => { :content_type => "image/jpg" }, :presence => true
|
52
|
+
image.save.should be_true
|
53
|
+
image.errors.should be_empty
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,214 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe FileClip do
|
4
|
+
let(:filepicker_url) { "https://www.filepicker.io/api/file/ibOold9OQfqbmzgP6D3O" }
|
5
|
+
let(:image) { Image.new }
|
6
|
+
let(:uri) { URI.parse(filepicker_url) }
|
7
|
+
|
8
|
+
describe "change keys" do
|
9
|
+
it "defaults to just fileclip_url" do
|
10
|
+
FileClip.change_keys.should == [:filepicker_url]
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can be added to" do
|
14
|
+
FileClip.change_keys << :file_name
|
15
|
+
FileClip.change_keys.should == [:filepicker_url, :file_name]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".delayed?" do
|
20
|
+
it "returns false without delayed paperclip" do
|
21
|
+
FileClip.delayed?.should be_false
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns true if delayed paperclip exists" do
|
25
|
+
stub_const("DelayedPaperclip", true)
|
26
|
+
FileClip.delayed?.should be_true
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "class_methods" do
|
31
|
+
describe "fileclip" do
|
32
|
+
it "should register callback when called" do
|
33
|
+
Image.fileclip :attachment
|
34
|
+
Image._commit_callbacks.first.filter.should == :update_from_filepicker!
|
35
|
+
end
|
36
|
+
|
37
|
+
it "registers after save callback if commit is not available" do
|
38
|
+
pending # Skipping either callback
|
39
|
+
Image._save_callbacks.first.filter.should_not == :update_from_filepicker!
|
40
|
+
Image.stub(:respond_to?).with(:after_commit).and_return false
|
41
|
+
FileClip::Glue.included(Image)
|
42
|
+
Image._save_callbacks.first.filter.should == :update_from_filepicker!
|
43
|
+
end
|
44
|
+
|
45
|
+
it "adds name to fileclipped" do
|
46
|
+
Image.fileclipped.should == :attachment
|
47
|
+
Image.fileclip(:image)
|
48
|
+
Image.fileclipped.should == :image
|
49
|
+
Image.fileclip(:attachment) # set it back for other tests
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "resque_enabled?" do
|
54
|
+
it "returns false by default" do
|
55
|
+
FileClip.resque_enabled?.should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "returns true if resque exists" do
|
59
|
+
stub_const "Resque", Class.new
|
60
|
+
FileClip.resque_enabled?.should be_true
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "instance methods" do
|
66
|
+
context "#attachment_name" do
|
67
|
+
context "image" do
|
68
|
+
it "should return :attachment" do
|
69
|
+
image.attachment_name.should == :attachment
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "#attachment_object" do
|
75
|
+
context "image" do
|
76
|
+
it "should receive attachment" do
|
77
|
+
image.should_receive(:attachment)
|
78
|
+
image.attachment_object
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
context "#update_from_filepicker!" do
|
84
|
+
|
85
|
+
context "without resque" do
|
86
|
+
before :each do
|
87
|
+
image.filepicker_url = filepicker_url
|
88
|
+
image.stub_chain(:previous_changes, :keys).and_return ["filepicker_url"]
|
89
|
+
end
|
90
|
+
|
91
|
+
context "image" do
|
92
|
+
it "should process image" do
|
93
|
+
image.should_receive(:process_from_filepicker)
|
94
|
+
image.update_from_filepicker!
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "with resque" do
|
100
|
+
before :each do
|
101
|
+
image.filepicker_url = filepicker_url
|
102
|
+
image.stub_chain(:previous_changes, :keys).and_return ["filepicker_url"]
|
103
|
+
end
|
104
|
+
|
105
|
+
it "enqueues job" do
|
106
|
+
stub_const "Resque", Class.new
|
107
|
+
Resque.should_receive(:enqueue).with(FileClip::Jobs::Resque, "Image", nil)
|
108
|
+
image.update_from_filepicker!
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context "#update_from_filepicker?" do
|
114
|
+
it "should be false with only a filepicker url" do
|
115
|
+
image.filepicker_url = filepicker_url
|
116
|
+
image.update_from_filepicker?.should be_false
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should be false without a filepicker" do
|
120
|
+
image.stub_chain(:previous_changes, :keys).and_return ["filepicker_url"]
|
121
|
+
image.update_from_filepicker?.should be_false
|
122
|
+
end
|
123
|
+
|
124
|
+
it "should be true if filepicker url exists and is changed" do
|
125
|
+
image.filepicker_url = filepicker_url
|
126
|
+
image.stub_chain(:previous_changes, :keys).and_return ["filepicker_url"]
|
127
|
+
image.update_from_filepicker?.should be_true
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
context "#process_from_filepicker" do
|
132
|
+
context "not delayed" do
|
133
|
+
context "image" do
|
134
|
+
before :each do
|
135
|
+
image.filepicker_url = filepicker_url
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should set attachment and save" do
|
139
|
+
image.should_receive(:attachment=).with(uri)
|
140
|
+
image.should_receive(:save)
|
141
|
+
image.process_from_filepicker
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context "#filepicker_url_not_present?" do
|
148
|
+
it "should return true" do
|
149
|
+
image.filepicker_url_not_present?.should == true
|
150
|
+
end
|
151
|
+
|
152
|
+
context "with filepicker url" do
|
153
|
+
before :each do
|
154
|
+
image.filepicker_url = filepicker_url
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should return false" do
|
158
|
+
image.filepicker_url_not_present?.should == false
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "#fileclip_previously_changed?" do
|
164
|
+
it "should return true with previous changed filepicker_url" do
|
165
|
+
image.stub_chain(:previous_changes, :keys).and_return ["filepicker_url"]
|
166
|
+
image.fileclip_previously_changed?.should be_true
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should return false without previously changed filepicker_url" do
|
170
|
+
image.stub_chain(:previous_changes, :keys).and_return []
|
171
|
+
image.fileclip_previously_changed?.should be_false
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def raw_data
|
176
|
+
"{\"mimetype\": \"image/gif\", \"uploaded\": 1374701729162.0, \"writeable\": true, \"filename\": \"140x100.gif\", \"location\": \"S3\", \"path\": \"tmp/tMrYkwI0RWOv0R13hALu_140x100.gif\", \"size\": 449}"
|
177
|
+
end
|
178
|
+
|
179
|
+
def metadata
|
180
|
+
{"mimetype" => "image/gif",
|
181
|
+
"uploaded" => 1374701729162.0,
|
182
|
+
"writeable" => true,
|
183
|
+
"filename" => "140x100.gif",
|
184
|
+
"location" => "S3",
|
185
|
+
"path" => "tmp/tMrYkwI0RWOv0R13hALu_140x100.gif",
|
186
|
+
"size" => 449 }
|
187
|
+
end
|
188
|
+
|
189
|
+
|
190
|
+
context "assign metadata" do
|
191
|
+
before :each do
|
192
|
+
image.filepicker_url = filepicker_url
|
193
|
+
RestClient.stub(:get).with(image.filepicker_url + "/metadata").and_return raw_data
|
194
|
+
end
|
195
|
+
|
196
|
+
it "sets metadata from filepicker" do
|
197
|
+
image.set_metadata
|
198
|
+
image.attachment_content_type.should == "image/gif"
|
199
|
+
image.attachment_file_name.should == "140x100.gif"
|
200
|
+
image.attachment_file_size.should == 449
|
201
|
+
end
|
202
|
+
|
203
|
+
context "process_from_filepicker" do
|
204
|
+
it "sets data and uploads attachment" do
|
205
|
+
image.process_from_filepicker
|
206
|
+
image.attachment_content_type.should == "image/gif"
|
207
|
+
image.attachment_file_name.should == "140x100.gif"
|
208
|
+
image.attachment_file_size.should == 449
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
end
|
data/spec/schema.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
ActiveRecord::Schema.define :version => 0 do
|
2
|
+
create_table "images", :force => true do |t|
|
3
|
+
t.string :attachment_file_name
|
4
|
+
t.string :attachment_content_type
|
5
|
+
t.integer :attachment_updated_at
|
6
|
+
t.integer :attachment_file_size
|
7
|
+
t.string :attachment_meta
|
8
|
+
t.string :filepicker_url
|
9
|
+
end
|
10
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems' unless defined? Gem
|
2
|
+
require 'bundler'
|
3
|
+
Bundler.setup
|
4
|
+
|
5
|
+
# Prepare activerecord
|
6
|
+
# require "active_record"
|
7
|
+
require 'rails/all'
|
8
|
+
|
9
|
+
# Connect to sqlite
|
10
|
+
ActiveRecord::Base.establish_connection(
|
11
|
+
"adapter" => "sqlite3",
|
12
|
+
"database" => ":memory:"
|
13
|
+
)
|
14
|
+
|
15
|
+
ActiveRecord::Migration.verbose = false
|
16
|
+
load(File.join(File.dirname(__FILE__), 'schema.rb'))
|
17
|
+
|
18
|
+
require 'paperclip'
|
19
|
+
ActiveRecord::Base.send(:include, Paperclip::Glue)
|
20
|
+
|
21
|
+
require 'fileclip'
|
22
|
+
ActiveRecord::Base.send(:include, FileClip::Glue)
|
23
|
+
|
24
|
+
|
25
|
+
class Image < ActiveRecord::Base
|
26
|
+
|
27
|
+
has_attached_file :attachment,
|
28
|
+
:storage => :filesystem,
|
29
|
+
:path => "./spec/tmp/:style/:id.:extension",
|
30
|
+
:url => "./spec/tmp/:style/:id.extension"
|
31
|
+
|
32
|
+
fileclip :attachment
|
33
|
+
|
34
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
class window.FileClip
|
2
|
+
_clicked_button: ""
|
3
|
+
|
4
|
+
constructor: ->
|
5
|
+
filepicker.setKey('<%= FileClip.configuration.filepicker_key %>');
|
6
|
+
|
7
|
+
# For filepicker_helper
|
8
|
+
# Accepts button that to be clicked and optional callback
|
9
|
+
button: (target, callback) ->
|
10
|
+
$(document).on "click", target, =>
|
11
|
+
@buttonHandler(target, callback)
|
12
|
+
|
13
|
+
# Handler to set which button was clicked and to pass on callback
|
14
|
+
# To puicker
|
15
|
+
buttonHandler: (target, callback) ->
|
16
|
+
@_clicked_button = $(target)
|
17
|
+
@picker(callback)
|
18
|
+
|
19
|
+
picker: (callback) =>
|
20
|
+
filepicker.pickAndStore
|
21
|
+
mimetypes: "<%= FileClip.configuration.mime_types %>"
|
22
|
+
container: "modal"
|
23
|
+
services: <%= FileClip.configuration.services %>
|
24
|
+
maxSize: (<%= FileClip.configuration.max_size %> * 1024 * 1024)
|
25
|
+
,
|
26
|
+
location: "S3"
|
27
|
+
path: "<%= FileClip.configuration.storage_path %>"
|
28
|
+
access: "<%= FileClip.configuration.file_access %>"
|
29
|
+
, (fpfile) =>
|
30
|
+
@imageHandler fpfile, callback
|
31
|
+
, (error) =>
|
32
|
+
console.log error.code
|
33
|
+
|
34
|
+
# Accepts a filepicker file and optional callback
|
35
|
+
# Passes file and button clicked to a callback
|
36
|
+
# Target if passed in
|
37
|
+
# id to look up the link where it should be going
|
38
|
+
# or clicked button's next input
|
39
|
+
imageHandler: (fpfile, callback, target) ->
|
40
|
+
file = fpfile[0]
|
41
|
+
|
42
|
+
$file_target = if not @_clicked_button
|
43
|
+
$(target).find(".js-fileclip_url")
|
44
|
+
else if @_clicked_button.data("id")
|
45
|
+
$("##{@_clicked_button.data("id")}").next(".js-fileclip_url")
|
46
|
+
else
|
47
|
+
@_clicked_button.next(".js-fileclip_url")
|
48
|
+
|
49
|
+
if $file_target.length > 0
|
50
|
+
$file_target.val file.url
|
51
|
+
else
|
52
|
+
console.log "File Failed to Save"
|
53
|
+
|
54
|
+
callback(file, @_clicked_button) if callback
|
55
|
+
|
56
|
+
|
57
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fileclip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Scott Carleton
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-07
|
11
|
+
date: 2013-10-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: paperclip
|
@@ -16,14 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - '>='
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 3.
|
19
|
+
version: 3.5.1
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - '>='
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 3.
|
26
|
+
version: 3.5.1
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: rest-client
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - '>='
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: resque
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
- !ruby/object:Gem::Dependency
|
84
98
|
name: railties
|
85
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -113,19 +127,37 @@ description: A FilePicker / PaperClip mashup. Use Filepicker for uploads and pa
|
|
113
127
|
email: scott@artsicle.com
|
114
128
|
executables: []
|
115
129
|
extensions: []
|
116
|
-
extra_rdoc_files:
|
117
|
-
- LICENSE
|
118
|
-
- README.md
|
130
|
+
extra_rdoc_files: []
|
119
131
|
files:
|
120
132
|
- .document
|
133
|
+
- .gitignore
|
134
|
+
- .rspec
|
135
|
+
- .ruby-gemset
|
136
|
+
- .ruby-version
|
137
|
+
- .travis.yml
|
121
138
|
- Gemfile
|
122
139
|
- Gemfile.lock
|
123
140
|
- LICENSE
|
124
141
|
- README.md
|
125
142
|
- Rakefile
|
143
|
+
- TODO.md
|
126
144
|
- fileclip.gemspec
|
127
145
|
- lib/fileclip.rb
|
146
|
+
- lib/fileclip/action_view/helpers.rb
|
147
|
+
- lib/fileclip/configuration.rb
|
148
|
+
- lib/fileclip/engine.rb
|
149
|
+
- lib/fileclip/jobs/resque.rb
|
150
|
+
- lib/fileclip/railtie.rb
|
151
|
+
- lib/fileclip/validators.rb
|
128
152
|
- lib/fileclip/version.rb
|
153
|
+
- spec/fileclip/configuration_spec.rb
|
154
|
+
- spec/fileclip/engine_spec.rb
|
155
|
+
- spec/fileclip/railtie_spec.rb
|
156
|
+
- spec/fileclip/validators_spec.rb
|
157
|
+
- spec/fileclip_spec.rb
|
158
|
+
- spec/schema.rb
|
159
|
+
- spec/spec_helper.rb
|
160
|
+
- vendor/assets/javascripts/fileclip.js.coffee.erb
|
129
161
|
homepage: http://github.com/ScotterC/fileclip
|
130
162
|
licenses:
|
131
163
|
- MIT
|
@@ -150,4 +182,11 @@ rubygems_version: 2.0.6
|
|
150
182
|
signing_key:
|
151
183
|
specification_version: 4
|
152
184
|
summary: A FilePicker / PaperClip mashup.
|
153
|
-
test_files:
|
185
|
+
test_files:
|
186
|
+
- spec/fileclip/configuration_spec.rb
|
187
|
+
- spec/fileclip/engine_spec.rb
|
188
|
+
- spec/fileclip/railtie_spec.rb
|
189
|
+
- spec/fileclip/validators_spec.rb
|
190
|
+
- spec/fileclip_spec.rb
|
191
|
+
- spec/schema.rb
|
192
|
+
- spec/spec_helper.rb
|