paperclip_attributes 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.
Files changed (87) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +3 -0
  4. data/CHANGELOG.md +7 -0
  5. data/Gemfile +14 -0
  6. data/Gemfile.lock +167 -0
  7. data/MIT-LICENSE +20 -0
  8. data/README.md +105 -0
  9. data/Rakefile +21 -0
  10. data/app/assets/images/paperclip_attributes/.keep +0 -0
  11. data/app/assets/javascripts/paperclip_attributes/.keep +0 -0
  12. data/app/assets/stylesheets/paperclip_attributes/.keep +0 -0
  13. data/app/controllers/.keep +0 -0
  14. data/app/helpers/.keep +0 -0
  15. data/app/mailers/.keep +0 -0
  16. data/app/models/.keep +0 -0
  17. data/app/views/.keep +0 -0
  18. data/bin/rails +12 -0
  19. data/config/routes.rb +2 -0
  20. data/lib/generators/paperclip_attributes/USAGE +17 -0
  21. data/lib/generators/paperclip_attributes/paperclip_attributes_generator.rb +34 -0
  22. data/lib/paperclip/has_attached_file_override.rb +21 -0
  23. data/lib/paperclip_attributes/attributes.rb +34 -0
  24. data/lib/paperclip_attributes/command.rb +44 -0
  25. data/lib/paperclip_attributes/commands/add_photo_dimensions.rb +27 -0
  26. data/lib/paperclip_attributes/commands/add_photo_dominant_color.rb +35 -0
  27. data/lib/paperclip_attributes/engine.rb +15 -0
  28. data/lib/paperclip_attributes/error.rb +21 -0
  29. data/lib/paperclip_attributes/version.rb +3 -0
  30. data/lib/paperclip_attributes.rb +7 -0
  31. data/lib/tasks/paperclip_attributes_tasks.rake +4 -0
  32. data/paperclip_attributes.gemspec +28 -0
  33. data/spec/dummy/README.rdoc +28 -0
  34. data/spec/dummy/Rakefile +6 -0
  35. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  36. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  37. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  38. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  39. data/spec/dummy/app/models/user.rb +6 -0
  40. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  41. data/spec/dummy/bin/bundle +3 -0
  42. data/spec/dummy/bin/rails +4 -0
  43. data/spec/dummy/bin/rake +4 -0
  44. data/spec/dummy/bin/setup +29 -0
  45. data/spec/dummy/config/application.rb +31 -0
  46. data/spec/dummy/config/boot.rb +5 -0
  47. data/spec/dummy/config/database.yml +25 -0
  48. data/spec/dummy/config/environment.rb +5 -0
  49. data/spec/dummy/config/environments/development.rb +41 -0
  50. data/spec/dummy/config/environments/production.rb +79 -0
  51. data/spec/dummy/config/environments/test.rb +42 -0
  52. data/spec/dummy/config/initializers/assets.rb +11 -0
  53. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  54. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  55. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  56. data/spec/dummy/config/initializers/inflections.rb +16 -0
  57. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  58. data/spec/dummy/config/initializers/session_store.rb +3 -0
  59. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  60. data/spec/dummy/config/locales/en.yml +23 -0
  61. data/spec/dummy/config/routes.rb +56 -0
  62. data/spec/dummy/config/secrets.yml +22 -0
  63. data/spec/dummy/config.ru +4 -0
  64. data/spec/dummy/db/development.sqlite3 +0 -0
  65. data/spec/dummy/db/migrate/20160429182529_create_users.rb +9 -0
  66. data/spec/dummy/db/migrate/20160429182620_add_attachment_avatar_to_users.rb +11 -0
  67. data/spec/dummy/db/migrate/20160429205001_add_avatar_dimensions_to_users.rb +6 -0
  68. data/spec/dummy/db/migrate/20160501021321_add_avatar_color_to_users.rb +5 -0
  69. data/spec/dummy/db/schema.rb +29 -0
  70. data/spec/dummy/db/test.sqlite3 +0 -0
  71. data/spec/dummy/log/development.log +83 -0
  72. data/spec/dummy/log/test.log +4753 -0
  73. data/spec/dummy/public/404.html +67 -0
  74. data/spec/dummy/public/422.html +67 -0
  75. data/spec/dummy/public/500.html +66 -0
  76. data/spec/dummy/public/favicon.ico +0 -0
  77. data/spec/dummy/public/system/users/avatars/000/000/001/original/pikachu.png +0 -0
  78. data/spec/dummy/spec/assets/bukowski.jpg +0 -0
  79. data/spec/dummy/spec/assets/pikachu.png +0 -0
  80. data/spec/dummy/spec/assets/video.mp4 +0 -0
  81. data/spec/dummy/spec/factories/users.rb +4 -0
  82. data/spec/dummy/spec/lib/paperclip_attributes/commands/add_photo_dimensions_spec.rb +29 -0
  83. data/spec/dummy/spec/lib/paperclip_attributes/commands/add_photo_dominant_color_spec.rb +27 -0
  84. data/spec/dummy/spec/models/user_spec.rb +53 -0
  85. data/spec/rails_helper.rb +61 -0
  86. data/spec/spec_helper.rb +92 -0
  87. metadata +284 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c5406db14acb8c5918106761f9003cf02aab5085
