artwork 0.7.3 → 1.0.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.
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.