fileclip 0.1.0 → 0.2.2
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.
- 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 [](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
|