papercrop 0.0.2 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of papercrop might be problematic. Click here for more details.

data/README.md CHANGED
@@ -0,0 +1,56 @@
1
+
2
+ ## Papercrop
3
+ An easy extension for Paperclip to crop your image uploads using jCrop.
4
+
5
+ ### Installation
6
+ Include papercrop in your Gemfile or install it by hand
7
+
8
+ gem install papercrop
9
+
10
+ You need to add the required files in your assets...
11
+
12
+ In your application.js
13
+
14
+ //= require jquery
15
+ //= require jquery.jcrop
16
+ //= require papercrop
17
+
18
+ In your application.css
19
+
20
+ *= require jquery.jcrop
21
+
22
+ ### Using Papercrop
23
+ You are a few steps away to start cropping attachments. Let's start with the model, a user with avatar:
24
+
25
+ has_attached_file :avatar, :styles => {:thumb => '50x50', :medium => '100x100'}
26
+ crop_attached_file :avatar
27
+
28
+ By default, the crop area and the preview box will have an aspect ratio of 1:1.
29
+ You can modify that by passing a new aspect.
30
+
31
+ crop_attached_file :snapshot, :aspect => "16:9"
32
+
33
+ On the controller you can render a view after user creation, create a simple crop action, etc... whatever you like the most. Inside the form of a persisted user:
34
+
35
+ <%= form_for @user do |f| %>
36
+ <%= f.cropbox :avatar %>
37
+ <%= f.crop_preview :avatar %>
38
+ <%= f.submit 'Save' %>
39
+ <% end %>
40
+
41
+ Both helpers accept a :width option to customize their dimensions. The preview box has width 100 by default but the cropbox is unlimited in size (takes the original image width), so setting the cropbox width is interesting to avoid layout breaks with huge images.
42
+
43
+ <%= form_for @user do |f| %>
44
+ <%= f.cropbox :avatar, :width => 500 %>
45
+ <%= f.crop_preview :avatar, :width => 150 %>
46
+ <%= f.submit 'Save' %>
47
+ <% end %>
48
+
49
+ Regardless of the width, the preview box and the cropping area will have the aspect ratio defined in the model (1:1 by default)
50
+
51
+ That's all!
52
+
53
+ #### Credits and resources
54
+ * [Thoughtbot's Paperclip](https://github.com/thoughtbot/paperclip/)
55
+ * [Deep Liquid's JCrop](http://deepliquid.com/content/Jcrop.html)
56
+ * And Ryan Bates' [Railscast#182](http://railscasts.com/episodes/182-cropping-images/), which has inspired this gem
@@ -1,3 +1,5 @@
1
+ var jcrop_api;
2
+
1
3
  (function() {
2
4
  $(document).ready(function() {
3
5
  $('div[id$=_cropbox]').each(function() {
@@ -35,7 +37,7 @@
35
37
  setSelect : [0, 0, 500, 500],
36
38
  aspectRatio : aspect,
37
39
  boxWidth : $("input[id$='_" + attachment + "_box_w']").val()
38
- });
40
+ }, function(){ jcrop_api = this; });
39
41
  });
40
42
  });
41
43
  }).call(this);
@@ -8,6 +8,16 @@ module Papercrop
8
8
 
9
9
  module ClassMethods
10
10
 
11
+ # Initializes attachment cropping in your model
12
+ #
13
+ # crop_attached_file :avatar
14
+ #
15
+ # You can also define an aspect ratio for the crop and preview box through opts[:aspect]
16
+ #
17
+ # crop_attached_file :avatar, :aspect => "4:3"
18
+ #
19
+ # @param attachment_name [Symbol] The name of the desired attachment to crop
20
+ # @param opts [Hash]
11
21
  def crop_attached_file(attachment_name, opts = {})
12
22
  [:crop_x, :crop_y, :crop_w, :crop_h, :original_w, :original_h, :box_w, :aspect].each do |a|
13
23
  attr_accessor :"#{attachment_name}_#{a}"
@@ -30,12 +40,12 @@ module Papercrop
30
40
 
31
41
  after_update :"reprocess_to_crop_#{attachment_name}_attachment"
32
42
  end
33
-
34
43
  end
35
44
 
36
45
 
37
46
  module InstanceMethods
38
47
 
48
+ # Asks if the attachment received a crop process
39
49
  def cropping?(attachment_name)
40
50
  !self.send(:"#{attachment_name}_crop_x").blank? &&
41
51
  !self.send(:"#{attachment_name}_crop_y").blank? &&
@@ -44,12 +54,18 @@ module Papercrop
44
54
  end
45
55
 
46
56
 
