cropper 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.rspec +2 -0
- data/.rvmrc +48 -0
- data/Gemfile +7 -0
- data/README.md +17 -0
- data/Rakefile +31 -0
- data/app/assets/images/cropper/progress_stripes.png +0 -0
- data/app/assets/images/cropper/scale.png +0 -0
- data/app/assets/images/cropper/scale_large.png +0 -0
- data/app/assets/images/cropper/scale_small.png +0 -0
- data/app/assets/images/cropper/upload_spinner.gif +0 -0
- data/app/assets/javascripts/cropper.js.coffee +9 -0
- data/app/assets/javascripts/cropper/filedrop.js.coffee +255 -0
- data/app/assets/javascripts/cropper/upload_crop_scale.js.coffee +360 -0
- data/app/assets/javascripts/lib/es5-shim.js +1105 -0
- data/app/assets/javascripts/lib/modernizr.js +4 -0
- data/app/assets/stylesheets/cropper/uploads.css.sass +203 -0
- data/app/controllers/cropper/application_controller.rb +4 -0
- data/app/controllers/cropper/uploads_controller.rb +74 -0
- data/app/helpers/cropper/application_helper.rb +4 -0
- data/app/models/cropper/upload.rb +231 -0
- data/app/views/cropper/uploads/_crop.html.haml +34 -0
- data/app/views/cropper/uploads/_error.html.haml +1 -0
- data/app/views/cropper/uploads/_pick.html.haml +42 -0
- data/app/views/cropper/uploads/edit.html.haml +6 -0
- data/app/views/cropper/uploads/new.html.haml +5 -0
- data/app/views/cropper/uploads/show.html.haml +1 -0
- data/config/locales/en.yml +5 -0
- data/config/routes.rb +3 -0
- data/cropper.gemspec +32 -0
- data/db/migrate/20120510103921_uploads.rb +11 -0
- data/db/migrate/20130226190434_uploads_hold_crop_data.rb +8 -0
- data/db/migrate/20130402074802_upload_holder.rb +20 -0
- data/init.rb +4 -0
- data/lib/cropper.rb +159 -0
- data/lib/cropper/engine.rb +8 -0
- data/lib/cropper/glue.rb +20 -0
- data/lib/cropper/routing.rb +23 -0
- data/lib/cropper/schema.rb +63 -0
- data/lib/cropper/version.rb +3 -0
- data/lib/paperclip/geometry_transformation.rb +80 -0
- data/lib/paperclip/validators/attachment_height_validator.rb +89 -0
- data/lib/paperclip/validators/attachment_width_validator.rb +89 -0
- data/lib/paperclip_processors/offset_thumbnail.rb +93 -0
- data/lib/tasks/cropper_tasks.rake +4 -0
- data/script/rails +8 -0
- data/spec/acceptance/acceptance_helper.rb +2 -0
- data/spec/controllers/uploads_controller_spec.rb +5 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/thing.rb +4 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +56 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +6 -0
- data/spec/dummy/db/migrate/20120510104910_things.rb +8 -0
- data/spec/dummy/db/schema.rb +51 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/fixtures/images/icon.png +0 -0
- data/spec/fixtures/images/test.jpg +0 -0
- data/spec/models/thing_spec.rb +6 -0
- data/spec/models/upload_spec.rb +7 -0
- data/spec/spec_helper.rb +18 -0
- metadata +326 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
- upload ||= @upload
|
2
|
+
- prefix = upload.holder_column
|
3
|
+
- multiplier ||= (params[:multiplier] || 1).to_i
|
4
|
+
|
5
|
+
- target_w = upload.crop_width / multiplier
|
6
|
+
- target_h = upload.crop_height / multiplier
|
7
|
+
|
8
|
+
- max_w = upload.precrop_width / multiplier
|
9
|
+
- max_h = upload.precrop_height / multiplier
|
10
|
+
|
11
|
+
- initial_w = upload.scale_width? ? upload.scale_width / multiplier : max_w * 3 / 4
|
12
|
+
- initial_h = upload.scale_height? ? upload.scale_height / multiplier : max_h * 3 / 4
|
13
|
+
|
14
|
+
- offset_l = upload.offset_left? ? upload.offset_left / multiplier : (target_w - initial_w)/2
|
15
|
+
- offset_t = upload.offset_top? ? upload.offset_top / multiplier : (target_h - initial_h)/2
|
16
|
+
|
17
|
+
.cropper
|
18
|
+
.preview{:style => "width: #{initial_w}px; height: #{initial_h}px; top: #{offset_t}px; left: #{offset_l}px"}
|
19
|
+
%img{:src => upload.file.url(:precrop)}
|
20
|
+
|
21
|
+
%p.drag_instructions
|
22
|
+
= t :drag_instructions
|
23
|
+
|
24
|
+
= fields_for upload.holder do |hf|
|
25
|
+
= hf.fields_for :"#{upload.holder_column}_upload", upload do |uf|
|
26
|
+
%fieldset.crop
|
27
|
+
= uf.hidden_field :id, :data => {:"clear-on-detach" => true}
|
28
|
+
= uf.hidden_field :offset_left, :value => offset_l, :class => 'ol'
|
29
|
+
= uf.hidden_field :offset_top, :value => offset_t, :class => 'ot'
|
30
|
+
= uf.hidden_field :multiplier, :value => multiplier
|
31
|
+
.scaler
|
32
|
+
%p.range
|
33
|
+
= uf.range_field :scale_width, :min => target_w, :max => max_w, :value => initial_w, :class => 'sw'
|
34
|
+
= uf.hidden_field :scale_height, :value => initial_h, :class => 'sh'
|
@@ -0,0 +1 @@
|
|
1
|
+
= @upload.errors[:file].first
|
@@ -0,0 +1,42 @@
|
|
1
|
+
- upload ||= @upload
|
2
|
+
- holder ||= @holder || upload.holder
|
3
|
+
- extra_controls ||= false
|
4
|
+
|
5
|
+
- multiplier ||= params[:multiplier] || 1
|
6
|
+
|
7
|
+
= fields_for holder do |hf|
|
8
|
+
= hf.fields_for :"#{upload.holder_column}_upload", upload do |uf|
|
9
|
+
.uploadbox{:data => {:action => "upload", :url => cropper.uploads_path(:holder_id => holder.id, :holder_type => holder.class.to_s.underscore, :holder_column => upload.holder_column, :multiplier => multiplier, :format => :js)}}
|
10
|
+
.prompt
|
11
|
+
= link_to t(:click_to_upload), '#', :data => {:action => "pick"}
|
12
|
+
.droppable
|
13
|
+
.note
|
14
|
+
= t :drop_to_upload
|
15
|
+
.img<
|
16
|
+
- if upload.persisted?
|
17
|
+
- width = upload.crop_width / multiplier
|
18
|
+
- height = upload.crop_height / multiplier
|
19
|
+
= link_to image_tag(upload.file.url(:cropped), :style => "width: #{width}px; height: #{height}px"), cropper.edit_upload_url(upload, :multiplier => multiplier), :data => {:action => "recrop"}
|
20
|
+
= link_to t(:detach_upload), '#', :class => 'detach', :data => {:action => 'detach'}
|
21
|
+
|
22
|
+
%p.file
|
23
|
+
= uf.file_field :file, :class => 'file_upload', :accept => "image"
|
24
|
+
|
25
|
+
%p.instructions
|
26
|
+
- unless upload.persisted?
|
27
|
+
= link_to t(:click_to_upload), '#', :data => {:action => "pick"}
|
28
|
+
%span.droppable
|
29
|
+
= t :drop_to_upload
|
30
|
+
|
31
|
+
- if extra_controls
|
32
|
+
.controls
|
33
|
+
#uploader.upload.button
|
34
|
+
= link_to t(:upload), '#', :data => {:action => "pick"}
|
35
|
+
.edit.button
|
36
|
+
- if upload && upload.persisted?
|
37
|
+
= link_to t(:edit_crop), cropper.edit_upload_url(upload, :multiplier => multiplier), :data => {:action => "recrop"}
|
38
|
+
- else
|
39
|
+
= link_to t(:edit_crop), '#', :data => {:action => "recrop"}, :class => 'unavailable'
|
40
|
+
.cancel.button
|
41
|
+
= link_to t(:cancel), '#'
|
42
|
+
|
@@ -0,0 +1,6 @@
|
|
1
|
+
/ This we show when setting the crop parameters of an upload.
|
2
|
+
/ It is usually either summoned by a click or returned on a
|
3
|
+
/ redirect from uploads#create. For more direct editing you could
|
4
|
+
/ also nest cropper/uploads/crop in the recipient's edit form.
|
5
|
+
.edit_upload
|
6
|
+
= render :partial => "cropper/uploads/crop"
|
@@ -0,0 +1 @@
|
|
1
|
+
= image_tag @upload.file.url(:cropped)
|
data/config/routes.rb
ADDED
data/cropper.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "cropper/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "cropper"
|
7
|
+
s.version = Cropper::VERSION
|
8
|
+
s.authors = ["William Ross"]
|
9
|
+
s.email = ["will@spanner.org"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{A simple but specific way to attach (re)croppable uploads to any model}
|
12
|
+
s.description = %q{Provides a mechanism for uploading, cropping and reusing images in any of your models.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "cropper"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency "rails", "~> 3.2.0"
|
22
|
+
s.add_dependency('paperclip', '~> 3.3')
|
23
|
+
s.add_dependency('delayed_job_active_record')
|
24
|
+
|
25
|
+
s.add_development_dependency "rake"
|
26
|
+
s.add_development_dependency "rspec-rails"
|
27
|
+
s.add_development_dependency "shoulda-matchers"
|
28
|
+
s.add_development_dependency "capybara"
|
29
|
+
s.add_development_dependency "acts_as_fu"
|
30
|
+
s.add_development_dependency "sqlite3"
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class UploadsHoldCropData < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :cropper_uploads, :scale_width, :integer
|
4
|
+
add_column :cropper_uploads, :scale_height, :integer
|
5
|
+
add_column :cropper_uploads, :offset_left, :integer
|
6
|
+
add_column :cropper_uploads, :offset_top, :integer
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
class UploadHolder < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
add_column :cropper_uploads, :holder_id, :integer
|
4
|
+
add_column :cropper_uploads, :holder_type, :string
|
5
|
+
add_column :cropper_uploads, :holder_column, :string
|
6
|
+
|
7
|
+
Cropper::Upload.reset_column_information
|
8
|
+
Cropper::Upload.all.each do |u|
|
9
|
+
puts "finding match for upload #{u.id}"
|
10
|
+
if person = Droom::Person.where(:image_upload_id => u.id).first
|
11
|
+
puts "-> #{person.formal_name}"
|
12
|
+
%w{offset_left offset_top scale_width scale_height}.each do |col|
|
13
|
+
u.update_column(col.to_sym, person.send(:"image_#{col}"))
|
14
|
+
end
|
15
|
+
u.update_column(:holder_type, "Droom::Person")
|
16
|
+
u.update_column(:holder_column, 'image')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/init.rb
ADDED
data/lib/cropper.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
require "paperclip"
|
2
|
+
require "paperclip/validators/attachment_height_validator"
|
3
|
+
require "paperclip/validators/attachment_width_validator"
|
4
|
+
require "paperclip/geometry_transformation"
|
5
|
+
require "paperclip_processors/offset_thumbnail"
|
6
|
+
require "cropper/engine"
|
7
|
+
require "cropper/routing"
|
8
|
+
require 'cropper/glue'
|
9
|
+
require 'open-uri'
|
10
|
+
|
11
|
+
module Cropper
|
12
|
+
# Module configuration is handled in a simple way by accessors on the Cropper module. At the moment
|
13
|
+
# there aren't many. Any, in fact, but we do hold some structural information about the uploading classes.
|
14
|
+
#
|
15
|
+
mattr_accessor :uploadable_classes, :upload_options
|
16
|
+
|
17
|
+
class << self
|
18
|
+
def uploadable_classes
|
19
|
+
@@uploadable_classes ||= {}
|
20
|
+
end
|
21
|
+
|
22
|
+
def upload_options
|
23
|
+
@@upload_options ||= {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def declare_uploadable(klass, column, options)
|
27
|
+
k = klass.to_s.underscore.to_sym
|
28
|
+
uploadable_classes[k] ||= []
|
29
|
+
uploadable_classes[k].push(column.to_sym)
|
30
|
+
upload_options[k] ||= {}
|
31
|
+
upload_options[k][column.to_sym] = {
|
32
|
+
:precrop_geometry => options[:styles][:precrop],
|
33
|
+
:crop_geometry => options[:geometry]
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def crop_geometry(klass, column)
|
38
|
+
k = klass.to_s.underscore.to_sym
|
39
|
+
upload_options[k][column.to_sym][:crop_geometry]
|
40
|
+
end
|
41
|
+
|
42
|
+
def precrop_geometry(klass, column)
|
43
|
+
k = klass.to_s.underscore.to_sym
|
44
|
+
Rails.logger.warn "precrop_geometry(#{k.inspect}, #{column.inspect})"
|
45
|
+
upload_options[k][column.to_sym][:precrop_geometry]
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Cropper::ClassMethods is included into ActiveRecord::Base in the same way as the Paperclip module.
|
50
|
+
# It adds a `has_upload` class method that defines an attachment and adds several instance methods
|
51
|
+
# that will return the values that determine its cropping. Those values are usually but not
|
52
|
+
# necessarily given by the user.
|
53
|
+
#
|
54
|
+
module ClassMethods
|
55
|
+
## Defining upload columns
|
56
|
+
#
|
57
|
+
# *has_upload* brings in the whole machinery of receiving and cropping an uploaded file. The options given are exactly the same
|
58
|
+
# as paperclip's `has_attached_file` call, with the addition of a 'crop' parameter that gives the target dimensions. The crop
|
59
|
+
# value is applied in the upload object, then any other styles you specify here are applied to that cropped image when it is
|
60
|
+
# passed to this model.
|
61
|
+
#
|
62
|
+
# The practical effect of this is that your :original file always has your :crop dimensions.
|
63
|
+
#
|
64
|
+
# You can also set an optional :precrop option to set the dimensions of the file that is presented in the cropping interface.
|
65
|
+
# The default is 1600x1600<, which is often going to be too big and may cause unwanted scaling-up of your source image.
|
66
|
+
# The precrop geometry is also applied in the upload object, when a file is first uploaded.
|
67
|
+
#
|
68
|
+
# The call usually looks like this:
|
69
|
+
#
|
70
|
+
# class User < ActiveRecord::Base
|
71
|
+
# has_upload :avatar,
|
72
|
+
# :precrop => '1440x960<
|
73
|
+
# :crop => '720x480#'
|
74
|
+
# :styles => {
|
75
|
+
# :thumbnail => "60x60#"
|
76
|
+
# }
|
77
|
+
#
|
78
|
+
# The crop geometry will always be treated as a fixed target shape: that is, as though it ended in '#'. Any other suffix will be
|
79
|
+
# removed. The other styles that you define can be in any form that paperclip understands.
|
80
|
+
#
|
81
|
+
# A model can make more than one has_upload call. The methods we define here are all prefixed with the association name, so you
|
82
|
+
# usually end up calling methods like `person.icon_upload`.
|
83
|
+
#
|
84
|
+
def has_upload(attachment_name=:image, options={})
|
85
|
+
# unless !table_exists? || column_names.include?("#{attachment_name}_upload_id")
|
86
|
+
# raise RuntimeError, "has_upload(#{attachment_name}) called on class #{self.to_s} but we have no #{attachment_name}_upload_id column" unless
|
87
|
+
# end
|
88
|
+
|
89
|
+
# allow uploads to be assigned to this class and column in the UploadsController.
|
90
|
+
options.reverse_merge!(:geometry => "960x640#", :whiny => true, :styles => {})
|
91
|
+
options[:styles].reverse_merge!({:precrop => "1600x1600<"})
|
92
|
+
Cropper.declare_uploadable(self, attachment_name, options)
|
93
|
+
|
94
|
+
### Upload association
|
95
|
+
#
|
96
|
+
# [uploads](/app/models/upload.html) are the original image files uploaded and cropped by this person.
|
97
|
+
#
|
98
|
+
has_many :uploads, :class_name => "Cropper::Upload", :as => :holder # so what happens when we call this twice?
|
99
|
+
|
100
|
+
# Ok, I give in. We have to require an image_upload_id column. It's silly trying to fake the whole association machine.
|
101
|
+
belongs_to :"#{attachment_name}_upload", :class_name => "Cropper::Upload", :autosave => true
|
102
|
+
|
103
|
+
# accepts_nested_attributes_for :"#{attachment_name}_upload"
|
104
|
+
attr_accessible :"#{attachment_name}_upload_attributes"
|
105
|
+
after_save :"connect_to_#{attachment_name}_upload"
|
106
|
+
|
107
|
+
#...but we still need to intervene to set the holder_column column of the upload when it is assigned
|
108
|
+
define_method :"#{attachment_name}_upload_with_holder_column=" do |upload|
|
109
|
+
upload.holder_column = attachment_name
|
110
|
+
send :"#{attachment_name}_upload_without_holder_column=", upload
|
111
|
+
end
|
112
|
+
alias_method_chain :"#{attachment_name}_upload=", :holder_column
|
113
|
+
|
114
|
+
#...or built.
|
115
|
+
define_method :"build_#{attachment_name}_upload_with_holder_column" do |attributes={}, options={}|
|
116
|
+
attributes[:holder_column] = attachment_name
|
117
|
+
attributes[:holder_type] ||= self.class.to_s unless attributes[:holder]
|
118
|
+
send :"build_#{attachment_name}_upload_without_holder_column", attributes, options
|
119
|
+
end
|
120
|
+
alias_method_chain :"build_#{attachment_name}_upload", :holder_column
|
121
|
+
|
122
|
+
# when a new holder is created, the interface means that the upload will have preceded it. In that
|
123
|
+
# case we will have forced the setting of holder_type to allow crop-dimension lookups. When eventually
|
124
|
+
# saving, we have to make sure that holder_id is also present.
|
125
|
+
define_method :"connect_to_#{attachment_name}_upload" do
|
126
|
+
if upload = send(:"#{attachment_name}_upload")
|
127
|
+
upload.update_column(:holder_type, self.class.to_s)
|
128
|
+
upload.update_column(:holder_id, self.id)
|
129
|
+
upload.update_column(:holder_column, attachment_name)
|
130
|
+
end
|
131
|
+
Rails.logger.warn "connect_to_#{attachment_name}_upload: upload is #{upload.inspect}. Self is #{self.inspect}"
|
132
|
+
true
|
133
|
+
end
|
134
|
+
|
135
|
+
define_method :"#{attachment_name}_upload_attributes=" do |attributes|
|
136
|
+
# assign_nested_attributes_for_image_upload_association(:image_upload, attributes, mass_assignment_options)
|
137
|
+
if upload_id = attributes.delete('id')
|
138
|
+
self.send :"#{attachment_name}_upload=", Cropper::Upload.find(upload_id)
|
139
|
+
end
|
140
|
+
if upload = self.send(:"#{attachment_name}_upload")
|
141
|
+
Rails.logger.warn "setting upload attributes for #{upload.inspect} -> #{attributes.inspect}"
|
142
|
+
upload.assign_attributes(attributes)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
### Attachment
|
147
|
+
#
|
148
|
+
# Eventually we get to the point. Image attachments work in the usual Paperclip way except that they are always received from
|
149
|
+
# an upload object, presumably in an already-cropped form.
|
150
|
+
# If this class then generates other styles, they are built from that cropped image rather than the file originally uploaded.
|
151
|
+
#
|
152
|
+
has_attached_file attachment_name, options
|
153
|
+
|
154
|
+
# Note: updates to the attached file are pushed to the holder from the upload after processing is complete, so we won't always
|
155
|
+
# have them immediately. Best course is to display the upload cropped rather than the holder original.
|
156
|
+
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/cropper/glue.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'cropper/schema'
|
2
|
+
|
3
|
+
module Cropper
|
4
|
+
module Glue
|
5
|
+
def self.included base #:nodoc:
|
6
|
+
|
7
|
+
# Extend ActiveRecord::Base with Cropper::ClassMethods, as defined in cropper.rb.
|
8
|
+
#
|
9
|
+
base.extend ClassMethods
|
10
|
+
|
11
|
+
# Load migration helpers into all the right places.
|
12
|
+
#
|
13
|
+
if defined?(ActiveRecord)
|
14
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:include, Cropper::Schema)
|
15
|
+
ActiveRecord::ConnectionAdapters::Table.send(:include, Cropper::Schema)
|
16
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, Cropper::Schema)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module ActionDispatch::Routing
|
2
|
+
|
3
|
+
class Mapper
|
4
|
+
def cropper_for(*res)
|
5
|
+
options = res.extract_options!
|
6
|
+
res.map!(&:to_sym)
|
7
|
+
|
8
|
+
# options[:path] ||= "cropper"
|
9
|
+
# options[:as] ||= :cropper
|
10
|
+
# options[:path] = "#{options[:path]}/" unless options[:path].last == '/'
|
11
|
+
# mount Cropper::Engine => options[:path], :as => options[:as]
|
12
|
+
|
13
|
+
Rails.application.routes.draw do
|
14
|
+
resources :uploads, :module => :cropper
|
15
|
+
res.each do |resource|
|
16
|
+
resources resource do
|
17
|
+
resources :uploads, :module => :cropper
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Cropper
|
2
|
+
# Provides helpers that can be used in migrations.
|
3
|
+
# Copied from, and often makes calls on, the equivalent file in Paperclip.
|
4
|
+
#
|
5
|
+
module Schema
|
6
|
+
UPLOAD_COLUMNS = {
|
7
|
+
:file_name => :string,
|
8
|
+
:content_type => :string,
|
9
|
+
:file_size => :integer,
|
10
|
+
:updated_at => :datetime,
|
11
|
+
:upload_id => :integer,
|
12
|
+
:scale_width => :integer,
|
13
|
+
:scale_height => :integer,
|
14
|
+
:offset_left => :integer,
|
15
|
+
:offset_top => :integer
|
16
|
+
}
|
17
|
+
|
18
|
+
def self.included(base)
|
19
|
+
ActiveRecord::ConnectionAdapters::Table.send :include, TableDefinition
|
20
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send :include, TableDefinition
|
21
|
+
ActiveRecord::ConnectionAdapters::AbstractAdapter.send :include, Statements
|
22
|
+
end
|
23
|
+
|
24
|
+
module Statements
|
25
|
+
def add_upload(table_name, *attachment_names)
|
26
|
+
raise ArgumentError, "Please specify attachment name in your add_upload call in your migration." if attachment_names.empty?
|
27
|
+
|
28
|
+
attachment_names.each do |attachment_name|
|
29
|
+
UPLOAD_COLUMNS.each_pair do |column_name, column_type|
|
30
|
+
unless column_exists? table_name, "#{attachment_name}_#{column_name}"
|
31
|
+
add_column(table_name, "#{attachment_name}_#{column_name}", column_type)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
def remove_upload(table_name, *attachment_names)
|
39
|
+
raise ArgumentError, "Please specify attachment name in your remove_upload call in your migration." if attachment_names.empty?
|
40
|
+
|
41
|
+
attachment_names.each do |attachment_name|
|
42
|
+
COLUMNS.each_pair do |column_name, column_type|
|
43
|
+
if column_exists? table_name, "#{attachment_name}_#{column_name}"
|
44
|
+
remove_column(table_name, "#{attachment_name}_#{column_name}")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
module TableDefinition
|
52
|
+
def cropped_attachment(*attachment_names)
|
53
|
+
attachment_names.each do |attachment_name|
|
54
|
+
UPLOAD_COLUMNS.each_pair do |column_name, column_type|
|
55
|
+
column("#{attachment_name}_#{column_name}", column_type)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|