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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 435bef9bd97c9e7a5a77ab0f26e68b2977d9cd48
4
- data.tar.gz: 2ffee75c354221079689f99cb4f86e13af632e5d
3
+ metadata.gz: f40a90259ac27e876f6cf56f326ab18279b476f5
4
+ data.tar.gz: decfde8e4d6ac8580cb2d86ec1c3394f37ca9333
5
5
  SHA512:
6
- metadata.gz: 36ecf1b9637d0e5bd6e1a8bb88e12aede0e7bfc310b1283d473d2c8029ee804742a1d154033c0f0f93626d206ac4ca8050c8601c5e88304e4eec4f2c2edd7f92
7
- data.tar.gz: cceec767215643332fe54b0f11fa0dbb538a8ffc21c5edf8a9f67d3d15ddc5a76d76d5b526444e052a3ac977306b6c69639bede4af1c0098ceb80fdeee3e09fb
6
+ metadata.gz: 9b1f34aef2c3516b4db6e14ae09ab4c6d1a08ade820374c71b9e64d33224b7336028f8104d4aa435095a367f6660619a174d92df3c65cc967cd3bf1d431aee96
7
+ data.tar.gz: 5b1c57b57955c4b3253dd8362d18b6c9b30ef0df73ef010cd3888ed9303ee59c5edb5d6996c108ef29d7fb4715bd4ef283f95caf843189788121b4b9c95d0b21
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ # YARD artifacts
16
+ .yardoc
17
+ _yardoc
18
+ doc/
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1 @@
1
+ fileclip
@@ -0,0 +1 @@
1
+ 2.0.0-p247
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.0.0
4
+
5
+ script:
6
+ - bundle exec rspec spec
7
+
8
+ notifications:
9
+ email:
10
+ - scott@artsicle.com
@@ -1,9 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- fileclip (0.0.3)
4
+ fileclip (0.2.1)
5
5
  paperclip
6
- paperclip (>= 3.3.0)
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.0)
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
- * path is "/fileclip"
57
- * access is public
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
+
@@ -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 = "fileclip"
6
- s.version = FileClip::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.3.0"]
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"
@@ -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(ClassMethods)
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 add_callbacks
43
+ def fileclip(name)
44
44
  attr_accessible :filepicker_url
45
+ after_commit :update_from_filepicker!
45
46
 
46
- # if respond_to?(:after_commit)
47
- after_commit :update_from_filepicker!
48
- # else
49
- # after_save :update_from_filepicker!
50
- # end
47
+ set_fileclipped(name)
48
+ end
51
49
 
52
- # TODO:
53
- # skip validates_attachment_presence if filepicker url present
54
- # Save without this particular vaildation
50
+ def fileclipped
51
+ @attachment_name
55
52
  end
56
53
 
57
- def paperclip_definitions
58
- @paperclip_definitions ||= if Paperclip::VERSION.to_f < 3.5
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 first
61
+ # TODO: can't handle multiples, just given
71
62
  def attachment_name
72
- @attachment_name ||= self.class.paperclip_definitions.keys.first
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
- process_from_filepicker if update_from_filepicker?
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
- filepicker_url_previously_changed? &&
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 filepicker_url_previously_changed?
110
- previous_changes.keys.include?('filepicker_url')
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
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ initializer 'fileclip.insert_into_active_record' do
5
+ ::ActiveSupport.on_load :active_record do
6
+ FileClip::Railtie.insert
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module FileClip
2
+ module Jobs
3
+ class Resque
4
+ @queue = :fileclip
5
+
6
+ def self.perform(instance_klass, instance_id)
7
+ FileClip.process(instance_klass, instance_id)
8
+ end
9
+ end
10
+ end
11
+ 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
@@ -1,3 +1,3 @@
1
1
  module FileClip
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -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
@@ -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
@@ -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.1.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-26 00:00:00.000000000 Z
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.3.0
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.3.0
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