artwork 0.7.3 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ebd31f20d2755cc9c814519721157b8381e4d31
4
- data.tar.gz: e302263d9af85029c512d50c0100557ff8c0a100
3
+ metadata.gz: e1716bb4537624c4da2a9199eab9618665ff2b23
4
+ data.tar.gz: e4a2bdc791695af01c5def8addc4d57569f05673
5
5
  SHA512:
6
- metadata.gz: 4223d517c83f899f61485a2e1ad5b0b52a970fc97736765d92d20beb9faef8e2377246459b98e01fffe3475896e3c4956a6fd4ae66ff3ca89e2a19c87fd1b24a
7
- data.tar.gz: f897de740bc861b0b8559e89641e3cc086a6b7d4de2793609c162c2d28c7c3ea6ed79676a8e7656f47eb3aa7f9aae314571f39aaf82c378a59ae4d76d1c5cd23
6
+ metadata.gz: 6682f4264b7dd90546dd432911eab9c20b1f4a3142bed4134c470c6597a7f369916f32308f51a771af22824525180cda6155c9bd3a99c3a6f3978680e7eff3da
7
+ data.tar.gz: 85d2fbe50587176e8a4f093b485b57a17f22a6ed55fa728d2f43151e987f9689c11c8525a7b62482ddce19026379db5714712858970fcc1a4fbf4ddb059e937e
@@ -1,3 +1,24 @@
1
+ ## v1.0.0
2
+
3
+ This is a release with major changes in the logic for selecting thumbs and
4
+ refactoring to allow easier overriding of parts of the artwork logic in the
5
+ application.
6
+
7
+ Changes include:
8
+
9
+ - When you're trying to select a retina thumb, the gem will try to select one
10
+ that is at least as wide or wider than the desired size and if there isn't
11
+ such a thumb the search will fallback to normal, non-retina thumbs.
12
+ - Requesting a thumb style of '320x' will select sizes like '420x500', i.e.
13
+ sizes with height or a label only if there isn't a single thumb, larger than
14
+ the requested size and with no height and no label.
15
+ - `artwork_thumb_for` has been renamed to `attachment_style_for`. Keep in mind
16
+ that now there's a different method named `artwork_thumb_for` which
17
+ selects only a compatible artwork thumb/style. Another new method, named
18
+ `plain_thumb_for` works for non-artwork compatible thumbs, e.g. `:foobar`.
19
+ - The internal API has been changed to some extent due to refactoring and
20
+ changes.
21
+
1
22
  ## v0.7.3
2
23
 
3
24
  - Paperclip is no longer a dependency
@@ -1,5 +1,7 @@
1
1
  require 'artwork/version'
2
2
  require 'artwork/configuration'
3
+ require 'artwork/thumbnail'
4
+ require 'artwork/desired_thumbnail'
3
5
  require 'artwork/model'
4
6
  require 'artwork/view'
5
7
  require 'artwork/controller'
@@ -8,7 +10,29 @@ require 'artwork/engine' if Object.const_defined?(:Rails) and Rails.const_define
8
10
  module Artwork
9
11
  extend Configuration
10
12
 
11
- def self.root_path
12
- File.dirname(__FILE__)
13
+ class << self
14
+ def root_path
15
+ File.dirname(__FILE__)
16
+ end
17
+
18
+ def desired_thumb_for(size, base_resolution = nil)
19
+ if size.is_a? Numeric
20
+ DesiredThumbnail.new(width: size, base_resolution: base_resolution)
21
+ else
22
+ thumb = DesiredThumbnail.from_style(size)
23
+
24
+ thumb.base_resolution = base_resolution if base_resolution
25
+
26
+ thumb
27
+ end
28
+ end
29
+
30
+ def scale_in_current_resolution(size, base_resolution = nil)
31
+ desired_thumb_for(size, base_resolution).width_in_current_resolution
32
+ end
33
+
34
+ def expected_width_for(size, base_resolution = nil)
35
+ desired_thumb_for(size, base_resolution).expected_width
36
+ end
13
37
  end
14
38
  end