57
+ # Returns a Paperclip::Geometry object from a named attachment
58
+ #
59
+ # @param attachment_name [Symbol]
60
+ # @param style [Symbol] attachment style, :original by default
61
+ # @return Paperclip::Geometry
47
62
  def image_geometry(attachment_name, style = :original)
48
63
  @geometry ||= {}
49
64
  @geometry[style] ||= Paperclip::Geometry.from_file(self.send(attachment_name).path(style))
50
65
  end
51
66
 
52
67
 
68
+ # Uses method missing to reprocess the attachment callback
53
69
  def method_missing(method, *args)
54
70
  if method.to_s =~ /(reprocess_to_crop_)(\S{1,})(_attachment)/
55
71
  reprocess_cropped_attachment(
@@ -62,8 +78,9 @@ module Papercrop
62
78
 
63
79
  private
64
80
 
81
+ # Reprocess the attachment after cropping
65
82
  def reprocess_cropped_attachment(attachment_name)
66
- self.send(attachment_name.to_sym).reprocess! if cropping? attachment_name
83
+ self.send(attachment_name.to_sym).reprocess! if cropping?(attachment_name)
67
84
  end
68
85
 
69
86
  end
@@ -1,6 +1,15 @@
1
1
  module Papercrop
2
2
  module Helpers
3
3
 
4
+ # Form helper to render the cropping preview box of an attachment.
5
+ # Box width can be handled by setting the :width option.
6
+ # Width is 100 by default. Height is calculated by the aspect ratio.
7
+ #
8
+ # crop_preview :avatar
9
+ # crop_preview :avatar, :width => 150
10
+ #
11
+ # @param attachment [Symbol] attachment name
12
+ # @param opts [Hash]
4
13
  def crop_preview(attachment, opts = {})
5
14
  attachment = attachment.to_sym
6
15
  width = opts[:width] || 100
@@ -19,6 +28,14 @@ module Papercrop
19
28
  end
20
29
 
21
30
 
31
+ # Form helper to render the main cropping box of an attachment.
32
+ # Loads the original image. Initially the cropbox has no limits on dimensions, showing the image at full size.
33
+ # You can restrict it by setting the :width option to the width you want.
34
+ #
35
+ # cropbox :avatar, :width => 650
36
+ #
37
+ # @param attachment [Symbol] attachment name
38
+ # @param opts [Hash]
22
39
  def cropbox(attachment, opts = {})
23
40
  attachment = attachment.to_sym
24
41
  original_width = self.object.image_geometry(attachment, :original).width
@@ -0,0 +1,29 @@
1
+ require "spec_helper"
2
+
3
+ describe "Image crop with JS", :js => true do
4
+
5
+ after do
6
+ Landscape.destroy_all
7
+ end
8
+
9
+
10
+ it "crops an image with javascript" do
11
+ visit landscapes_path
12
+
13
+ click_link "New Landscape"
14
+
15
+ fill_in "Name", :with => "Mountains"
16
+ find("#landscape_picture").native.send_keys(File.expand_path("../../../test_app/test/fixtures/matterhorn.jpg", __FILE__))
17
+ click_button "Create Landscape"
18
+
19
+ sleep 2
20
+ page.execute_script("jcrop_api.setSelect([300, 200, 700, 500])")
21
+ page.execute_script('if ($("#picture_crop_y").val() == "199"){$("#picture_crop_y").val("200")}')
22
+ page.execute_script('if ($("#picture_crop_w").val() == "399"){$("#picture_crop_w").val("400")}')
23
+
24
+ click_button "Crop image"
25
+
26
+ sleep 1
27
+ compare_images(CROPPED_IMG_PATH, Landscape.last.picture.path(:medium)).should eq(0.0)
28
+ end
29
+ end
@@ -0,0 +1,39 @@
1
+ require "spec_helper"
2
+
3
+ describe "Image crop" do
4
+
5
+ after do
6
+ Landscape.destroy_all
7
+ end
8
+
9
+
10
+ it "crops an image" do
11
+ visit landscapes_path
12
+
13
+ click_link "New Landscape"
14
+
15
+ fill_in "Name", :with => "Mountains"
16
+ attach_file "Picture", "test_app/test/fixtures/matterhorn.jpg"
17
+ click_button "Create Landscape"
18
+
19
+ page.should have_css("#picture_crop_preview_wrapper")
20
+ page.should have_css("#picture_crop_preview")
21
+ page.should have_css("#picture_cropbox")
22
+
23
+ page.should have_css("#landscape_picture_original_w")
24
+
25
+ find("#landscape_picture_original_w").value.should eq("1024.0")
26
+ find("#landscape_picture_original_h").value.should eq("768.0")
27
+ find("#landscape_picture_box_w").value.should eq("600")
28
+ find("#picture_aspect").value.should eq((4.0 / 3.0).to_s)
29
+
30
+ find("#picture_crop_x").set "300.0"
31
+ find("#picture_crop_y").set "200.0"
32
+ find("#picture_crop_w").set "400"
33
+ find("#picture_crop_h").set "300"
34
+
35
+ click_button "Crop image"
36
+
37
+ compare_images(CROPPED_IMG_PATH, Landscape.last.picture.path(:medium)).should eq(0.0)
38
+ end
39
+ end
@@ -0,0 +1,64 @@
1
+ require "spec_helper"
2
+
3
+ describe "Active Record Extension" do
4
+
5
+ before do
6
+ @landscape = Landscape.new(:name => "Mountains")
7
+ @landscape.picture = open("test_app/test/fixtures/matterhorn.jpg")
8
+ @landscape.save
9
+ end
10
+
11
+
12
+ after do
13
+ @landscape.destroy
14
+ end
15
+
16
+
17
+ it "includes accessors to the model" do
18
+ %w{crop_x crop_y crop_w crop_h original_w original_h box_w aspect}.each do |m|
19
+ @landscape.should respond_to(:"picture_#{m}")
20
+ @landscape.should respond_to(:"picture_#{m}=")
21
+ end
22
+ end
23
+
24
+
25
+ it "registers the post processor" do
26
+ @landscape.attachment_definitions[:picture][:processors].should eq([:cropper])
27
+ end
28
+
29
+
30
+ it "defines an after update callback" do
31
+ @landscape._update_callbacks.map do |e|
32
+ e.instance_values['filter'].should eq(:reprocess_to_crop_picture_attachment)
33
+ end
34
+ end
35
+
36
+
37
+ it "returns image properties" do
38
+ @landscape.picture_aspect.should eq(4.0 / 3.0)
39
+
40
+ @landscape.image_geometry(:picture).width.should eq(1024.0)
41
+ @landscape.image_geometry(:picture).height.should eq(768.0)
42
+ end
43
+
44
+
45
+ it "knows when to crop" do
46
+ @landscape.cropping?(:picture).should be(false)
47
+ @landscape.picture_crop_x = 0.0
48
+ @landscape.picture_crop_y = 0.0
49
+ @landscape.picture_crop_w = 400
50
+ @landscape.picture_crop_h = 300
51
+ @landscape.cropping?(:picture).should be(true)
52
+ end
53
+
54
+
55
+ it "crops images" do
56
+ @landscape.picture_crop_x = 300.0
57
+ @landscape.picture_crop_y = 200.0
58
+ @landscape.picture_crop_w = 400
59
+ @landscape.picture_crop_h = 300
60
+ @landscape.save
61
+
62
+ compare_images(CROPPED_IMG_PATH, @landscape.picture.path(:medium)).should eq(0.0)
63
+ end
64
+ end
@@ -0,0 +1,41 @@
1
+ # This file is copied to spec/ when you run 'rails generate rspec:install'
2
+ ENV["RAILS_ENV"] = 'test'
3
+ require File.expand_path("../../test_app/config/environment", __FILE__)
4
+ require 'rspec/rails'
5
+ require 'rspec/autorun'
6
+
7
+ # Requires supporting ruby files with custom matchers and macros, etc,
8
+ # in spec/support/ and its subdirectories.
9
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
10
+
11
+ # Previously cropped image. Used for comparing test cropped images with RMagick
12
+ CROPPED_IMG_PATH = "test_app/test/fixtures/test_img.jpg"
13
+
14
+ RSpec.configure do |config|
15
+ # ## Mock Framework
16
+ #
17
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
18
+ #
19
+ # config.mock_with :mocha
20
+ # config.mock_with :flexmock
21
+ # config.mock_with :rr
22
+
23
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
24
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
25
+
26
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
27
+ # examples within a transaction, remove the following line or assign false
28
+ # instead of true.
29
+ config.use_transactional_fixtures = true
30
+
31
+ # If true, the base class of anonymous controllers will be inferred
32
+ # automatically. This will be the default behavior in future versions of
33
+ # rspec-rails.
34
+ config.infer_base_class_for_anonymous_controllers = false
35
+
36
+ # Run specs in random order to surface order dependencies. If you find an
37
+ # order dependency and want to debug it, you can fix the order by providing
38
+ # the seed, which is printed after each run.
39
+ # --seed 1234
40
+ config.order = "random"
41
+ end
@@ -0,0 +1,8 @@
1
+ require "RMagick"
2
+
3
+ def compare_images(test_image_path, cropped_image_path)
4
+ test_img = Magick::Image::read(test_image_path).first
5
+ target_img = Magick::Image::read(cropped_image_path).first
6
+
7
+ test_img.compare_channel(target_img, Magick::MeanAbsoluteErrorMetric).second
8
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: papercrop
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,18 +13,18 @@ date: 2012-08-12 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &10547380 !ruby/object:Gem::Requirement
16
+ requirement: &22349340 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
21
  version: '3.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *10547380
24
+ version_requirements: *22349340
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: jquery-rails
27
- requirement: &10546980 !ruby/object:Gem::Requirement
27
+ requirement: &22348940 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,19 +32,74 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *10546980
35
+ version_requirements: *22348940
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: paperclip
38
- requirement: &10546440 !ruby/object:Gem::Requirement
38
+ requirement: &22348380 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ~>
41
+ - - ! '>='
42
42
  - !ruby/object:Gem::Version
43
43
  version: '3.1'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *10546440
47
- description: Paperclip extension for cropping images
46
+ version_requirements: *22348380
47
+ - !ruby/object:Gem::Dependency
48
+ name: rspec-rails
49
+ requirement: &22337440 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '2.0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *22337440
58
+ - !ruby/object:Gem::Dependency
59
+ name: capybara
60
+ requirement: &22336980 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: 1.1.1
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *22336980
69
+ - !ruby/object:Gem::Dependency
70
+ name: rmagick
71
+ requirement: &22336580 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *22336580
80
+ - !ruby/object:Gem::Dependency
81
+ name: sass
82
+ requirement: &22336120 !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ type: :development
89
+ prerelease: false
90
+ version_requirements: *22336120
91
+ - !ruby/object:Gem::Dependency
92
+ name: sqlite3
93
+ requirement: &22335680 !ruby/object:Gem::Requirement
94
+ none: false
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ type: :development
100
+ prerelease: false
101
+ version_requirements: *22335680
102
+ description: An easy extension for Paperclip to crop your image uploads using jCrop
48
103
  email: rsantamaria.dev@gmail.com
49
104
  executables: []
50
105
  extensions: []
@@ -56,7 +111,6 @@ files:
56
111
  - lib/assets/stylesheets/jquery.jcrop.css
57
112
  - lib/paperclip_processors/cropper.rb
58
113
  - lib/papercrop/active_record_extension.rb
59
- - lib/papercrop/controller_extension.rb
60
114
  - lib/papercrop/engine.rb
61
115
  - lib/papercrop/helpers.rb
62
116
  - lib/papercrop.rb
@@ -65,7 +119,12 @@ files:
65
119
  - vendor/jcrop-v0.9.10/js/jquery.Jcrop.js
66
120
  - vendor/jcrop-v0.9.10/MIT-LICENSE.txt
67
121
  - README.md
68
- homepage: http://rubygems.org/gems/papercrop
122
+ - spec/integration/papercrop_js_spec.rb
123
+ - spec/integration/papercrop_spec.rb
124
+ - spec/model_extensions/active_record_spec.rb
125
+ - spec/spec_helper.rb
126
+ - spec/support/compare_images.rb
127
+ homepage: https://github.com/rsantamaria/papercrop
69
128
  licenses: []
70
129
  post_install_message:
71
130
  rdoc_options: []
@@ -89,4 +148,9 @@ rubygems_version: 1.8.10
89
148
  signing_key:
90
149
  specification_version: 3
91
150
  summary: Paperclip extension for cropping images
92
- test_files: []
151
+ test_files:
152
+ - spec/integration/papercrop_js_spec.rb
153
+ - spec/integration/papercrop_spec.rb
154
+ - spec/model_extensions/active_record_spec.rb
155
+ - spec/spec_helper.rb
156
+ - spec/support/compare_images.rb
@@ -1,29 +0,0 @@
1
- module Papercrop
2
- module ControllerExtension
3
-
4
- def self.included(klass)
5
- klass.extend ClassMethods
6
- end
7
-
8
-
9
- module ClassMethods
10
-
11
- def crop_image(field_name, opts)
12
- opts[:after] ||= [:create, :update]
13
- opts[:class] ||= self.class.name.gsub("Controller", "").singularize.constantize
14
- end
15
-
16
- end
17
-
18
-
19
- module InstanceMethods
20
- end
21
- end
22
- end
23
-
24
-
25
- # if defined? ActionController::Base
26
- # ActionController::Base.class_eval do
27
- # include Papercrop::ControllerExtension
28
- # end
29
- # end