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 +4 -4
- data/CHANGELOG.md +21 -0
- data/lib/artwork.rb +26 -2
- data/lib/artwork/desired_thumbnail.rb +79 -0
- data/lib/artwork/model.rb +59 -38
- data/lib/artwork/thumbnail.rb +68 -27
- data/lib/artwork/version.rb +1 -1
- data/spec/artwork/thumbnail_spec.rb +47 -47
- data/spec/artwork_spec.rb +85 -0
- data/spec/shared/model.rb +23 -12
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1716bb4537624c4da2a9199eab9618665ff2b23
|
4
|
+
data.tar.gz: e4a2bdc791695af01c5def8addc4d57569f05673
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6682f4264b7dd90546dd432911eab9c20b1f4a3142bed4134c470c6597a7f369916f32308f51a771af22824525180cda6155c9bd3a99c3a6f3978680e7eff3da
|
7
|
+
data.tar.gz: 85d2fbe50587176e8a4f093b485b57a17f22a6ed55fa728d2f43151e987f9689c11c8525a7b62482ddce19026379db5714712858970fcc1a4fbf4ddb059e937e
|
data/CHANGELOG.md
CHANGED
@@ -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
|
data/lib/artwork.rb
CHANGED
@@ -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
|
-
|
12
|
-
|
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
|
data/lib/artwork/model.rb
CHANGED
@@ -1,60 +1,81 @@
|
|
1
|
-
require 'artwork/thumbnail'
|
2
|
-
|
3
1
|
module Artwork
|
4
2
|
module Model
|
5
|
-
def
|
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
|
-
|
9
|
-
|
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
|
-
|
12
|
-
matching_thumb_name = nil
|
25
|
+
return nil unless thumb
|
13
26
|
|
14
|
-
|
27
|
+
if thumb.respond_to?(:name)
|
28
|
+
thumb.name.to_sym
|
29
|
+
else
|
30
|
+
thumb.to_sym
|
31
|
+
end
|
32
|
+
end
|
15
33
|
|
16
|
-
|
17
|
-
|
34
|
+
def artwork_thumbs_for(attachment_name)
|
35
|
+
attachment_styles_for(attachment_name).map { |style| Thumbnail.from_style(style) }
|
36
|
+
end
|
18
37
|
|
19
|
-
|
38
|
+
def artwork_thumb_for(attachment_name, size)
|
39
|
+
desired_thumb = DesiredThumbnail.from_style(size)
|
20
40
|
|
21
|
-
|
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
|
-
|
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
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
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
|
-
|
52
|
+
def plain_thumb_for(attachment_name, label)
|
53
|
+
all_styles = attachment_styles_for(attachment_name)
|
43
54
|
|
44
|
-
|
45
|
-
|
46
|
-
end
|
55
|
+
normal_thumb = label.to_sym
|
56
|
+
retina_thumb = :"#{label}_2x"
|
47
57
|
|
48
|
-
|
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
|
52
|
-
|
53
|
-
|
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
|
57
|
-
|
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
|
data/lib/artwork/thumbnail.rb
CHANGED
@@ -2,34 +2,60 @@ module Artwork
|
|
2
2
|
class Thumbnail
|
3
3
|
include Comparable
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
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
|
-
@
|
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 <=>(
|
42
|
-
|
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
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
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
|
56
|
-
|
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
|
data/lib/artwork/version.rb
CHANGED
@@ -5,23 +5,23 @@ module Artwork
|
|
5
5
|
expected_defaults = {:compatible? => true}
|
6
6
|
|
7
7
|
examples = {
|
8
|
-
:'320x' => {:width => 320, :height => nil,
|
9
|
-
:'320x_2x' => {:width =>
|
10
|
-
:'640x_2x' => {:width =>
|
11
|
-
:'640x' => {:width => 640, :height => nil,
|
12
|
-
:'1280x' => {:width => 1280, :height => nil,
|
13
|
-
:'1280x_2x' => {:width =>
|
14
|
-
:'2000x' => {:width => 2000, :height => nil,
|
15
|
-
:'1500x_2x' => {:width =>
|
16
|
-
:'320x_some_label' => {:width => 320, :height => nil,
|
17
|
-
:'320x_some_label_2x' => {:width =>
|
18
|
-
:'320x500' => {:width => 320, :height => 500,
|
19
|
-
:'320x500_2x' => {:width =>
|
20
|
-
:'320x500_crop' => {:width => 320, :height => 500,
|
21
|
-
:'320x500_crop_2x' => {:width =>
|
22
|
-
:'320x_' => {:width => 320, :height => nil,
|
23
|
-
:'320x500_' => {:width => 320, :height => 500,
|
24
|
-
:'320x500__2x' => {:width =>
|
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.
|
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.
|
47
|
-
expect(Thumbnail.
|
48
|
-
expect(Thumbnail.
|
49
|
-
expect(Thumbnail.
|
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.
|
54
|
-
expect(Thumbnail.
|
55
|
-
expect(Thumbnail.
|
56
|
-
expect(Thumbnail.
|
57
|
-
expect(Thumbnail.
|
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.
|
64
|
-
expect(Thumbnail.
|
65
|
-
expect(Thumbnail.
|
66
|
-
expect(Thumbnail.
|
67
|
-
expect(Thumbnail.
|
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.
|
72
|
-
expect(Thumbnail.
|
73
|
-
expect(Thumbnail.
|
74
|
-
expect(Thumbnail.
|
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.
|
81
|
-
expect(Thumbnail.
|
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.
|
86
|
-
expect(Thumbnail.
|
87
|
-
expect(Thumbnail.
|
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.
|
92
|
-
expect(Thumbnail.
|
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.
|
99
|
-
medium = Thumbnail.
|
100
|
-
large = Thumbnail.
|
101
|
-
huge = Thumbnail.
|
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
|
|
data/spec/artwork_spec.rb
CHANGED
@@ -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
|
data/spec/shared/model.rb
CHANGED
@@ -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
|
62
|
-
expect(instance).to receive(:
|
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(:
|
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(:
|
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 '#
|
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.
|
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
|
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', :'
|
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', :'
|
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', :'
|
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.
|
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-
|
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.
|
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.
|