@@ -0,0 +1,79 @@
1
+ module Artwork
2
+ class DesiredThumbnail < Thumbnail
3
+ class << self
4
+ def from_style(style)
5
+ normal_style, base_resolution = style.to_s.split('@')
6
+
7
+ data = {}
8
+
9
+ if match = normal_style.match(Thumbnail::STYLE_PATTERN) and match[:retina_flag].nil?
10
+ data[:name] = match[:name]
11
+ data[:width] = match[:width].to_i
12
+ data[:height] = match[:height].to_i
13
+ data[:label] = match[:label] ? match[:label].gsub(/^_|_$/, '') : nil
14
+ else
15
+ data[:name] = normal_style.to_s
16
+ end
17
+
18
+ data[:base_resolution] = base_resolution.to_i if base_resolution
19
+
20
+ new(data)
21
+ end
22
+
23
+ def compatible?(style)
24
+ from_style(style).compatible?
25
+ end
26
+ end
27
+
28
+ def initialize(data = {})
29
+ data = data.dup
30
+
31
+ @base_resolution = data.delete(:base_resolution)
32
+
33
+ data[:name] = "#{data[:width]}x" if data[:name].nil? and data[:width]
34
+
35
+ super(data)
36
+ end
37
+
38
+ def width=(value)
39
+ reset_cached_widths
40
+ super
41
+ end
42
+
43
+ def base_resolution
44
+ @base_resolution ||= Artwork.base_resolution
45
+ end
46
+
47
+ def base_resolution=(value)
48
+ reset_cached_widths
49
+ @base_resolution = value
50
+ end
51
+
52
+ def retina?
53
+ Artwork.load_2x_images?
54
+ end
55
+
56
+ def width_in_current_resolution
57
+ return @width_in_current_resolution if @width_in_current_resolution
58
+
59
+ resolution_ratio = base_resolution.to_f / Artwork.current_resolution.to_f
60
+
61
+ @width_in_current_resolution = width.to_f / resolution_ratio
62
+ end
63
+
64
+ def expected_width
65
+ return @expected_width if @expected_width
66
+
67
+ result = width_in_current_resolution
68
+
69
+ @expected_width = retina? ? result * 2 : result
70
+ end
71
+
72
+ private
73
+
74
+ def reset_cached_widths
75
+ @expected_width = nil
76
+ @width_in_current_resolution = nil
77
+ end
78
+ end
79
+ end
@@ -1,60 +1,81 @@
1
- require 'artwork/thumbnail'
2
-
3
1
  module Artwork
4
2
  module Model
5
- def artwork_thumb_for(attachment_name, size, alternative_sizes = nil)
3
+ def artwork_url(attachment_name, size, options = {})
4
+ thumb_name = attachment_style_for(attachment_name, size, options)
5
+
6
+ return nil unless thumb_name
7
+
8
+ send(attachment_name).url(thumb_name, options)
9
+ end
10
+
11
+ def attachment_styles_for(attachment_name)
12
+ self.class.attachment_definitions[attachment_name.to_sym][:styles].keys
13
+ end
14
+
15
+ def attachment_style_for(attachment_name, size, alternative_sizes = nil)
6
16
  size = determine_alternative_size_for(alternative_sizes) || size
7
17
 
8
- size, base_resolution = size.to_s.split('@')
9
- base_resolution ||= Artwork.base_resolution
18
+ thumb =
19
+ if DesiredThumbnail.compatible?(size)
20
+ artwork_thumb_for(attachment_name, size)
21
+ else
22
+ plain_thumb_for(attachment_name, size)
23
+ end
10
24
 
11
- desired_thumb = Thumbnail.new(size)
12
- matching_thumb_name = nil
25
+ return nil unless thumb
13
26
 
14
- ratio_for_current_resolution = base_resolution.to_f / Artwork.current_resolution.to_f
27
+ if thumb.respond_to?(:name)
28
+ thumb.name.to_sym
29
+ else
30
+ thumb.to_sym
31
+ end
32
+ end
15
33
 
16
- if desired_thumb.compatible?
17
- desired_size = desired_thumb.width / ratio_for_current_resolution
34
+ def artwork_thumbs_for(attachment_name)
35
+ attachment_styles_for(attachment_name).map { |style| Thumbnail.from_style(style) }
36
+ end
18
37
 
19
- thumbs = attachment_styles_for(attachment_name).map { |thumb_name| Thumbnail.new(thumb_name) }
38
+ def artwork_thumb_for(attachment_name, size)
39
+ desired_thumb = DesiredThumbnail.from_style(size)
20
40
 
21
- thumbs = thumbs \
22
- .select(&:compatible?) \
23
- .reject(&:retina?) \
24
- .select { |thumb| desired_thumb.label.nil? or desired_thumb.label == thumb.label.to_s } \
25
- .select { |thumb| desired_thumb.aspect_ratio.nil? or desired_thumb.same_aspect_ratio_with?(thumb) } \
26
- .sort
41
+ thumbs = artwork_thumbs_for(attachment_name)
27
42
 
28
- thumbs.each do |thumb|
29
- if desired_size <= thumb.width
30
- matching_thumb_name = thumb.name
31
- break
32
- end
33
- end
43
+ thumbs = thumbs.select(&:compatible?).select { |thumb| desired_thumb.is_like?(thumb) }.sort
34
44
 
35
- # If we did not find any matching attachment definitions,
36
- # the desired size is probably larger than all of our thumb widths,
37
- # So pick the last (largest) one we have.
38
- return nil if thumbs.empty?
39
- matching_thumb_name ||= thumbs.last.name
45
+ if Artwork.load_2x_images?
46
+ retina_artwork_thumb_for(attachment_name, thumbs, desired_thumb)
47
+ else
48
+ normal_artwork_thumb_for(attachment_name, thumbs, desired_thumb)
40
49
  end
50
+ end
41
51
 
42
- matching_thumb_name ||= size.to_sym
52
+ def plain_thumb_for(attachment_name, label)
53
+ all_styles = attachment_styles_for(attachment_name)
43
54
 
