attachs 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +98 -0
- data/Rakefile +34 -0
- data/app/controllers/attachs/presets_controller.rb +17 -0
- data/config/locales/en.yml +8 -0
- data/config/locales/es.yml +8 -0
- data/config/routes.rb +5 -0
- data/lib/attachs.rb +16 -0
- data/lib/attachs/active_record/base.rb +145 -0
- data/lib/attachs/engine.rb +7 -0
- data/lib/attachs/magick/image.rb +85 -0
- data/lib/attachs/railtie.rb +20 -0
- data/lib/attachs/storages/local.rb +61 -0
- data/lib/attachs/storages/s3.rb +77 -0
- data/lib/attachs/types/file.rb +113 -0
- data/lib/attachs/types/image.rb +40 -0
- data/lib/attachs/validators/attachment_content_type_validator.rb +11 -0
- data/lib/attachs/validators/attachment_presence_validator.rb +9 -0
- data/lib/attachs/validators/attachment_size_validator.rb +27 -0
- data/lib/attachs/validators/base.rb +13 -0
- data/lib/attachs/version.rb +5 -0
- data/lib/generators/attachs/s3/config_generator.rb +13 -0
- data/lib/generators/attachs/s3/templates/s3.yml +16 -0
- data/lib/tasks/attachs_tasks.rake +71 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/all_attached.rb +16 -0
- data/test/dummy/app/models/file_attached.rb +3 -0
- data/test/dummy/app/models/image_attached.rb +3 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +29 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20130820222342_create_file_attacheds.rb +9 -0
- data/test/dummy/db/migrate/20130820222355_create_image_attacheds.rb +9 -0
- data/test/dummy/db/migrate/20130820222534_create_all_attacheds.rb +19 -0
- data/test/dummy/db/schema.rb +44 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +28 -0
- data/test/dummy/log/test.log +8545 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/public/uploads/files/file.txt +1 -0
- data/test/dummy/public/uploads/images/big/image.jpg +0 -0
- data/test/dummy/public/uploads/images/original/image.jpg +0 -0
- data/test/dummy/public/uploads/images/small/image.jpg +0 -0
- data/test/dummy/test/fixtures/file.txt +1 -0
- data/test/dummy/test/fixtures/file_big.txt +1 -0
- data/test/dummy/test/fixtures/file_empty.txt +1 -0
- data/test/dummy/test/fixtures/image.jpg +0 -0
- data/test/dummy/test/fixtures/image_big.jpg +0 -0
- data/test/dummy/test/fixtures/image_empty.jpg +0 -0
- data/test/local_file_record_test.rb +20 -0
- data/test/local_file_string_test.rb +23 -0
- data/test/local_file_upload_test.rb +30 -0
- data/test/local_generate_test.rb +25 -0
- data/test/local_image_record_test.rb +25 -0
- data/test/local_image_string_test.rb +34 -0
- data/test/local_image_upload_test.rb +27 -0
- data/test/local_records_test.rb +52 -0
- data/test/local_validators_test.rb +71 -0
- data/test/s3_file_record_tes.rb +21 -0
- data/test/s3_file_string_tes.rb +24 -0
- data/test/s3_file_upload_tes.rb +31 -0
- data/test/s3_image_record_tes.rb +26 -0
- data/test/s3_image_string_tes.rb +31 -0
- data/test/s3_image_upload_tes.rb +28 -0
- data/test/s3_records_tes.rb +56 -0
- data/test/s3_validators_tes.rb +72 -0
- data/test/test_helper.rb +49 -0
- metadata +250 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 54ae49b0a6e0cb9b5e170ac1b1559dd6e614055b
|
4
|
+
data.tar.gz: 273fcb21962f1b648de5d86064775d9b9b0dfddb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 2512efff14fad943789edf5867e952c558fed32fb25d31f4fde483015784d1cd2d5603075a2e33109b1b0fd8b3fce7ad8a74f0a2291265d60306f1cdadc8f6cd
|
7
|
+
data.tar.gz: c089f8e848fd436b8491144bf3a0ef57c00be075145cd8f495e6834faaf9333a1774efb37d621da9639da77dac5265a7572e0a7c417a340a69e5aeb542e9ab6b
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2013 Mattways
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
{<img src="https://codeclimate.com/github/mattways/attachs.png" />}[https://codeclimate.com/github/mattways/attachs] {<img src="https://travis-ci.org/mattways/attachs.png?branch=master" alt="Build Status" />}[https://travis-ci.org/mattways/attachs] {<img src="https://gemnasium.com/mattways/attachs.png" alt="Dependency Status" />}[https://gemnasium.com/mattways/attachs]
|
2
|
+
|
3
|
+
= Attachs
|
4
|
+
|
5
|
+
Minimalistic toolkit to attach file and images to records.
|
6
|
+
|
7
|
+
= Install
|
8
|
+
|
9
|
+
Put this line in your Gemfile:
|
10
|
+
gem 'attachs'
|
11
|
+
|
12
|
+
Then bundle:
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
ImageMagick must be install, you can install it with homebrew:
|
16
|
+
brew install imagemagick
|
17
|
+
|
18
|
+
= Usage
|
19
|
+
|
20
|
+
Mount the engine at the end of you routes.rb (only if you are using local storage):
|
21
|
+
mount Attachs:Engine: '/' # Will be use to generate on the fly missing image presets
|
22
|
+
|
23
|
+
Add the column to your table (just a string):
|
24
|
+
create_table :models do |t|
|
25
|
+
t.string :attr
|
26
|
+
end
|
27
|
+
|
28
|
+
If you need a file:
|
29
|
+
class Model < ActiveRecord::Base
|
30
|
+
has_attached_file :attr, default: 'file.txt'
|
31
|
+
end
|
32
|
+
|
33
|
+
If you need a image:
|
34
|
+
class Model < ActiveRecord::Base
|
35
|
+
has_attached_image :attr, presets: [:small, :big], default: 'assets/image.jpg'
|
36
|
+
end
|
37
|
+
|
38
|
+
Define presets in your application.rb
|
39
|
+
config.attachs.presets = {
|
40
|
+
big: { method: :fit, width: 1024, height: 768 }, # Fit will scale the image until it fit in the space without cropping
|
41
|
+
small: { method: :fill, width: 120, height: :120 }, # Fill will scale the image to fill all the space and then crop
|
42
|
+
custom: proc { |image| image.convert resize: '100x100' } # ImageMagick wrapper to do whatever you want
|
43
|
+
}
|
44
|
+
config.attachs.default_presets = [:small] # Define the default presets for all models with attached images
|
45
|
+
config.attachs.storage = :local # The default it's local, you can use :s3 as well
|
46
|
+
|
47
|
+
If you want to use S3 create a s3.yml config file with this generator and complete it:
|
48
|
+
rails g attachs:s3:config
|
49
|
+
|
50
|
+
The validation works very similar to paperclip:
|
51
|
+
class Model < ActiveRecord::Base
|
52
|
+
has_attached_file :attr
|
53
|
+
validates :attr, attachment_presence: true, attachment_size: { in: 0..4.megabytes }, attachment_content_type: { in: ['txt'] }
|
54
|
+
end
|
55
|
+
|
56
|
+
If you want to translate the errores the keys are:
|
57
|
+
errors.messages.attachment_presence
|
58
|
+
errors.messages.attachment_size_in # :max and :min
|
59
|
+
errors.messages.attachment_size_less_than # :count
|
60
|
+
errors.messages.attachment_size_greater_than # :count
|
61
|
+
errors.messages.attachment_content_type # :types
|
62
|
+
|
63
|
+
In your views:
|
64
|
+
a{ href: record.file.url } # To get the file url
|
65
|
+
a{ href: record.image.url } # To get the original image
|
66
|
+
a{ href: record.image.url(:big) } # To get the a thumb
|
67
|
+
|
68
|
+
In your forms:
|
69
|
+
= f.file_field :attr
|
70
|
+
|
71
|
+
If your file it's optional:
|
72
|
+
= f.check_box :delete_attr
|
73
|
+
|
74
|
+
= FAQ
|
75
|
+
|
76
|
+
== How can I use a cdn with this plugin?
|
77
|
+
|
78
|
+
Define a base url in your application.rb:
|
79
|
+
config.attachs.base_url = 'http://cdn.example.com'
|
80
|
+
|
81
|
+
== How can I automatically create buckets?
|
82
|
+
|
83
|
+
Use this rake task after create the s3.yml file:
|
84
|
+
rake attachs:s3:buckets:create
|
85
|
+
|
86
|
+
== How can I clean a preset?
|
87
|
+
|
88
|
+
Use this rake task:
|
89
|
+
rake attachs:presets:clean MODEL=models PRESETS=first_preset,second_preset
|
90
|
+
|
91
|
+
== How can I refresh a preset?
|
92
|
+
|
93
|
+
Use this rake task:
|
94
|
+
rake attachs:presets:refresh MODEL=models PRESETS=first_preset,second_preset
|
95
|
+
|
96
|
+
== How can I migrate from versions before 0.3.0
|
97
|
+
|
98
|
+
All will work the same except from the name of the config parameter, replace uploads with attachs.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
begin
|
2
|
+
require 'bundler/setup'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'rdoc/task'
|
8
|
+
|
9
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
10
|
+
rdoc.rdoc_dir = 'rdoc'
|
11
|
+
rdoc.title = 'Attachs'
|
12
|
+
rdoc.options << '--line-numbers'
|
13
|
+
rdoc.rdoc_files.include('README.rdoc')
|
14
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
15
|
+
end
|
16
|
+
|
17
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
18
|
+
load 'rails/tasks/engine.rake'
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
Bundler::GemHelper.install_tasks
|
23
|
+
|
24
|
+
require 'rake/testtask'
|
25
|
+
|
26
|
+
Rake::TestTask.new(:test) do |t|
|
27
|
+
t.libs << 'lib'
|
28
|
+
t.libs << 'test'
|
29
|
+
t.pattern = 'test/**/*_test.rb'
|
30
|
+
t.verbose = false
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
task default: :test
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Attachs
|
2
|
+
class PresetsController < ActionController::Base
|
3
|
+
|
4
|
+
def generate
|
5
|
+
filename = "#{params[:image]}.#{params[:format]}"
|
6
|
+
preset = params[:preset].gsub('-', '_').to_sym
|
7
|
+
if Rails.application.config.attachs.presets.has_key? preset
|
8
|
+
image = Attachs::Types::Image.new(filename)
|
9
|
+
if image.exists? and !image.exists?(preset)
|
10
|
+
image.generate_preset preset
|
11
|
+
redirect_to image.url(params[:preset]), cb: Random.rand(100000)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
en:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
attachment_presence: "can't be blank"
|
5
|
+
attachment_content_type: "the allowed types are: %{types}"
|
6
|
+
attachment_size_less_than: "size must be less than %{count}"
|
7
|
+
attachment_size_greater_than: "size must be greater than %{count}"
|
8
|
+
attachment_size_in: "size must be between %{min} and %{max}"
|
@@ -0,0 +1,8 @@
|
|
1
|
+
es:
|
2
|
+
errors:
|
3
|
+
messages:
|
4
|
+
attachment_presence: "no puede estar vacío"
|
5
|
+
attachment_content_type: "los formatos permitidos son: %{types}"
|
6
|
+
attachment_size_less_than: "debe pesar menos de %{count}"
|
7
|
+
attachment_size_greater_than: "debe pesar más de %{count}"
|
8
|
+
attachment_size_in: "debe pesar entre %{min} y %{max}"
|
data/config/routes.rb
ADDED
data/lib/attachs.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'attachs/active_record/base'
|
2
|
+
require 'attachs/magick/image'
|
3
|
+
require 'attachs/storages/local'
|
4
|
+
require 'attachs/storages/s3'
|
5
|
+
require 'attachs/types/file'
|
6
|
+
require 'attachs/types/image'
|
7
|
+
require 'attachs/validators/base'
|
8
|
+
require 'attachs/validators/attachment_content_type_validator'
|
9
|
+
require 'attachs/validators/attachment_presence_validator'
|
10
|
+
require 'attachs/validators/attachment_size_validator'
|
11
|
+
require 'attachs/engine'
|
12
|
+
require 'attachs/railtie'
|
13
|
+
require 'attachs/version'
|
14
|
+
|
15
|
+
module Attachs
|
16
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
module Attachs
|
2
|
+
module ActiveRecord
|
3
|
+
module Base
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
singleton_class.class_eval do
|
8
|
+
[:file, :image].each do |type|
|
9
|
+
name = :"has_attached_#{type}"
|
10
|
+
define_method name do |*args|
|
11
|
+
options = args.extract_options!
|
12
|
+
options[:type] = type
|
13
|
+
define_attachment *args.append(options)
|
14
|
+
end
|
15
|
+
alias_method :"attached_#{type}", name
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
attr_reader :stored_attachments, :deleted_attachments
|
23
|
+
|
24
|
+
def attachments
|
25
|
+
@attachments ||= {}
|
26
|
+
end
|
27
|
+
|
28
|
+
def build_attachment_instance(source, options)
|
29
|
+
klass = options.has_key?(:type) ? options[:type].to_s.classify : 'File'
|
30
|
+
Attachs::Types.const_get(klass).new source, options
|
31
|
+
end
|
32
|
+
|
33
|
+
def check_changed_attachments
|
34
|
+
@stored_attachments = []
|
35
|
+
@deleted_attachments = []
|
36
|
+
self.class.attachments.each do |attr, options|
|
37
|
+
if changed_attributes.has_key? attr.to_s
|
38
|
+
stored = attributes[attr.to_s]
|
39
|
+
deleted = changed_attributes[attr.to_s]
|
40
|
+
add_changed_attachment stored, options, :stored if stored.present?
|
41
|
+
add_changed_attachment deleted, options, :deleted if deleted.present?
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def iterate_attachments
|
47
|
+
self.class.attachments.each do |attr, options|
|
48
|
+
next unless instance = send(attr)
|
49
|
+
yield instance
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def add_changed_attachment(source, options, type)
|
54
|
+
(type == :stored ? stored_attachments : deleted_attachments) << (source.is_a?(String) ? build_attachment_instance(source, options) : source)
|
55
|
+
end
|
56
|
+
|
57
|
+
def store_attachments
|
58
|
+
iterate_attachments { |a| a.store }
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete_attachments
|
62
|
+
iterate_attachments { |a| a.delete }
|
63
|
+
end
|
64
|
+
|
65
|
+
def remove_stored_attachments
|
66
|
+
stored_attachments.each { |a| a.delete }
|
67
|
+
end
|
68
|
+
|
69
|
+
def remove_deleted_attachments
|
70
|
+
deleted_attachments.each { |a| a.delete }
|
71
|
+
end
|
72
|
+
|
73
|
+
module ClassMethods
|
74
|
+
|
75
|
+
attr_reader :attachments
|
76
|
+
|
77
|
+
def inherited(subclass)
|
78
|
+
subclass.instance_variable_set(:@attachments, @attachments)
|
79
|
+
super
|
80
|
+
end
|
81
|
+
|
82
|
+
def attachable?
|
83
|
+
attachments.present?
|
84
|
+
end
|
85
|
+
|
86
|
+
protected
|
87
|
+
|
88
|
+
def define_attachment(*args)
|
89
|
+
options = args.extract_options!
|
90
|
+
make_attachable unless attachable?
|
91
|
+
args.each do |attr|
|
92
|
+
define_attachable_attribute_methods attr.to_sym, options
|
93
|
+
define_default_validations attr.to_sym, options
|
94
|
+
attachments[attr.to_sym] = options
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def make_attachable
|
99
|
+
before_save :store_attachments, :check_changed_attachments
|
100
|
+
after_save :remove_deleted_attachments
|
101
|
+
before_destroy :delete_attachments
|
102
|
+
after_rollback :remove_stored_attachments
|
103
|
+
@attachments = {}
|
104
|
+
end
|
105
|
+
|
106
|
+
def define_default_validations(attr, options)
|
107
|
+
default_validations = Rails.application.config.attachs.default_validations[options[:type]]
|
108
|
+
validates attr, default_validations.dup if default_validations.present?
|
109
|
+
end
|
110
|
+
|
111
|
+
def define_attachable_attribute_methods(attr, options)
|
112
|
+
['set','get'].each { |method| send "define_attachable_attribute_method_#{method}", attr, options }
|
113
|
+
end
|
114
|
+
|
115
|
+
def define_attachable_attribute_method_set(attr, options)
|
116
|
+
define_method "#{attr}=" do |value|
|
117
|
+
if value.is_a? ActionDispatch::Http::UploadedFile or value.is_a? Rack::Test::UploadedFile or (value.is_a? String and value =~ /^[a-zA-Z0-9_-]+\.[a-zA-z]+$/)
|
118
|
+
attachment = build_attachment_instance(value, options)
|
119
|
+
attachments[attr] = attachment
|
120
|
+
write_attribute attr, attachment.filename
|
121
|
+
end
|
122
|
+
end
|
123
|
+
define_method "delete_#{attr}=" do |value|
|
124
|
+
if attribute_present? attr and value == '1'
|
125
|
+
send "#{attr}_will_change!"
|
126
|
+
attachments[attr] = nil
|
127
|
+
attributes[attr.to_s] = nil
|
128
|
+
end
|
129
|
+
instance_variable_set("@delete_#{attr}".to_sym, value)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
def define_attachable_attribute_method_get(attr, options)
|
134
|
+
define_method attr do
|
135
|
+
return attachments[attr] if attachments.has_key? attr
|
136
|
+
return nil if super().nil? and not options.has_key? :default
|
137
|
+
attachments[attr] = build_attachment_instance(super(), options)
|
138
|
+
end
|
139
|
+
attr_reader :"delete_#{attr}"
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Attachs
|
2
|
+
module Magick
|
3
|
+
class Image
|
4
|
+
|
5
|
+
def initialize(source, output=nil)
|
6
|
+
@source = source
|
7
|
+
@output = output
|
8
|
+
end
|
9
|
+
|
10
|
+
def convert(args)
|
11
|
+
tokens = [convert? ? 'convert' : 'mogrify']
|
12
|
+
file_to_tokens tokens
|
13
|
+
args_to_tokens args, tokens
|
14
|
+
tokens << "\"#{output}\"" if convert?
|
15
|
+
success, output = run(tokens)
|
16
|
+
if block_given?
|
17
|
+
yield success, output
|
18
|
+
else
|
19
|
+
success
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def identify(args)
|
24
|
+
tokens = ['identify']
|
25
|
+
args_to_tokens args, tokens
|
26
|
+
file_to_tokens tokens
|
27
|
+
success, output = run(tokens)
|
28
|
+
if block_given?
|
29
|
+
yield success, output
|
30
|
+
else
|
31
|
+
success
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def dimensions
|
36
|
+
identify(format: '%wx%h') do |success, output|
|
37
|
+
success ? output.chomp.split('x').map(&:to_i) : []
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def width
|
42
|
+
dimensions[0]
|
43
|
+
end
|
44
|
+
|
45
|
+
def height
|
46
|
+
dimensions[1]
|
47
|
+
end
|
48
|
+
|
49
|
+
def resize_to_fill(max_width, max_height)
|
50
|
+
width, height = dimensions
|
51
|
+
scale = [max_width.to_f/width, max_height.to_f/height].max
|
52
|
+
convert resize: "#{(scale*width).ceil}x#{(scale*height).ceil}", gravity: 'center', crop: "#{max_width}x#{max_height}+0+0"
|
53
|
+
end
|
54
|
+
|
55
|
+
def resize_to_fit(max_width, max_height)
|
56
|
+
width, height = dimensions
|
57
|
+
scale = [max_width.to_f/width, max_height.to_f/height].reject{ |s| s==0 }.min
|
58
|
+
convert resize: "#{(scale*width).ceil}x#{(scale*height).ceil}", gravity: 'center'
|
59
|
+
end
|
60
|
+
|
61
|
+
protected
|
62
|
+
|
63
|
+
attr_reader :source, :output
|
64
|
+
|
65
|
+
def convert?
|
66
|
+
!(output.nil? and ::File.exists?(output))
|
67
|
+
end
|
68
|
+
|
69
|
+
def file_to_tokens(tokens)
|
70
|
+
tokens << (convert? ? "\"#{source}\"" : output)
|
71
|
+
end
|
72
|
+
|
73
|
+
def args_to_tokens(args, tokens)
|
74
|
+
args.each { |k, v| tokens << "-#{k} #{v}" }
|
75
|
+
end
|
76
|
+
|
77
|
+
def run(tokens)
|
78
|
+
output = `#{tokens.join(' ')}`
|
79
|
+
success = $?.exitstatus == 0
|
80
|
+
[success, output]
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|