cropped_paperclip 0.1.0
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.
- 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/.DS_Store +0 -0
- data/app/assets/.DS_Store +0 -0
- data/app/assets/javascripts/.DS_Store +0 -0
- data/app/assets/javascripts/cropped_paperclip/filedrop.js.coffee +254 -0
- data/app/assets/javascripts/cropped_paperclip/upload_crop_scale.js.coffee +319 -0
- data/app/assets/javascripts/es5-shim.js +1105 -0
- data/app/assets/javascripts/uploader.js.coffee +3 -0
- data/app/controllers/cropped_paperclip/application_controller.rb +4 -0
- data/app/controllers/cropped_paperclip/uploads_controller.rb +40 -0
- data/app/helpers/cropped_paperclip/application_helper.rb +4 -0
- data/app/models/upload.rb +119 -0
- data/config/routes.rb +3 -0
- data/cropped_paperclip.gemspec +32 -0
- data/db/migrate/20120510103921_uploads.rb +11 -0
- data/init.rb +4 -0
- data/lib/cropped_paperclip.rb +170 -0
- data/lib/cropped_paperclip/engine.rb +7 -0
- data/lib/cropped_paperclip/glue.rb +20 -0
- data/lib/cropped_paperclip/schema.rb +35 -0
- data/lib/cropped_paperclip/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 +86 -0
- data/lib/tasks/cropped_paperclip_tasks.rake +4 -0
- data/script/rails +8 -0
- data/spec/.DS_Store +0 -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 +15 -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 +3 -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/.DS_Store +0 -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 +13 -0
- data/spec/spec_helper.rb +18 -0
- metadata +309 -0
@@ -0,0 +1,40 @@
|
|
1
|
+
module CroppedPaperclip
|
2
|
+
class UploadsController < ::ApplicationController
|
3
|
+
respond_to :js
|
4
|
+
before_filter :find_upload, :only => [:show, :edit, :destroy]
|
5
|
+
before_filter :build_upload, :only => [:new, :create]
|
6
|
+
|
7
|
+
def show
|
8
|
+
respond_with(@upload)
|
9
|
+
end
|
10
|
+
|
11
|
+
def new
|
12
|
+
render
|
13
|
+
end
|
14
|
+
|
15
|
+
def create
|
16
|
+
@upload.update_attributes(params[:upload])
|
17
|
+
render :partial => 'crop'
|
18
|
+
end
|
19
|
+
|
20
|
+
def edit
|
21
|
+
render :partial => 'crop'
|
22
|
+
end
|
23
|
+
|
24
|
+
def destroy
|
25
|
+
@upload.destroy
|
26
|
+
respond_with(@upload)
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def find_upload
|
32
|
+
@upload = params[:id] == 'latest' || params[:id].blank? ? current_user.last_upload : Upload.find(params[:id])
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_upload
|
36
|
+
@upload = Upload.create
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
# This is a standard upload class that should be useable for most purposes.
|
2
|
+
# We assume that even when the final destination is an S3 bucket, the initial upload
|
3
|
+
# will be held locally.
|
4
|
+
#
|
5
|
+
class Upload < ActiveRecord::Base
|
6
|
+
has_attached_file :file,
|
7
|
+
:path => ":rails_root/public/system/:class/:attachment/:id/:style/:filename",
|
8
|
+
:url => "/system/:class/:attachment/:id/:style/:filename",
|
9
|
+
:processors => lambda { |instance| instance.precrop_processors },
|
10
|
+
:styles => lambda { |attachment| attachment.instance.precrop_styles }
|
11
|
+
|
12
|
+
attr_accessible :file
|
13
|
+
|
14
|
+
# To change precrop dimensions or other thumbnail properties, just monkeypatch this method.
|
15
|
+
#
|
16
|
+
def precrop_styles
|
17
|
+
{
|
18
|
+
:icon => { :geometry => "40x40#" },
|
19
|
+
:thumb => { :geometry => "100x100#" },
|
20
|
+
:precrop => { :geometry => "1600x3000" }
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def precrop_processors
|
25
|
+
[:thumbnail]
|
26
|
+
end
|
27
|
+
|
28
|
+
validates :file, :attachment_presence => true
|
29
|
+
|
30
|
+
## Image dimensions
|
31
|
+
#
|
32
|
+
# We need to know dimensions of the precrop image in order to set up the cropping interface, so we
|
33
|
+
# examine the uploaded file before it is flushed.
|
34
|
+
#
|
35
|
+
after_post_process :read_dimensions
|
36
|
+
|
37
|
+
# *original_geometry* returns the discovered dimensions of the uploaded file as a paperclip geometry object.
|
38
|
+
#
|
39
|
+
def original_geometry
|
40
|
+
@original_geometry ||= Paperclip::Geometry.new(original_width, original_height)
|
41
|
+
end
|
42
|
+
|
43
|
+
# *geometry*, given a style name, returns the dimensions of the file if that style were applied. For
|
44
|
+
# speed we calculate this rather than reading the file, which might be in S3 or some other distant place.
|
45
|
+
#
|
46
|
+
# The logic is in [lib/paperclip/geometry_tranformation.rb](/lib/paperclip/geometry_tranformation.html),
|
47
|
+
# which is a ruby library that mimics the action of imagemagick's convert command.
|
48
|
+
#
|
49
|
+
def geometry(style_name='original')
|
50
|
+
# These calculations are all memoised.
|
51
|
+
@geometry ||= {}
|
52
|
+
begin
|
53
|
+
@geometry[style_name] ||= if style_name.to_s == 'original'
|
54
|
+
# If no style name is given, or it is 'original', we return the original discovered dimensions.
|
55
|
+
original_geometry
|
56
|
+
else
|
57
|
+
# Otherwise, we apply a mock transformation to see what dimensions would result.
|
58
|
+
style = self.file.styles[style_name.to_sym]
|
59
|
+
original_geometry.transformed_by(style.geometry)
|
60
|
+
end
|
61
|
+
rescue Paperclip::TransformationError => e
|
62
|
+
# In case of explosion, we always return the original dimensions so that action can continue.
|
63
|
+
original_geometry
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# *width* returns the width of this image in a given style.
|
68
|
+
#
|
69
|
+
def width(style_name='original')
|
70
|
+
geometry(style_name).width.to_i
|
71
|
+
end
|
72
|
+
|
73
|
+
# *height* returns the height of this image in a given style.
|
74
|
+
#
|
75
|
+
def height(style_name='original')
|
76
|
+
geometry(style_name).height.to_i
|
77
|
+
end
|
78
|
+
|
79
|
+
# *square?* returns true if width and height are the same.
|
80
|
+
#
|
81
|
+
def square?(style_name='original')
|
82
|
+
geometry(style_name).square?
|
83
|
+
end
|
84
|
+
|
85
|
+
# *vertical?* returns true if the image, in the given style, is taller than it is wide.
|
86
|
+
#
|
87
|
+
def vertical?(style_name='original')
|
88
|
+
geometry(style_name).vertical?
|
89
|
+
end
|
90
|
+
|
91
|
+
# *horizontal?* returns true if the image, in the given style, is wider than it is tall.
|
92
|
+
#
|
93
|
+
def horizontal?(style_name='original')
|
94
|
+
geometry(style_name).horizontal?
|
95
|
+
end
|
96
|
+
|
97
|
+
# *dimensions_known?* returns true we have managed to discover the dimensions of the original file.
|
98
|
+
#
|
99
|
+
def dimensions_known?
|
100
|
+
original_width? && original_height?
|
101
|
+
end
|
102
|
+
|
103
|
+
private
|
104
|
+
|
105
|
+
# *read_dimensions* is called after post processing to record in the database the original width, height
|
106
|
+
# and extension of the uploaded file. At this point the file queue will not have been flushed but the upload
|
107
|
+
# should be in place. We grab dimensions from the temp file and calculate thumbnail dimensions later, on demand.
|
108
|
+
#
|
109
|
+
def read_dimensions
|
110
|
+
if file = self.file.queued_for_write[:original]
|
111
|
+
geometry = Paperclip::Geometry.from_file(file)
|
112
|
+
self.original_width = geometry.width
|
113
|
+
self.original_height = geometry.height
|
114
|
+
self.original_extension = File.extname(file.path)
|
115
|
+
end
|
116
|
+
true
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
data/config/routes.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "cropped_paperclip/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "cropped_paperclip"
|
7
|
+
s.version = CroppedPaperclip::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 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 = "cropped_paperclip"
|
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.1.0')
|
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
|
data/init.rb
ADDED
@@ -0,0 +1,170 @@
|
|
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 "cropped_paperclip/engine"
|
7
|
+
require 'cropped_paperclip/glue'
|
8
|
+
|
9
|
+
module CroppedPaperclip
|
10
|
+
mattr_accessor :attachment_path
|
11
|
+
mattr_accessor :attachment_url
|
12
|
+
attachment_path = ":rails_root/public/system/:class/:attachment/:id/:style/:filename"
|
13
|
+
attachment_url = "/system/:class/:attachment/:id/:style/:filename"
|
14
|
+
|
15
|
+
# CroppedPaperclip::ClassMethods is included into ActiveRecord::Base in the same way as the Paperclip module.
|
16
|
+
# It adds a `has_upload` class method that defines an attachment and adds several instance methods
|
17
|
+
# that will return the values that determine its cropping. Those values are usually but not
|
18
|
+
# necessarily given by the user.
|
19
|
+
#
|
20
|
+
|
21
|
+
module ClassMethods
|
22
|
+
## Defining upload columns
|
23
|
+
#
|
24
|
+
# *has_upload* brings in the whole machinery of receiving and cropping an uploaded file. eg.
|
25
|
+
#
|
26
|
+
# class User < ActiveRecord::Base
|
27
|
+
# has_upload :avatar, :size => '120x120#'
|
28
|
+
#
|
29
|
+
# The geometry string will always be treated as though it ended in '#'.
|
30
|
+
#
|
31
|
+
# Set the :cropped option to false if you want the file-upload-sharing mechanism but no cropping step.
|
32
|
+
# In that case any geometry string can be used and it will be passed through intact.
|
33
|
+
#
|
34
|
+
# class Group < ActiveRecord::Base
|
35
|
+
# has_upload :icon, :size => '40x40#', :crop => false
|
36
|
+
#
|
37
|
+
def has_upload(attachment_name=:image, options={})
|
38
|
+
unless !table_exists? || column_names.include?("#{attachment_name}_upload_id")
|
39
|
+
raise RuntimeError, "has_upload(#{attachment_name}) called on class #{self.to_s} but we have no #{attachment_name}_upload_id column"
|
40
|
+
end
|
41
|
+
|
42
|
+
options.reverse_merge!(:geometry => "640x960#", :cropped => true, :whiny => true)
|
43
|
+
options[:geometry].sub!(/\D*$/, '') if options[:cropped]
|
44
|
+
# raise here if geometry is not useable
|
45
|
+
|
46
|
+
class_variable_set(:"@@#{attachment_name}_cropped", options[:cropped])
|
47
|
+
|
48
|
+
# The essential step is present in this style definition. It specifies the OffsetThumbnail processor,
|
49
|
+
# which is similar to the usual thumbnailer but has a more flexible scaling and cropping procedure,
|
50
|
+
# and passes through a couple of callback procs that will return the scaling and cropping arguments
|
51
|
+
# it requires.
|
52
|
+
#
|
53
|
+
crop_style = options[:cropped] == false ? geometry : {
|
54
|
+
:geometry => "#{options[:geometry]}#",
|
55
|
+
:processors => [:offset_thumbnail],
|
56
|
+
|
57
|
+
# The processor will first scale the image to the width that is specified by the scale_width property of the instance
|
58
|
+
:scale => lambda { |att|
|
59
|
+
width = att.instance.send :"#{attachment_name}_scale_width"
|
60
|
+
"#{width || 0}x"
|
61
|
+
},
|
62
|
+
|
63
|
+
# ...then perform the crop described by the width, height, offset_top and offset_left properties of the instance.
|
64
|
+
:crop_and_offset => lambda { |att|
|
65
|
+
width, height = options[:geometry].split('x')
|
66
|
+
left = att.instance.send :"#{attachment_name}_offset_left" || 0
|
67
|
+
top = att.instance.send :"#{attachment_name}_offset_top"
|
68
|
+
"%dx%d%+d%+d" % [width, height, -(left || 0), -(top || 0)]
|
69
|
+
}
|
70
|
+
}
|
71
|
+
|
72
|
+
options[:styles] ||= { :icon => "48x48#" }
|
73
|
+
options[:styles].merge!({:cropped => crop_style})
|
74
|
+
|
75
|
+
### Upload association
|
76
|
+
#
|
77
|
+
# [uploads](/app/models/upload.html) are the raw image files uploaded by this person.
|
78
|
+
# They are held separately as the basis for repeatable (and shareable) image assignment.
|
79
|
+
#
|
80
|
+
belongs_to :"#{attachment_name}_upload", :class_name => "Upload"
|
81
|
+
before_save :"read_#{attachment_name}_upload"
|
82
|
+
|
83
|
+
### Attachment
|
84
|
+
#
|
85
|
+
# Image attachments work in the usual Paperclip way except that the :cropped style is applied differently to each instance.
|
86
|
+
# The editing interface allows the user to upload a picture (which creates an upload object) and choose how it is scaled
|
87
|
+
# and cropped (which stores values here).
|
88
|
+
#
|
89
|
+
# The cropped image is created by a [custom processor](/lib/paperclip_processors/offset_thumbnail.html) very similar to
|
90
|
+
# Paperclip::Thumbnail, but which looks up the scale and crop parameters to calculate the imagemagick transformation.
|
91
|
+
#
|
92
|
+
has_attached_file attachment_name, options
|
93
|
+
|
94
|
+
## Maintenance
|
95
|
+
#
|
96
|
+
# *read_[name]_upload* is called before_save. If there is a new upload, or any of our scale and crop values are changed, it will assign
|
97
|
+
# the uploaded file. Even if it's the same file as before, the effect is to trigger post-processing again and apply the current crop and scale values.
|
98
|
+
#
|
99
|
+
define_method :"read_#{attachment_name}_upload" do
|
100
|
+
if self.send(:"reprocess_#{attachment_name}?") && upload = self.send(:"#{attachment_name}_upload")
|
101
|
+
self.send :"#{attachment_name}=", upload.file
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# *reprocess_[name]?* returns true if there have been any changes to the upload association that would necessitate a new crop.
|
106
|
+
#
|
107
|
+
cols = [:upload_id]
|
108
|
+
cols += [:upload_id, :scale_width, :offset_top, :offset_left] if options[:cropped]
|
109
|
+
define_method :"reprocess_#{attachment_name}?" do
|
110
|
+
cols.any? {|col| send(:"#{attachment_name}_#{col}_changed?") }
|
111
|
+
end
|
112
|
+
|
113
|
+
# * [name]_cropped? returns true if the named attachment is cropped on assignment. It can be useful in a form partial.
|
114
|
+
#
|
115
|
+
define_method :"#{attachment_name}_cropped?" do
|
116
|
+
STDERR.puts ">> #{attachment_name}_cropped?"
|
117
|
+
!!class_variable_get(:"@@#{attachment_name}_cropped")
|
118
|
+
end
|
119
|
+
|
120
|
+
define_method :"#{attachment_name}_for_cropping" do
|
121
|
+
if upload = send(:"#{attachment_name}_upload")
|
122
|
+
# here we introduce a convention that might not stand up
|
123
|
+
STDERR.puts ">> #{attachment_name}_for_cropping"
|
124
|
+
upload.url(:"#{attachment_name}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
end
|
129
|
+
|
130
|
+
## Delay post-processing
|
131
|
+
|
132
|
+
def delay_post_processing(attachment_name=:image)
|
133
|
+
send(:"before_#{attachment_name}_post_process", :"defer_#{attachment_name}_post_processing")
|
134
|
+
after_save(:"resume_#{attachment_name}_post_processing")
|
135
|
+
|
136
|
+
# There are too many thumbnail styles in this class. We can't make the user wait while they are processed,
|
137
|
+
# so the whole job of thumbnailing is spun off into a delayed_job. Since the main publication page displays
|
138
|
+
# the :original style, we can show the user her public page while the rest of the thumbnails are still being
|
139
|
+
# processed.
|
140
|
+
#
|
141
|
+
# The usual post_processing routine is abandoned when we return false from this call.
|
142
|
+
#
|
143
|
+
define_method :"defer_#{attachment_name}_post_processing" do
|
144
|
+
if send(:"reprocess_#{attachment_name}?") && !send(:"awaiting_#{attachment_name}_processing?")
|
145
|
+
send(:"awaiting_#{attachment_name}_processing", true)
|
146
|
+
false
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
# The delayed job is created just by interposing the `delay` method in a call to `process_image_styles!`. The effect
|
151
|
+
# is to serialize this object and that call to the database and resume it later when the job runner picks it up.
|
152
|
+
# We can't do that until the publication object has an id, so the call is made from an after_save handler.
|
153
|
+
#
|
154
|
+
define_method :"resume_#{attachment_name}_post_processing" do
|
155
|
+
if send(:"reprocess_#{attachment_name}?") && send(:"awaiting_#{attachment_name}_processing?")
|
156
|
+
self.delay.send(:"process_#{attachment_name}_styles!")
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
# This is the eventual processing step, to which the delayed job object is just a sort of pointer.
|
161
|
+
# It retrieves the original image from S3 and applies the processing styles.
|
162
|
+
#
|
163
|
+
define_method :"process_#{attachment_name}_styles!" do
|
164
|
+
send(attachment_name).reprocess!
|
165
|
+
update_column(:"awaiting_#{attachment_name}_processing", false)
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'cropped_paperclip/schema'
|
2
|
+
|
3
|
+
module CroppedPaperclip
|
4
|
+
module Glue
|
5
|
+
def self.included base #:nodoc:
|
6
|
+
|
7
|
+
# Extend ActiveRecord::Base with CroppedPaperclip::ClassMethods, as defined in cropped_paperclip.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, CroppedPaperclip::Schema)
|
15
|
+
ActiveRecord::ConnectionAdapters::Table.send(:include, CroppedPaperclip::Schema)
|
16
|
+
ActiveRecord::ConnectionAdapters::TableDefinition.send(:include, CroppedPaperclip::Schema)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module CroppedPaperclip
|
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
|
+
end
|
22
|
+
|
23
|
+
module TableDefinition
|
24
|
+
def uploadable_attachment(*attachment_names)
|
25
|
+
attachment_names.each do |attachment_name|
|
26
|
+
UPLOAD_COLUMNS.each_pair do |column_name, column_type|
|
27
|
+
column("#{attachment_name}_#{column_name}", column_type)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|