44
- if Artwork.load_2x_images? and attachment_styles_for(attachment_name).include?(:"#{matching_thumb_name}_2x")
45
- matching_thumb_name = :"#{matching_thumb_name}_2x"
46
- end
55
+ normal_thumb = label.to_sym
56
+ retina_thumb = :"#{label}_2x"
47
57
 
48
- matching_thumb_name.to_sym
58
+ if Artwork.load_2x_images? and all_styles.include?(retina_thumb)
59
+ retina_thumb
60
+ elsif all_styles.include?(normal_thumb)
61
+ normal_thumb
62
+ end
49
63
  end
50
64
 
51
- def artwork_url(attachment_name, size, options = {})
52
- thumb_name = artwork_thumb_for(attachment_name, size, options)
53
- send(attachment_name).url(thumb_name, options)
65
+ def normal_artwork_thumb_for(attachment_name, thumbs, desired_thumb)
66
+ usable_thumbs = thumbs.reject(&:retina?)
67
+
68
+ thumb = usable_thumbs.find { |current| desired_thumb.expected_width <= current.width }
69
+
70
+ thumb || usable_thumbs.max_by(&:width)
54
71
  end
55
72
 
56
- def attachment_styles_for(attachment_name)
57
- self.class.attachment_definitions[attachment_name.to_sym][:styles].keys
73
+ def retina_artwork_thumb_for(attachment_name, thumbs, desired_thumb)
74
+ retina_thumbs = thumbs.select(&:retina?)
75
+
76
+ thumb = retina_thumbs.find { |current| desired_thumb.expected_width <= current.width }
77
+
78
+ thumb || normal_artwork_thumb_for(attachment_name, thumbs, desired_thumb) || retina_thumbs.max_by(&:width)
58
79
  end
59
80
 
60
81
  private
@@ -2,34 +2,60 @@ module Artwork
2
2
  class Thumbnail
3
3
  include Comparable
4
4
 
5
- NAME_PATTERN = /^(\d+)x(\d+)?((?!_2x)_\w*?)?(_2x)?$/i.freeze
6
-
7
- attr :name
8
- attr :width
9
- attr :height
10
- attr :label
11
- attr :aspect_ratio
12
-
13
- def initialize(name)
14
- @name = name.to_s
15
-
16
- if match = @name.match(NAME_PATTERN)
17
- @width = match[1].to_i
18
- @height = match[2].to_i
19
- @label = match[3] ? match[3].gsub(/^_|_$/, '') : nil
20
- @retina_flag = match[4]
5
+ STYLE_PATTERN = /\A
6
+ (?<name>
7
+ (?<width>\d+)x(?<height>\d+)?
8
+ (?<label>(?!_2x)_\w*?)?
9
+ (?<retina_flag>_2x)?
10
+ )
11
+ \z/ix.freeze
12
+
13
+ class << self
14
+ def from_style(style)
15
+ data = {}
16
+
17
+ if match = style.to_s.match(STYLE_PATTERN)
18
+ data[:name] = match[:name]
19
+ data[:width] = match[:width].to_i
20
+ data[:height] = match[:height].to_i
21
+ data[:label] = match[:label] ? match[:label].gsub(/^_|_$/, '') : nil
22
+ data[:retina] = !!match[:retina_flag]
23
+
24
+ if data[:retina]
25
+ data[:width] *= 2
26
+ data[:height] *= 2
27
+ end
28
+ else
29
+ data[:name] = style.to_s
30
+ end
31
+
32
+ new(data)
33
+ end
34
+
35
+ def compatible?(style)
36
+ style.to_s =~ STYLE_PATTERN ? true : false
21
37
  end
38
+ end
39
+
40
+ def initialize(name:, width: nil, height: nil, label: nil, retina: false)
41
+ @name = name
42
+ @width = width
43
+ @height = height == 0 ? nil : height
44
+ @label = label
45
+ @retina = retina
22
46
 
23
- @height = nil if @height == 0
24
47
  @aspect_ratio = @width.to_f / @height if @height
25
48
  end
26
49
 
50
+ attr_accessor :name, :width, :height, :label, :aspect_ratio
51
+ attr_writer :retina
52
+
27
53
  def compatible?
28
54
  not width.nil?
29
55
  end
30
56
 
31
57
  def retina?
32
- @retina_flag == '_2x'
58
+ @retina
33
59
  end
34
60
 
35
61
  def same_aspect_ratio_with?(other_thumb)
@@ -38,22 +64,37 @@ module Artwork
38
64
  (0.0..0.1).include? (aspect_ratio - other_thumb.aspect_ratio).abs
39
65
  end
40
66
 
41
- def <=>(other_thumb)
42
- width <=> other_thumb.width
67
+ def <=>(other)
68
+ if self.height.nil? and other.height.nil?
69
+ (self.width || -1) <=> (other.width || -1)
70
+ elsif !self.height.nil? and !other.height.nil?
71
+ result = (self.width || -1) <=> (other.width || -1)
72
+
73
+ if result == 0
74
+ result = self.height <=> other.height
75
+ end
76
+
77
+ result
78
+ elsif self.height.nil?
79
+ -1
80
+ else
81
+ 1
82
+ end
43
83
  end