4
+ data.tar.gz: 3ec4152c1976a21b15f36b11465cc9f8e4bd4098
5
+ SHA512:
6
+ metadata.gz: 8ec98bdf38981b16b226b55c73f73303239a60c4f4d3324bc86318b50c9d5a72c12de0af1ed7c4919ba43994e5c4f9a75387fac0f799f648a5b6307c166e589e
7
+ data.tar.gz: 20fece050c4b3d71d336d445ff1e6effd6597da163187d2155901c34b8bbddf96a4e91126773ac0c43f2765d25057e030dde823c2ab4e985f2ed755eb8efb72c
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ .bundle/
2
+ log/*.log
3
+ pkg/
4
+ spec/dummy/db/*.sqlite3
5
+ spec/dummy/db/*.sqlite3-journal
6
+ spec/dummy/log/*.log
7
+ spec/dummy/tmp/
8
+ spec/dummy/.sass-cache
9
+ spec/dummy/public/system/*
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require rails_helper
3
+ --format=doc
data/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Change Log
2
+ All notable changes to this project will be documented in this file.
3
+ This project adheres to [Semantic Versioning](http://semver.org/).
4
+
5
+ ### v0.1.0
6
+
7
+ * Initial release.
data/Gemfile ADDED
@@ -0,0 +1,14 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Declare your gem's dependencies in paperclip_attributes.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ # Declare any dependencies that are still in development here instead of in
9
+ # your gemspec. These might include edge Rails or gems from your path or
10
+ # Git. Remember to move these dependencies to your gemspec before releasing
11
+ # your gem to rubygems.org.
12
+
13
+ # To use a debugger
14
+ # gem 'byebug', group: [:development, :test]
data/Gemfile.lock ADDED
@@ -0,0 +1,167 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ paperclip_attributes (0.1.0)
5
+ miro (~> 0.3.0)
6
+ paperclip (~> 4.3.6)
7
+ rails (~> 4.2.5.2)
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ actionmailer (4.2.5.2)
13
+ actionpack (= 4.2.5.2)
14
+ actionview (= 4.2.5.2)
15
+ activejob (= 4.2.5.2)
16
+ mail (~> 2.5, >= 2.5.4)
17
+ rails-dom-testing (~> 1.0, >= 1.0.5)
18
+ actionpack (4.2.5.2)
19
+ actionview (= 4.2.5.2)
20
+ activesupport (= 4.2.5.2)
21
+ rack (~> 1.6)
22
+ rack-test (~> 0.6.2)
23
+ rails-dom-testing (~> 1.0, >= 1.0.5)
24
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
25
+ actionview (4.2.5.2)
26
+ activesupport (= 4.2.5.2)
27
+ builder (~> 3.1)
28
+ erubis (~> 2.7.0)
29
+ rails-dom-testing (~> 1.0, >= 1.0.5)
30
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
31
+ activejob (4.2.5.2)
32
+ activesupport (= 4.2.5.2)
33
+ globalid (>= 0.3.0)
34
+ activemodel (4.2.5.2)
35
+ activesupport (= 4.2.5.2)
36
+ builder (~> 3.1)
37
+ activerecord (4.2.5.2)
38
+ activemodel (= 4.2.5.2)
39
+ activesupport (= 4.2.5.2)
40
+ arel (~> 6.0)
41
+ activesupport (4.2.5.2)
42
+ i18n (~> 0.7)
43
+ json (~> 1.7, >= 1.7.7)
44
+ minitest (~> 5.1)
45
+ thread_safe (~> 0.3, >= 0.3.4)
46
+ tzinfo (~> 1.1)
47
+ arel (6.0.3)
48
+ builder (3.2.2)
49
+ chunky_png (1.3.5)
50
+ climate_control (0.0.3)
51
+ activesupport (>= 3.0)
52
+ cocaine (0.5.8)
53
+ climate_control (>= 0.0.3, < 1.0)
54
+ coderay (1.1.1)
55
+ color (1.8)
56
+ concurrent-ruby (1.0.1)
57
+ diff-lcs (1.2.5)
58
+ erubis (2.7.0)
59
+ factory_girl (4.5.0)
60
+ activesupport (>= 3.0.0)
61
+ factory_girl_rails (4.6.0)
62
+ factory_girl (~> 4.5.0)
63
+ railties (>= 3.0.0)
64
+ globalid (0.3.6)
65
+ activesupport (>= 4.1.0)
66
+ i18n (0.7.0)
67
+ json (1.8.3)
68
+ loofah (2.0.3)
69
+ nokogiri (>= 1.5.9)
70
+ mail (2.6.4)
71
+ mime-types (>= 1.16, < 4)
72
+ method_source (0.8.2)
73
+ mime-types (3.0)
74
+ mime-types-data (~> 3.2015)
75
+ mime-types-data (3.2016.0221)
76
+ mimemagic (0.3.0)
77
+ mini_portile2 (2.0.0)
78
+ minitest (5.8.4)
79
+ miro (0.3.0)
80
+ cocaine
81
+ color
82
+ oily_png
83
+ nokogiri (1.6.7.2)
84
+ mini_portile2 (~> 2.0.0.rc2)
85
+ oily_png (1.2.0)
86
+ chunky_png (~> 1.3.1)
87
+ paperclip (4.3.6)
88
+ activemodel (>= 3.2.0)
89
+ activesupport (>= 3.2.0)
90
+ cocaine (~> 0.5.5)
91
+ mime-types
92
+ mimemagic (= 0.3.0)
93
+ pry (0.10.3)
94
+ coderay (~> 1.1.0)
95
+ method_source (~> 0.8.1)
96
+ slop (~> 3.4)
97
+ rack (1.6.4)
98
+ rack-test (0.6.3)
99
+ rack (>= 1.0)
100
+ rails (4.2.5.2)
101
+ actionmailer (= 4.2.5.2)
102
+ actionpack (= 4.2.5.2)
103
+ actionview (= 4.2.5.2)
104
+ activejob (= 4.2.5.2)
105
+ activemodel (= 4.2.5.2)
106
+ activerecord (= 4.2.5.2)
107
+ activesupport (= 4.2.5.2)
108
+ bundler (>= 1.3.0, < 2.0)
109
+ railties (= 4.2.5.2)
110
+ sprockets-rails
111
+ rails-deprecated_sanitizer (1.0.3)
112
+ activesupport (>= 4.2.0.alpha)
113
+ rails-dom-testing (1.0.7)
114
+ activesupport (>= 4.2.0.beta, < 5.0)
115
+ nokogiri (~> 1.6.0)
116
+ rails-deprecated_sanitizer (>= 1.0.1)
117
+ rails-html-sanitizer (1.0.3)
118
+ loofah (~> 2.0)
119
+ railties (4.2.5.2)
120
+ actionpack (= 4.2.5.2)
121
+ activesupport (= 4.2.5.2)
122
+ rake (>= 0.8.7)
123
+ thor (>= 0.18.1, < 2.0)
124
+ rake (11.1.2)
125
+ rspec-core (3.4.4)
126
+ rspec-support (~> 3.4.0)
127
+ rspec-expectations (3.4.0)
128
+ diff-lcs (>= 1.2.0, < 2.0)
129
+ rspec-support (~> 3.4.0)
130
+ rspec-mocks (3.4.1)
131
+ diff-lcs (>= 1.2.0, < 2.0)
132
+ rspec-support (~> 3.4.0)
133
+ rspec-rails (3.4.2)
134
+ actionpack (>= 3.0, < 4.3)
135
+ activesupport (>= 3.0, < 4.3)
136
+ railties (>= 3.0, < 4.3)
137
+ rspec-core (~> 3.4.0)
138
+ rspec-expectations (~> 3.4.0)
139
+ rspec-mocks (~> 3.4.0)
140
+ rspec-support (~> 3.4.0)
141
+ rspec-support (3.4.1)
142
+ slop (3.6.0)
143
+ sprockets (3.6.0)
144
+ concurrent-ruby (~> 1.0)
145
+ rack (> 1, < 3)
146
+ sprockets-rails (3.0.4)
147
+ actionpack (>= 4.0)
148
+ activesupport (>= 4.0)
149
+ sprockets (>= 3.0.0)
150
+ sqlite3 (1.3.11)
151
+ thor (0.19.1)
152
+ thread_safe (0.3.5)
153
+ tzinfo (1.2.2)
154
+ thread_safe (~> 0.1)
155
+
156
+ PLATFORMS
157
+ ruby
158
+
159
+ DEPENDENCIES
160
+ factory_girl_rails (~> 4.6.0)
161
+ paperclip_attributes!
162
+ pry
163
+ rspec-rails (~> 3.4.0)
164
+ sqlite3
165
+
166
+ BUNDLED WITH
167
+ 1.11.2
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2016 Platanus
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.md ADDED
@@ -0,0 +1,105 @@
1
+ # Paperclip Attributes
2
+
3
+ Rails Engine built on top of [Paperclip](https://github.com/thoughtbot/paperclip) gem to add attributes, as columns in your models, related to your attachments.
4
+
5
+ ## Installation
6
+
7
+ Add to your Gemfile:
8
+
9
+ ```ruby
10
+ gem "paperclip_attributes"
11
+ ```
12
+
13
+ ```bash
14
+ bundle install
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ To add new attributes, you need to run the following generator:
20
+
21
+ ```
22
+ rails g paperclip_attributes Model attachment recipe1 recipe2
23
+ ```
24
+
25
+ * `Model`: is the Active Record model containing the attachment you want to add attributes.
26
+ * `attachment`: is the paperclip's attachment name on given model.
27
+ * `recipes (recipe1 recipe2)`: is a list of recipes to extend the attachment. A recipe represents one or more attributes related to the attachment param. You can see a full list of recipes on the section below.
28
+
29
+ The generator, will only create migrations to extend your attachments. So, after run it, you need to do:
30
+
31
+ ```
32
+ rake db:migrate
33
+ ```
34
+
35
+ Then, to enable the functionality in your model, you need to add the recipes to the attachment definition:
36
+
37
+ ```ruby
38
+ class MyModel < ActiveRecord::Base
39
+ has_attached_file :attachment, attributes: [:recipe1, :recipe2]
40
+ end
41
+ ```
42
+
43
+ That's it!
44
+
45
+ The process to extract attributes will be done on `before_save` callback.
46
+
47
+ ## Example
48
+
49
+ ```
50
+ rails g paperclip_attributes User avatar dimensions color
51
+ ```
52
+
53
+ In `User` model:
54
+
55
+ ```ruby
56
+ class User < ActiveRecord::Base
57
+ has_attached_file :avatar, attributes: [:dimensions, :color]
58
+ end
59
+ ```
60
+
61
+ Then, with an `User` instance, you'll be able to do something like this:
62
+
63
+ ```ruby
64
+ user = User.new
65
+ user.avatar = some_file
66
+ user.save!
67
+
68
+ user.avatar_height #=> 200
69
+ user.avatar_width #=> 400
70
+ user.avatar_dominant_color #=> "#FF9900"
71
+
72
+ ```
73
+
74
+ ## Recipes
75
+
76
+ ### For images:
77
+
78
+ #### `dimensions`:
79
+
80
+ * `[attachment]_width`: the original width of the image.
81
+ * `[attachment]_height`: the original height of the image.
82
+
83
+ #### `color`:
84
+
85
+ * `[attachment]_dominant_color`: the predominant color of the image.
86
+
87
+ ## Contributing
88
+
89
+ 1. Fork it
90
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
91
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
92
+ 4. Push to the branch (`git push origin my-new-feature`)
93
+ 5. Create new Pull Request
94
+
95
+ ## Credits
96
+
97
+ Thank you [contributors](https://github.com/platanus/paperclip_attributes/graphs/contributors)!
98
+
99
+ <img src="http://platan.us/gravatar_with_text.png" alt="Platanus" width="250"/>
100
+
101
+ Paperclip Attributes is maintained by [platanus](http://platan.us).
102
+
103
+ ## License
104
+
105
+ Paperclip Attributes is © 2016 platanus, spa. It is free software and may be redistributed under the terms specified in the LICENSE file.
data/Rakefile ADDED
@@ -0,0 +1,21 @@
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 = 'PaperclipAttributes'
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("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+ load 'rails/tasks/statistics.rake'
20
+
21
+ Bundler::GemHelper.install_tasks
File without changes
File without changes
File without changes
File without changes
data/app/helpers/.keep ADDED
File without changes
data/app/mailers/.keep ADDED
File without changes
data/app/models/.keep ADDED
File without changes
data/app/views/.keep ADDED
File without changes
data/bin/rails ADDED
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails 4 gems installed from the root of your application.
3
+
4
+ ENGINE_ROOT = File.expand_path('../..', __FILE__)
5
+ ENGINE_PATH = File.expand_path('../../lib/paperclip_attributes/engine', __FILE__)
6
+
7
+ # Set up gems listed in the Gemfile.
8
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
9
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
10
+
11
+ require 'rails/all'
12
+ require 'rails/engine/commands'
data/config/routes.rb ADDED
@@ -0,0 +1,2 @@
1
+ Rails.application.routes.draw do
2
+ end
@@ -0,0 +1,17 @@
1
+ Description:
2
+ This generator adds to a model's paperclip attachment the attributes passed as params.
3
+ - model: is the Active Record model containing the attachment you want to add attributes.
4
+ - attachment: is the paperclip's attachment on given model.
5
+ - recipes: is a list of recipes to extend the attachment. A recipe represents one or more attributes related to the attachment param.
6
+
7
+ Example:
8
+ rails generate paperclip_attributes User avatar dimensions
9
+
10
+ This will create a migration at db/migrate like this:
11
+
12
+ class AddAvatarDimensionsToUsers < ActiveRecord::Migration
13
+ def change
14
+ add_column :users, :width, :integer
15
+ add_column :users, :height, :integer
16
+ end
17
+ end
@@ -0,0 +1,34 @@
1
+ class PaperclipAttributesGenerator < Rails::Generators::Base
2
+ VALID_ATTRIBUTES = %w(dimensions color).freeze
3
+
4
+ source_root File.expand_path('../templates', __FILE__)
5
+
6
+ argument :model, required: true, banner: "model"
7
+ argument :attachment, required: true, banner: "attachment"
8
+ argument :recipes, required: true, type: :array, banner: "recipe_one recipe_two..."
9
+
10
+ def generate_migration
11
+ generate "migration #{migration_name} #{migration_attributes}"
12
+ end
13
+
14
+ private
15
+
16
+ def migration_attributes
17
+ recipes.inject({}) do |result, attribute|
18
+ fail "Invalid attribute given" unless VALID_ATTRIBUTES.include?(attribute)
19
+ case attribute.to_sym
20
+ when :dimensions then result[:width] = result[:height] = :integer
21
+ when :color then result[:dominant_color] = :string
22
+ end
23
+ result
24
+ end.map { |k, v| "#{attachment}_#{k}:#{v}" }.join(" ")
25
+ end
26
+
27
+ def migration_name
28
+ "add_#{attachment}_#{recipes.join('_')}_to_#{table_name}"
29
+ end
30
+
31
+ def table_name
32
+ model.underscore.pluralize
33
+ end
34
+ end
@@ -0,0 +1,21 @@
1
+ module ::Paperclip
2
+ module ClassMethods
3
+ def has_attached_file(name, options = {})
4
+ add_attachment_attributes(name, options)
5
+ HasAttachedFile.define_on(self, name, options)
6
+ end
7
+
8
+ def add_attachment_attributes(name, options)
9
+ @attachmets_recipes ||= {}
10
+ @attachmets_recipes[name.to_sym] = options.fetch(:attributes, [])
11
+ end
12
+
13
+ def attachmets_recipes
14
+ @attachmets_recipes
15
+ end
16
+
17
+ def attachments_names
18
+ attachmets_recipes.keys
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,34 @@
1
+ module PaperclipAttributes
2
+ module Attributes
3
+ extend ActiveSupport::Concern
4
+
5
+ RECIPES = {
6
+ color: PaperclipAttributes::Commands::AddPhotoDominantColor,
7
+ dimensions: PaperclipAttributes::Commands::AddPhotoDimensions
8
+ }
9
+
10
+ included do
11
+ def changed_attachments_names
12
+ self.class.attachments_names.select do |column|
13
+ send("#{column}_updated_at_changed?")
14
+ end
15
+ end
16
+
17
+ def execute_attachment_recipes(attachment)
18
+ self.class.attachmets_recipes[attachment].each do |recipe|
19
+ cmd = RECIPES[recipe]
20
+ raise PaperclipAttributes::Error::UnknownRecipe.new unless cmd
21
+ cmd.new(self, attachment).perform
22
+ end
23
+ end
24
+
25
+ before_save do
26
+ changed_attachments_names.each do |changed_attachment|
27
+ execute_attachment_recipes(changed_attachment)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ ActiveRecord::Base.send(:include, PaperclipAttributes::Attributes)
@@ -0,0 +1,44 @@
1
+ module PaperclipAttributes
2
+ module Command
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ attr_reader :model, :column
7
+
8
+ def initialize(model, column)
9
+ @model = model
10
+ @column = column
11
+ end
12
+
13
+ def perform
14
+ raise PaperclipAttributes::Error::PerformNotImplemented.new
15
+ end
16
+
17
+ def image?
18
+ content_type = model.send("#{column}_content_type")
19
+ content_type =~ %r{^(image|(x-)?application)/(bmp|gif|jpeg|jpg|pjpeg|png|x-png)$}
20
+ end
21
+
22
+ def with_tempfile(&block)
23
+ tempfile = model.send(column).queued_for_write[:original]
24
+ return if tempfile.nil?
25
+ block.call(tempfile)
26
+ end
27
+
28
+ def with_img_tempfile(&block)
29
+ return unless image?
30
+ with_tempfile(&block)
31
+ end
32
+
33
+ def set_attribute(attribute, value)
34
+ writter_method = "#{column}_#{attribute}="
35
+
36
+ if !model.respond_to?(writter_method)
37
+ raise PaperclipAttributes::Error::AttributeNotFound.new
38
+ end
39
+
40
+ model.send(writter_method, value)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,27 @@
1
+ module PaperclipAttributes
2
+ module Commands
3
+ class AddPhotoDimensions
4
+ include PaperclipAttributes::Command
5
+
6
+ def perform
7
+ dimensions = extract_dimensions
8
+ add_dimensions_to_model(dimensions)
9
+ end
10
+
11
+ private
12
+
13
+ def extract_dimensions
14
+ with_img_tempfile do |tempfile|
15
+ geometry = Paperclip::Geometry.from_file(tempfile)
16
+ { width: geometry.width.to_i, height: geometry.height.to_i }
17
+ end
18
+ end
19
+
20
+ def add_dimensions_to_model(dimensions)
21
+ return unless dimensions
22
+ set_attribute(:width, dimensions[:width])
23
+ set_attribute(:height, dimensions[:height])
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+ module PaperclipAttributes
2
+ module Commands
3
+ class AddPhotoDominantColor
4
+ include PaperclipAttributes::Command
5
+
6
+ def perform
7
+ color = calculate_dominant_color
8
+ set_attribute(:dominant_color, color)
9
+ end
10
+
11
+ private
12
+
13
+ def calculate_dominant_color
14
+ with_img_tempfile do |tempfile|
15
+ Miro.options[:color_count] = 1
16
+ Miro.options[:method] = "histogram"
17
+ colors = Miro::DominantColors.new(tempfile.path)
18
+ lighten_color(colors.to_hex.first)
19
+ end
20
+ rescue
21
+ nil
22
+ end
23
+
24
+ def lighten_color(hex_color, amount = 0.2)
25
+ hex_color.delete!("#")
26
+
27
+ rgb = hex_color.scan(/../).map(&:hex).map do |color|
28
+ [(color.to_i + 255 * amount).round, 255].min
29
+ end
30
+
31
+ "#%02x%02x%02x" % rgb
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ module PaperclipAttributes
2
+ class Engine < ::Rails::Engine
3
+ config.generators do |g|
4
+ g.test_framework false
5
+ end
6
+
7
+ initializer "initialize" do
8
+ require_relative "./error"
9
+ require_relative "./command"
10
+ require_relative "./commands/add_photo_dimensions"
11
+ require_relative "./commands/add_photo_dominant_color"
12
+ require_relative "./attributes"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,21 @@
1
+ module PaperclipAttributes
2
+ module Error
3
+ class UnknownRecipe < Exception
4
+ def initialize
5
+ super("the given recipe is invalid")
6
+ end
7
+ end
8
+
9
+ class AttributeNotFound < Exception
10
+ def initialize
11
+ super("you need to execute the paperclip_attributes generator with recipes you need")
12
+ end
13
+ end
14
+
15
+ class PerformNotImplemented < Exception
16
+ def initialize
17
+ super("override perform method in host class")
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module PaperclipAttributes
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,7 @@
1
+ require "paperclip"
2
+ require "miro"
3
+ require "paperclip_attributes/engine"
4
+ require_relative "./paperclip/has_attached_file_override"
5
+
6
+ module PaperclipAttributes
7
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :paperclip_attributes do
3
+ # # Task goes here
4
+ # end