44
84
 
45
85
  def eq(other)
46
- name == other.name and \
47
- width == other.width and \
48
- height == other.height and \
49
- label == other.label and \
50
- retina? == other.retina?
86
+ self.name == other.name &&
87
+ self.width == other.width &&
88
+ self.height == other.height &&
89
+ self.label == other.label &&
90
+ self.retina? == other.retina?
51
91
  end
52
92
 
53
93
  alias == eq
54
94
 
55
- def self.compatible?(name)
56
- name.to_s =~ NAME_PATTERN ? true : false
95
+ def is_like?(other)
96
+ self.label == other.label &&
97
+ (self.aspect_ratio.nil? || self.same_aspect_ratio_with?(other))
57
98
  end
58
99
  end
59
100
  end
@@ -1,3 +1,3 @@
1
1
  module Artwork
2
- VERSION = '0.7.3'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -5,23 +5,23 @@ module Artwork
5
5
  expected_defaults = {:compatible? => true}
6
6
 
7
7
  examples = {
8
- :'320x' => {:width => 320, :height => nil, :retina? => false, :label => nil},
9
- :'320x_2x' => {:width => 320, :height => nil, :retina? => true, :label => nil},
10
- :'640x_2x' => {:width => 640, :height => nil, :retina? => true, :label => nil},
11
- :'640x' => {:width => 640, :height => nil, :retina? => false, :label => nil},
12
- :'1280x' => {:width => 1280, :height => nil, :retina? => false, :label => nil},
13
- :'1280x_2x' => {:width => 1280, :height => nil, :retina? => true, :label => nil},
14
- :'2000x' => {:width => 2000, :height => nil, :retina? => false, :label => nil},
15
- :'1500x_2x' => {:width => 1500, :height => nil, :retina? => true, :label => nil},
16
- :'320x_some_label' => {:width => 320, :height => nil, :retina? => false, :label => 'some_label'},
17
- :'320x_some_label_2x' => {:width => 320, :height => nil, :retina? => true, :label => 'some_label'},
18
- :'320x500' => {:width => 320, :height => 500, :retina? => false, :label => nil},
19
- :'320x500_2x' => {:width => 320, :height => 500, :retina? => true, :label => nil},
20
- :'320x500_crop' => {:width => 320, :height => 500, :retina? => false, :label => 'crop'},
21
- :'320x500_crop_2x' => {:width => 320, :height => 500, :retina? => true, :label => 'crop'},
22
- :'320x_' => {:width => 320, :height => nil, :retina? => false, :label => ''},
23
- :'320x500_' => {:width => 320, :height => 500, :retina? => false, :label => ''},
24
- :'320x500__2x' => {:width => 320, :height => 500, :retina? => true, :label => ''},
8
+ :'320x' => {:width => 320, :height => nil, :retina? => false, :label => nil},
9
+ :'320x_2x' => {:width => 640, :height => nil, :retina? => true, :label => nil},
10
+ :'640x_2x' => {:width => 1280, :height => nil, :retina? => true, :label => nil},
11
+ :'640x' => {:width => 640, :height => nil, :retina? => false, :label => nil},
12
+ :'1280x' => {:width => 1280, :height => nil, :retina? => false, :label => nil},
13
+ :'1280x_2x' => {:width => 2560, :height => nil, :retina? => true, :label => nil},
14
+ :'2000x' => {:width => 2000, :height => nil, :retina? => false, :label => nil},
15
+ :'1500x_2x' => {:width => 3000, :height => nil, :retina? => true, :label => nil},
16
+ :'320x_some_label' => {:width => 320, :height => nil, :retina? => false, :label => 'some_label'},
17
+ :'320x_some_label_2x' => {:width => 640, :height => nil, :retina? => true, :label => 'some_label'},
18
+ :'320x500' => {:width => 320, :height => 500, :retina? => false, :label => nil},
19
+ :'320x500_2x' => {:width => 640, :height => 1000, :retina? => true, :label => nil},
20
+ :'320x500_crop' => {:width => 320, :height => 500, :retina? => false, :label => 'crop'},
21
+ :'320x500_crop_2x' => {:width => 640, :height => 1000, :retina? => true, :label => 'crop'},
22
+ :'320x_' => {:width => 320, :height => nil, :retina? => false, :label => ''},
23
+ :'320x500_' => {:width => 320, :height => 500, :retina? => false, :label => ''},
24
+ :'320x500__2x' => {:width => 640, :height => 1000, :retina? => true, :label => ''},
25
25
  :unsupported => {:compatible? => false},
26
26
  'unsupported_thumb' => {:compatible? => false},
27
27
  }
@@ -30,7 +30,7 @@ module Artwork
30
30
  expected_properties = expected_defaults.merge(expected_properties)
31
31
  expected_properties.each do |field_name, expected_value|
32
32
  it "##{field_name} is #{expected_value.inspect} for #{thumb_name}" do
33
- thumbnail = Thumbnail.new(thumb_name)
33
+ thumbnail = Thumbnail.from_style(thumb_name)
34
34
  expect(thumbnail.send(field_name)).to eq expected_value
35
35
  end
36
36
  end
@@ -43,62 +43,62 @@ module Artwork
43
43
 
44
44
  describe '#eq' do
45
45
  it 'is true for different objects with the same width, height, label and retina flag' do
46
- expect(Thumbnail.new(:'1200x500_crop_2x')).to eq Thumbnail.new('1200x500_crop_2x')
47
- expect(Thumbnail.new(:'1200x_2x')).to eq Thumbnail.new('1200x_2x')
48
- expect(Thumbnail.new(:'1200x')).to eq Thumbnail.new('1200x')
49
- expect(Thumbnail.new(:'1200x_black_and_white')).to eq Thumbnail.new('1200x_black_and_white')
46
+ expect(Thumbnail.from_style(:'1200x500_crop_2x')).to eq Thumbnail.from_style('1200x500_crop_2x')
47
+ expect(Thumbnail.from_style(:'1200x_2x')).to eq Thumbnail.from_style('1200x_2x')
48
+ expect(Thumbnail.from_style(:'1200x')).to eq Thumbnail.from_style('1200x')
49
+ expect(Thumbnail.from_style(:'1200x_black_and_white')).to eq Thumbnail.from_style('1200x_black_and_white')
50
50
  end
51
51
 
52
52
  it 'is false for different objects if any of the width, height, label or retina flag differ' do
53
- expect(Thumbnail.new(:'1200x500_crop_2x')).not_to eq Thumbnail.new('1200x500_crop')
54
- expect(Thumbnail.new(:'1200x500_crop_2x')).not_to eq Thumbnail.new('1200x500crop_2x')
55
- expect(Thumbnail.new(:'1200x500_crop_2x')).not_to eq Thumbnail.new('1201x500_crop_2x')
56
- expect(Thumbnail.new(:'1200x500_crop_2x')).not_to eq Thumbnail.new('1500x')
57
- expect(Thumbnail.new(:'1200x500_crop_2x')).not_to eq Thumbnail.new('1200x400_crop_2x')
53
+ expect(Thumbnail.from_style(:'1200x500_crop_2x')).not_to eq Thumbnail.from_style('1200x500_crop')
54
+ expect(Thumbnail.from_style(:'1200x500_crop_2x')).not_to eq Thumbnail.from_style('1200x500crop_2x')
55
+ expect(Thumbnail.from_style(:'1200x500_crop_2x')).not_to eq Thumbnail.from_style('1201x500_crop_2x')
56
+ expect(Thumbnail.from_style(:'1200x500_crop_2x')).not_to eq Thumbnail.from_style('1500x')
57
+ expect(Thumbnail.from_style(:'1200x500_crop_2x')).not_to eq Thumbnail.from_style('1200x400_crop_2x')
58
58
  end
59
59
  end
60
60
 
61
61
  describe '#aspect_ratio' do
62
62
  it 'is nil if height is not present or is zero' do
63
- expect(Thumbnail.new('400x_label_2x').aspect_ratio).to be_nil
64
- expect(Thumbnail.new('400x_2x').aspect_ratio).to be_nil
65
- expect(Thumbnail.new('400x_').aspect_ratio).to be_nil
66
- expect(Thumbnail.new('400x').aspect_ratio).to be_nil
67
- expect(Thumbnail.new('400x0').aspect_ratio).to be_nil
63
+ expect(Thumbnail.from_style('400x_label_2x').aspect_ratio).to be_nil
64
+ expect(Thumbnail.from_style('400x_2x').aspect_ratio).to be_nil
65
+ expect(Thumbnail.from_style('400x_').aspect_ratio).to be_nil
66
+ expect(Thumbnail.from_style('400x').aspect_ratio).to be_nil
67
+ expect(Thumbnail.from_style('400x0').aspect_ratio).to be_nil
68
68
  end
69
69
 
70
70
  it 'is calculated as a decimal when both a width and a height are present' do
71
- expect(Thumbnail.new('400x300').aspect_ratio).to be_within(0.1).of(1.33)
72
- expect(Thumbnail.new('1600x900').aspect_ratio).to be_within(0.1).of(1.78)
73
- expect(Thumbnail.new('1600x900_with_label').aspect_ratio).to be_within(0.1).of(1.78)
74
- expect(Thumbnail.new('1600x900_with_label_2x').aspect_ratio).to be_within(0.1).of(1.78)
71
+ expect(Thumbnail.from_style('400x300').aspect_ratio).to be_within(0.1).of(1.33)
72
+ expect(Thumbnail.from_style('1600x900').aspect_ratio).to be_within(0.1).of(1.78)
73
+ expect(Thumbnail.from_style('1600x900_with_label').aspect_ratio).to be_within(0.1).of(1.78)
74
+ expect(Thumbnail.from_style('1600x900_with_label_2x').aspect_ratio).to be_within(0.1).of(1.78)
75
75
  end
76
76
  end
77
77
 
78
78
  describe '#same_aspect_ratio_with?' do
79
79
  it 'returns nil if either thumbs have no clear height' do
80
- expect(Thumbnail.new('400x300').same_aspect_ratio_with?(Thumbnail.new('400x'))).to be_nil
81
- expect(Thumbnail.new('400x0').same_aspect_ratio_with?(Thumbnail.new('400x300'))).to be_nil
80
+ expect(Thumbnail.from_style('400x300').same_aspect_ratio_with?(Thumbnail.from_style('400x'))).to be_nil
81
+ expect(Thumbnail.from_style('400x0').same_aspect_ratio_with?(Thumbnail.from_style('400x300'))).to be_nil
82
82
  end
83
83
 
84
84
  it 'returns true if thumbs have aspect ratios within 0.1 of one another' do
85
- expect(Thumbnail.new('400x300').same_aspect_ratio_with?(Thumbnail.new('400x300'))).to be true
86
- expect(Thumbnail.new('400x300').same_aspect_ratio_with?(Thumbnail.new('1600x1200_with_label_2x'))).to be true
87
- expect(Thumbnail.new('400x300').same_aspect_ratio_with?(Thumbnail.new('400x301'))).to be true
85
+ expect(Thumbnail.from_style('400x300').same_aspect_ratio_with?(Thumbnail.from_style('400x300'))).to be true
86
+ expect(Thumbnail.from_style('400x300').same_aspect_ratio_with?(Thumbnail.from_style('1600x1200_with_label_2x'))).to be true
87
+ expect(Thumbnail.from_style('400x300').same_aspect_ratio_with?(Thumbnail.from_style('400x301'))).to be true
88
88
  end
89
89
 
90
90
  it 'returns false if thumbs have different aspect ratios not within 0.1 of one another' do
91
- expect(Thumbnail.new('400x300').same_aspect_ratio_with?(Thumbnail.new('400x200'))).to be false
92
- expect(Thumbnail.new('400x300').same_aspect_ratio_with?(Thumbnail.new('5x10'))).to be false
91
+ expect(Thumbnail.from_style('400x300').same_aspect_ratio_with?(Thumbnail.from_style('400x200'))).to be false
92
+ expect(Thumbnail.from_style('400x300').same_aspect_ratio_with?(Thumbnail.from_style('5x10'))).to be false
93
93
  end
94
94
  end
95
95
 
96
96
  describe 'comparison' do
97
97
  it 'is based on the thumb width' do
98
- small = Thumbnail.new('90x_crop')
99
- medium = Thumbnail.new('500x_crop')
100
- large = Thumbnail.new('1090x_2x')
101
- huge = Thumbnail.new('3200x')
98
+ small = Thumbnail.from_style('90x_crop')
99
+ medium = Thumbnail.from_style('500x_crop')
100
+ large = Thumbnail.from_style('1090x_2x')
101
+ huge = Thumbnail.from_style('3200x')
102
102
 
103
103
  unsorted = [huge, large, small, medium]
104
104
 
@@ -15,4 +15,89 @@ describe Artwork do
15
15
  expect(Artwork).to respond_to(:load_2x_images?)
16
16
  expect(Artwork).to respond_to(:current_resolution)
17
17
  end
18
+
19
+ describe 'proxy methods to DesiredThumbnail' do
20
+ before :each do
21
+ Artwork.base_resolution = 1000
22
+ Artwork.current_resolution = 1000
23
+ Artwork.actual_resolution = 1000
24
+ Artwork.load_2x_images = false
25
+ end
26
+
27
+ describe '::scale_in_current_resolution' do
28
+ it 'will scale the passed width in the current resolution' do
29
+ expect(Artwork.scale_in_current_resolution(320)).to eq(320)
30
+ expect(Artwork.scale_in_current_resolution(320, 500)).to eq(640)
31
+ expect(Artwork.scale_in_current_resolution('280x')).to eq(280)
32
+ expect(Artwork.scale_in_current_resolution('280x_crop')).to eq(280)
33
+ expect(Artwork.scale_in_current_resolution('280x500_crop')).to eq(280)
34
+ expect(Artwork.scale_in_current_resolution('320x@500')).to eq(640)
35
+ expect(Artwork.scale_in_current_resolution('320x@500', 250)).to eq(1280)
36
+
37
+ Artwork.current_resolution = 2000
38
+ expect(Artwork.scale_in_current_resolution(320)).to eq(640)
39
+ expect(Artwork.scale_in_current_resolution(320, 500)).to eq(1280)
40
+ expect(Artwork.scale_in_current_resolution('280x')).to eq(560)
41
+ expect(Artwork.scale_in_current_resolution('280x_crop')).to eq(560)
42
+ expect(Artwork.scale_in_current_resolution('280x500_crop')).to eq(560)
43
+ expect(Artwork.scale_in_current_resolution('320x@500')).to eq(1280)
44
+ expect(Artwork.scale_in_current_resolution('320x@500', 250)).to eq(2560)
45
+ end
46
+
47
+ it 'is not affected by the retina flag' do
48
+ Artwork.load_2x_images = true
49
+
50
+ expect(Artwork.scale_in_current_resolution(320)).to eq(320)
51
+ expect(Artwork.scale_in_current_resolution(320, 500)).to eq(640)
52
+ expect(Artwork.scale_in_current_resolution('280x')).to eq(280)
53
+ expect(Artwork.scale_in_current_resolution('280x_crop')).to eq(280)
54
+ expect(Artwork.scale_in_current_resolution('280x500_crop')).to eq(280)
55
+ expect(Artwork.scale_in_current_resolution('320x@500')).to eq(640)
56
+ expect(Artwork.scale_in_current_resolution('320x@500', 250)).to eq(1280)
57
+
58
+ Artwork.current_resolution = 2000
59
+ expect(Artwork.scale_in_current_resolution(320)).to eq(640)
60
+ expect(Artwork.scale_in_current_resolution(320, 500)).to eq(1280)
61
+ expect(Artwork.scale_in_current_resolution('280x')).to eq(560)
62
+ expect(Artwork.scale_in_current_resolution('280x_crop')).to eq(560)
63
+ expect(Artwork.scale_in_current_resolution('280x500_crop')).to eq(560)
64
+ expect(Artwork.scale_in_current_resolution('320x@500')).to eq(1280)
65
+ expect(Artwork.scale_in_current_resolution('320x@500', 250)).to eq(2560)
66
+ end
67
+ end
68
+
69
+ # The same as ::scale_in_current_resolution but it will double the width if retina
70
+ describe '::expected_width_for' do
71
+ it 'will return the expedted width in the current resolution' do
72
+ expect(Artwork.expected_width_for(320)).to eq(320)
73
+ expect(Artwork.expected_width_for(320, 500)).to eq(640)
74
+ expect(Artwork.expected_width_for('280x')).to eq(280)
75
+ expect(Artwork.expected_width_for('280x_crop')).to eq(280)
76
+ expect(Artwork.expected_width_for('280x500_crop')).to eq(280)
77
+ expect(Artwork.expected_width_for('320x@500')).to eq(640)
78
+ expect(Artwork.expected_width_for('320x@500', 250)).to eq(1280)
79
+
80
+ Artwork.current_resolution = 2000
81
+ expect(Artwork.expected_width_for(320)).to eq(640)
82
+ expect(Artwork.expected_width_for(320, 500)).to eq(1280)
83
+ expect(Artwork.expected_width_for('280x')).to eq(560)
84
+ expect(Artwork.expected_width_for('280x_crop')).to eq(560)
85
+ expect(Artwork.expected_width_for('280x500_crop')).to eq(560)
86
+ expect(Artwork.expected_width_for('320x@500')).to eq(1280)
87
+ expect(Artwork.expected_width_for('320x@500', 250)).to eq(2560)
88
+ end
89
+
90
+ it 'will double the width if retina is expected' do
91
+ Artwork.load_2x_images = true
92
+
93
+ expect(Artwork.expected_width_for(320)).to eq(640)
94
+ expect(Artwork.expected_width_for(320, 500)).to eq(1280)
95
+ expect(Artwork.expected_width_for('280x')).to eq(560)
96
+ expect(Artwork.expected_width_for('280x_crop')).to eq(560)
97
+ expect(Artwork.expected_width_for('280x500_crop')).to eq(560)
98
+ expect(Artwork.expected_width_for('320x@500')).to eq(1280)
99
+ expect(Artwork.expected_width_for('320x@500', 250)).to eq(2560)
100
+ end
101
+ end
102
+ end
18
103
  end
@@ -58,8 +58,8 @@ RSpec.shared_examples 'an artwork model' do
58
58
 
59
59
  describe '#artwork_url' do
60
60
  describe 'behaviour' do
61
- it 'returns the computed url of an attachment by delegating to artwork_thumb_for' do
62
- expect(instance).to receive(:artwork_thumb_for).with(:photo, :size, 'options').and_return(:computed_size)
61
+ it 'returns the computed url of an attachment by delegating to attachment_style_for' do
62
+ expect(instance).to receive(:attachment_style_for).with(:photo, :size, 'options').and_return(:computed_size)
63
63
 
64
64
  attachment = double
65
65
  expect(attachment).to receive(:url).with(:computed_size, 'options').and_return 'some/url'
@@ -69,7 +69,7 @@ RSpec.shared_examples 'an artwork model' do
69
69
  end
70
70
 
71
71
  it 'works with two arguments and a hash options' do
72
- expect(instance).to receive(:artwork_thumb_for).with(:photo, :size, :some => 'options').and_return(:computed_size)
72
+ expect(instance).to receive(:attachment_style_for).with(:photo, :size, :some => 'options').and_return(:computed_size)
73
73
 
74
74
  attachment = double
75
75
  expect(attachment).to receive(:url).with(:computed_size, :some => 'options').and_return 'some/url'
@@ -79,7 +79,7 @@ RSpec.shared_examples 'an artwork model' do
79
79
  end
80
80
 
81
81
  it 'works with two arguments only without any options hash' do
82
- expect(instance).to receive(:artwork_thumb_for).with(:photo, :size, {}).and_return(:computed_size)
82
+ expect(instance).to receive(:attachment_style_for).with(:photo, :size, {}).and_return(:computed_size)
83
83
 
84
84
  attachment = double
85
85
  expect(attachment).to receive(:url).with(:computed_size, {}).and_return 'some/url'
@@ -107,7 +107,7 @@ RSpec.shared_examples 'an artwork model' do
107
107
  end
108
108
  end
109
109
 
110
- describe '#artwork_thumb_for' do
110
+ describe '#attachment_style_for' do
111
111
  before :each do
112
112
  Artwork.base_resolution = 1000
113
113
  Artwork.current_resolution = 1000
@@ -116,7 +116,7 @@ RSpec.shared_examples 'an artwork model' do
116
116
  end
117
117
 
118
118
  def expect_thumb(size, expected)
119
- expect(instance.artwork_thumb_for(attachment_name, *Array(size))).to eq expected
119
+ expect(instance.attachment_style_for(attachment_name, *Array(size))).to eq expected
120
120
  end
121
121
 
122
122
  it 'picks the exact requested size if it exists' do
@@ -154,7 +154,7 @@ RSpec.shared_examples 'an artwork model' do
154
154
  it 'passes through unsupported thumb names' do
155
155
  expect_thumb 'unsupported', :unsupported
156
156
 
157
- Artwork.load_2x_images = true
157
+ Artwork.load_2x_images = true
158
158
  Artwork.base_resolution = 1000
159
159
  Artwork.current_resolution = 5000
160
160
 
@@ -162,7 +162,7 @@ RSpec.shared_examples 'an artwork model' do
162
162
  end
163
163
 
164
164
  it 'picks the nearest non-retina size to our desizred size' do
165
- expect_thumb '390x', :'400x500'
165
+ expect_thumb '390x', :'640x'
166
166
  expect_thumb '420x', :'640x'
167
167
  end
168
168
 
@@ -202,16 +202,16 @@ RSpec.shared_examples 'an artwork model' do
202
202
  expect_thumb '319x498_crop', :'320x500_crop'
203
203
  end
204
204
 
205
- it 'returns the largest thumb with the requested label if no other suitable sizes are found' do
205
+ it 'returns the largest nonretina thumb with the requested label if no other suitable sizes are found' do
206
206
  expect_thumb '20000x_crop', :'320x500_crop'
207
207
  Artwork.load_2x_images = true
208
- expect_thumb '20000x_crop', :'320x500_crop_2x'
208
+ expect_thumb '20000x_crop', :'320x500_crop'
209
209
  end
210
210
 
211
- it 'returns the largest thumb with the requested aspect ratio if no other suitable sizes are found' do
211
+ it 'returns the largest nonretina thumb with the requested aspect ratio if no other suitable sizes are found' do
212
212
  expect_thumb '8000x10000', :'400x500'
213
213
  Artwork.load_2x_images = true
214
- expect_thumb '8000x10000', :'400x500_2x'
214
+ expect_thumb '8000x10000', :'400x500'
215
215
  end
216
216
 
217
217
  it 'returns nil if no thumbnail matches the requested aspect ratio' do
@@ -222,6 +222,17 @@ RSpec.shared_examples 'an artwork model' do
222
222
  expect_thumb '319x_nonexistant_label', nil
223
223
  end
224
224
 
225
+ it 'will return the exact thumb for retina thumbs' do
226
+ expect_thumb '320x_2x', :'320x_2x'
227
+ expect_thumb '310x_2x', nil
228
+
229
+ Artwork.current_resolution = 1111
230
+ expect_thumb '320x_2x', :'320x_2x'
231
+
232
+ Artwork.load_2x_images = true
233
+ expect_thumb '320x_2x', :'320x_2x'
234
+ end
235
+
225
236
  context 'with an alternative sizes definition' do
226
237
  it 'ignores alternative sizes if current resolution is above all the max resolutions given' do
227
238
  Artwork.current_resolution = 1000
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: artwork
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.3
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dimitar Dimitrov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-10-15 00:00:00.000000000 Z
11
+ date: 2015-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -127,6 +127,7 @@ files:
127
127
  - lib/artwork.rb
128
128
  - lib/artwork/configuration.rb
129
129
  - lib/artwork/controller.rb
130
+ - lib/artwork/desired_thumbnail.rb
130
131
  - lib/artwork/engine.rb
131
132
  - lib/artwork/model.rb
132
133
  - lib/artwork/thumbnail.rb
@@ -162,7 +163,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
162
163
  version: '0'
163
164
  requirements: []
164
165
  rubyforge_project:
165
- rubygems_version: 2.4.5.1
166
+ rubygems_version: 2.2.2
166
167
  signing_key:
167
168
  specification_version: 4
168
169
  summary: Automated user resolution based image size choosing for Rails.