paperclip-globalize3 2.3.0 → 3.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.
@@ -1,8 +1,8 @@
1
- require "paperclip/globalize3/version"
2
- require "paperclip/globalize3/attachment"
1
+ require 'paperclip/globalize3/version'
2
+ require 'paperclip/globalize3/attachment'
3
3
 
4
- require "globalize"
5
- require "paperclip"
4
+ require 'globalize'
5
+ require 'paperclip'
6
6
 
7
7
  # Paperclip locale interpolation: if locale fallbacks are used, we need to determine & use the fallback locale
8
8
  Paperclip.interpolates(:locale) do |attachment, _style_name|
@@ -18,15 +18,11 @@ Paperclip.interpolates(:locale) do |attachment, _style_name|
18
18
  end
19
19
  else
20
20
  Rails.logger.warn(
21
- "WARN You have used :locale in a paperclip url/path for an untranslated model (in #{record.class.to_s})."
21
+ "WARN You have used :locale in a paperclip url/path for an untranslated model (in #{record.class})."
22
22
  )
23
23
  nil
24
24
  end
25
25
  (attachment_locale || Globalize.locale).to_s
26
26
  end
27
27
 
28
- unless Paperclip::Attachment.instance_methods.include?(:assign_attributes)
29
- Paperclip::Attachment.send(:include, Paperclip::Globalize3::Attachment::Compatibility::Paperclip41)
30
- end
31
-
32
- Paperclip::Attachment.send(:include, Paperclip::Globalize3::Attachment)
28
+ Paperclip::Attachment.send(:prepend, Paperclip::Globalize3::Attachment)
@@ -1,31 +1,37 @@
1
- # coding: utf-8
2
1
  lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
3
  require 'paperclip/globalize3/version'
4
+ require 'English'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
- spec.name = "paperclip-globalize3"
7
+ spec.name = 'paperclip-globalize3'
8
8
  spec.version = Paperclip::Globalize3::VERSION
9
- spec.authors = ["Maximilian Herold"]
10
- spec.email = ["herold@emjot.de"]
11
- spec.description = %q{locale-specific attachments with paperclip and globalize}
12
- spec.summary = %q{locale-specific attachments with paperclip and globalize}
13
- spec.homepage = "https://github.com/emjot/paperclip-globalize3"
14
- spec.license = "MIT"
9
+ spec.authors = ['Maximilian Herold']
10
+ spec.email = ['herold@emjot.de']
11
+ spec.description = 'locale-specific attachments with paperclip and globalize'
12
+ spec.summary = 'locale-specific attachments with paperclip and globalize'
13
+ spec.homepage = 'https://github.com/emjot/paperclip-globalize3'
14
+ spec.license = 'MIT'
15
15
 
16
- spec.files = `git ls-files`.split($/)
16
+ spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
17
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
- spec.require_paths = ["lib"]
19
+ spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency "activerecord", ['>= 4.0', '< 5.1']
22
- spec.add_dependency "globalize", ">= 4.0.0"
23
- spec.add_dependency "paperclip", "~> 4.1"
21
+ spec.required_ruby_version = '>= 2.2.2'
24
22
 
25
- spec.add_development_dependency "bundler", "~> 1.3"
26
- spec.add_development_dependency "appraisal", "~> 0.5.1"
27
- spec.add_development_dependency "rspec-rails", ["~> 2.14.1", "< 2.99"]
28
- spec.add_development_dependency "sqlite3"
29
- spec.add_development_dependency "rake", '< 12'
30
- spec.add_development_dependency "wwtd", "~> 0.5"
23
+ spec.add_dependency 'activerecord', ['>= 4.2', '< 5.2']
24
+ spec.add_dependency 'globalize', '>= 5.0.0'
25
+ spec.add_dependency 'paperclip', ['>= 4.2', '< 5.3']
26
+
27
+ spec.add_development_dependency 'appraisal', '~> 2.2'
28
+ spec.add_development_dependency 'bundler', '~> 1.13'
29
+ spec.add_development_dependency 'database_cleaner'
30
+ spec.add_development_dependency 'rake'
31
+ spec.add_development_dependency 'rspec', '~> 3.7'
32
+ spec.add_development_dependency 'rubocop'
33
+ spec.add_development_dependency 'rubocop-rspec'
34
+ spec.add_development_dependency 'sqlite3'
35
+ spec.add_development_dependency 'wwtd', '~> 1.3'
36
+ spec.add_development_dependency 'yard'
31
37
  end
data/spec/data/models.rb CHANGED
@@ -4,25 +4,24 @@ end
4
4
 
5
5
  class Post < BasePost
6
6
  has_attached_file :image,
7
- :url => "/system/:test_env_number/:class/:attachment/:id/:locale/:style-:fingerprint.:extension"
8
- validates_attachment :image, :content_type => { :content_type => ['image/png'] }
7
+ url: '/system/:test_env_number/:class/:attachment/:id/:locale/:style-:fingerprint.:extension'
8
+ validates_attachment :image, content_type: {content_type: ['image/png']}
9
9
 
10
10
  translates :image_file_name, :image_content_type, :image_file_size, :image_updated_at, :image_fingerprint
11
11
  end
12
12
 
13
13
  class OnlyProcessPost < BasePost
14
14
  has_attached_file :image,
15
- :url => "/system/:test_env_number/:class/:attachment/:id/:locale/:style-:fingerprint.:extension",
16
- :styles => { :thumb => "10x10", :large => "40x40" },
17
- :only_process => [:thumb]
18
- validates_attachment :image, :content_type => { :content_type => ['image/png'] }
15
+ url: '/system/:test_env_number/:class/:attachment/:id/:locale/:style-:fingerprint.:extension',
16
+ styles: {thumb: '10x10', large: '40x40'},
17
+ only_process: [:thumb]
18
+ validates_attachment :image, content_type: {content_type: ['image/png']}
19
19
 
20
20
  translates :image_file_name, :image_content_type, :image_file_size, :image_updated_at, :image_fingerprint
21
21
  end
22
22
 
23
23
  class Untranslated < ActiveRecord::Base
24
24
  has_attached_file :image,
25
- :url => "/system/:test_env_number/:class/:attachment/:id/:style-:fingerprint.:extension"
26
- validates_attachment :image, :content_type => { :content_type => ['image/png'] }
25
+ url: '/system/:test_env_number/:class/:attachment/:id/:style-:fingerprint.:extension'
26
+ validates_attachment :image, content_type: {content_type: ['image/png']}
27
27
  end
28
-
data/spec/data/schema.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  ActiveRecord::Migration.verbose = false
2
2
 
3
3
  ActiveRecord::Schema.define do
4
- create_table :posts, :force => true do |t|
4
+ create_table :posts, force: true do |t|
5
5
  t.integer :rating
6
6
  end
7
7
 
8
- create_table :post_translations, :force => true do |t|
8
+ create_table :post_translations, force: true do |t|
9
9
  t.string :locale
10
10
  t.references :post
11
11
  t.string :image_file_name
@@ -15,12 +15,11 @@ ActiveRecord::Schema.define do
15
15
  t.timestamp :image_updated_at
16
16
  end
17
17
 
18
- create_table :untranslateds, :force => true do |t|
18
+ create_table :untranslateds, force: true do |t|
19
19
  t.string :image_file_name
20
20
  t.integer :image_file_size
21
21
  t.string :image_content_type
22
22
  t.string :image_fingerprint
23
23
  t.timestamp :image_updated_at
24
24
  end
25
-
26
- end
25
+ end
@@ -0,0 +1,198 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe Paperclip::Globalize3::Attachment do
4
+ def with_locale(*args, &block)
5
+ Globalize.with_locale(*args, &block)
6
+ end
7
+
8
+ def with_locales(*args, &block)
9
+ Globalize.with_locales(*args, &block)
10
+ end
11
+
12
+ before do
13
+ stub_const('Rails', double('Rails'))
14
+ allow(Rails).to receive(:root).and_return(ROOT.join('tmp'))
15
+ allow(Rails).to receive(:env).and_return('test')
16
+ allow(Rails).to receive(:const_defined?).with(:Railtie).and_return(false)
17
+ end
18
+
19
+ let(:test_image_dir) do
20
+ File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'data'))
21
+ end
22
+
23
+ let(:test_image_file) do
24
+ File.new(File.join(test_image_dir, 'test.png'))
25
+ end
26
+
27
+ let(:test_image_file2) do
28
+ File.new(File.join(test_image_dir, 'test2.png'))
29
+ end
30
+
31
+ let(:sample_post_with_en) do
32
+ Post.create!.tap do |post|
33
+ with_locale(:en) { post.update!(image: test_image_file) }
34
+ end
35
+ end
36
+
37
+ let(:sample_post_with_en_and_de) do
38
+ Post.create!.tap do |post|
39
+ with_locale(:en) { post.update!(image: test_image_file) }
40
+ with_locale(:de) { post.update!(image: test_image_file2) }
41
+ end
42
+ end
43
+
44
+ describe 'attachment assignment' do
45
+ context 'when attachment has been assigned in one locale' do
46
+ let!(:post) { sample_post_with_en }
47
+
48
+ it 'is present in that locale' do
49
+ expect(with_locale(:en) { post.image_file_name }).to eq('test.png')
50
+ end
51
+
52
+ it 'exists in the file system in that locale' do
53
+ expect(File).to be_exist(with_locale(:en) { post.image.path })
54
+ end
55
+
56
+ it 'is not present in another locale' do
57
+ expect(with_locale(:de) { post.image_file_name }).to be_nil
58
+ end
59
+
60
+ it('results in a model count of 1') do
61
+ expect(Post.count).to eq(1)
62
+ end
63
+
64
+ it('results in a model translations count of 1') do
65
+ expect(Post.translation_class.count).to eq(1)
66
+ end
67
+ end
68
+
69
+ context 'when another attachment gets assigned to a different locale' do
70
+ subject(:assign_to_different) { with_locale(:de) { post.update!(image: test_image_file2) } }
71
+
72
+ let!(:post) { sample_post_with_en }
73
+
74
+ it 'is present in that different locale' do
75
+ expect { assign_to_different }.to change { with_locale(:de) { post.image_file_name } }.
76
+ from(nil).to('test2.png')
77
+ end
78
+
79
+ it 'has a different file path than in the first locale' do
80
+ assign_to_different
81
+ expect(with_locale(:de) { post.image.path }).not_to eq(with_locale(:en) { post.image.path })
82
+ end
83
+
84
+ it 'exists in the file system in that different locale' do
85
+ assign_to_different
86
+ expect(File).to be_exist((with_locale(:de) { post.image.path }))
87
+ end
88
+
89
+ it 'does not change the attachment in the first locale' do
90
+ expect { assign_to_different }.not_to(change { with_locale(:en) { post.image_file_name } })
91
+ end
92
+
93
+ it 'does not delete the file in the first locale' do
94
+ expect { assign_to_different }.not_to(change { File.exist?(with_locale(:en) { post.image.path }) })
95
+ end
96
+
97
+ it('does not change the model count') { expect { assign_to_different }.not_to change(Post, :count) }
98
+
99
+ it 'changes the model translations count by 1' do
100
+ expect { assign_to_different }.to change(Post.translation_class, :count).by(1)
101
+ end
102
+ end
103
+
104
+ context 'when attachments have been assigned in multiple locales and one gets re-assigned' do
105
+ subject(:re_assign_en) { with_locale(:en) { post.update!(image: test_image_file2) } }
106
+
107
+ let!(:post) { sample_post_with_en_and_de }
108
+ let!(:original_path_en) { with_locale(:en) { post.image.path } }
109
+ let!(:original_path_de) { with_locale(:de) { post.image.path } }
110
+
111
+ it 'changes the path in that locale' do
112
+ expect { re_assign_en }.to(change { with_locale(:en) { post.image.path } })
113
+ end
114
+
115
+ it 'deletes the old file in that locale' do
116
+ expect { re_assign_en }.to change { File.exist?(original_path_en) }.from(true).to(false)
117
+ end
118
+
119
+ it 'creates the new file in that locale' do
120
+ re_assign_en
121
+ expect(File).to be_exist(with_locale(:en) { post.image.path })
122
+ end
123
+
124
+ it 'does not delete the files of the other locales' do
125
+ re_assign_en
126
+ expect(File).to be_exist(original_path_de)
127
+ end
128
+ end
129
+
130
+ context 'when attachment defines :only_process' do
131
+ subject(:assign) { with_locale(:en) { post.update!(image: test_image_file) } }
132
+
133
+ let!(:post) { OnlyProcessPost.create }
134
+
135
+ it 'only clears the provided style in the current locale' do
136
+ expect(post.image).to receive(:queue_some_for_delete).with(:thumb, locales: :en)
137
+ expect(post.image).not_to receive(:queue_all_for_delete)
138
+ assign
139
+ end
140
+ end
141
+ end
142
+
143
+ describe 'model destroy' do
144
+ subject(:destroy) { post.destroy }
145
+
146
+ context 'when model has translations' do
147
+ let!(:post) { sample_post_with_en_and_de }
148
+ let!(:original_path_en) { with_locale(:en) { post.image.path } }
149
+ let!(:original_path_de) { with_locale(:de) { post.image.path } }
150
+
151
+ it 'deletes all attachments in all locales' do
152
+ expect { destroy }.
153
+ to change { [File.exist?(original_path_en), File.exist?(original_path_de)] }.
154
+ from([true, true]).
155
+ to([false, false])
156
+ end
157
+ end
158
+
159
+ context 'when model does not have translations' do
160
+ let!(:post) { Untranslated.create!(image: test_image_file) }
161
+ let!(:original_path) { post.image.path }
162
+
163
+ it 'deletes attachment files' do
164
+ expect { destroy }.to change { File.exist?(original_path) }.from(true).to(false)
165
+ end
166
+ end
167
+ end
168
+
169
+ context 'when fallbacks are defined' do
170
+ around do |example|
171
+ old_fallbacks = Globalize.fallbacks
172
+ Globalize.fallbacks = {en: %i[en de], de: %i[de en]}
173
+ example.run
174
+ Globalize.fallbacks = old_fallbacks
175
+ end
176
+
177
+ describe 'reading the attachment url in a non-existent locale' do
178
+ let!(:post) { sample_post_with_en }
179
+
180
+ it 'returns the attachment url in the fallback locale' do
181
+ with_locale(:de) { expect(post.image.url).to match('/en/') }
182
+ end
183
+ end
184
+
185
+ describe 'attachment assignment' do
186
+ context 'when another attachment gets assigned to a different locale' do
187
+ subject(:assign_to_different) { with_locale(:de) { post.update!(image: test_image_file) } }
188
+
189
+ let!(:post) { sample_post_with_en }
190
+
191
+ it 'has files for all attachments in all locales' do
192
+ assign_to_different
193
+ expect(with_locales(:en, :de) { File.exist?(post.image.path) }).to be_all
194
+ end
195
+ end
196
+ end
197
+ end
198
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,22 +1,15 @@
1
- require 'pathname'
2
1
  require 'fileutils'
2
+ require 'logger'
3
+ require 'pathname'
4
+ require 'rspec'
5
+ require 'active_record'
6
+ require 'active_support'
7
+ require 'database_cleaner'
3
8
 
4
9
  ROOT = Pathname(File.expand_path(File.join(File.dirname(__FILE__), '..')))
5
10
  TEST_ASSETS_PATH = Pathname.new(ROOT).join('tmp', 'public')
6
11
 
7
- RSpec.configure do |config|
8
- config.mock_with :rspec
9
- config.after(:suite) do
10
- FileUtils.rm_rf TEST_ASSETS_PATH if File.exist?(TEST_ASSETS_PATH)
11
- end
12
- end
13
-
14
- require 'active_support'
15
- require 'action_pack'
16
- require 'action_view'
17
- require 'action_controller'
18
- require 'action_dispatch'
19
- require File.expand_path(File.join(File.dirname(__FILE__), '../lib/paperclip-globalize3'))
12
+ require File.expand_path(File.join(File.dirname(__FILE__), '../lib/paperclip/globalize3'))
20
13
 
21
14
  ActiveRecord::Base.send(:include, Paperclip::Glue)
22
15
 
@@ -24,17 +17,56 @@ Paperclip.interpolates(:test_env_number) do |_, _|
24
17
  ENV['TEST_ENV_NUMBER'].presence || '0'
25
18
  end
26
19
 
27
- # set up globalize3 and models (borrowed from globalize3)
28
- require 'fileutils'
29
- require 'logger'
30
- tmpdir = File.join(File.dirname(__FILE__), "../tmp")
20
+ tmpdir = File.join(File.dirname(__FILE__), '../tmp')
31
21
  FileUtils.mkdir(tmpdir) unless File.exist?(tmpdir)
32
- log = File.expand_path(File.join(tmpdir, "globalize3_test.log"))
33
- FileUtils.touch(log) unless File.exists?(log)
22
+ log = File.expand_path(File.join(tmpdir, 'globalize3_test.log'))
23
+ FileUtils.touch(log) unless File.exist?(log)
34
24
  ActiveRecord::Base.logger = Logger.new(log)
35
25
  ActiveRecord::LogSubscriber.attach_to(:active_record)
36
- ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
26
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
27
+ if ActiveRecord::VERSION::STRING >= '4.2' &&
28
+ ActiveRecord::VERSION::STRING < '5.0'
29
+ ActiveRecord::Base.raise_in_transactional_callbacks = true
30
+ end
31
+ Paperclip.options[:logger] = ActiveRecord::Base.logger
32
+
37
33
  require File.expand_path('../data/schema', __FILE__)
38
34
  require File.expand_path('../data/models', __FILE__)
39
- I18n.locale = I18n.default_locale = :en
40
- Globalize.locale = nil
35
+ DatabaseCleaner.strategy = :truncation # we need to commit transactions so that after_commit callbacks are executed
36
+
37
+ I18n.available_locales = %i[en de]
38
+
39
+ RSpec.configure do |config|
40
+ config.expect_with :rspec do |expectations|
41
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
42
+ end
43
+
44
+ config.mock_with :rspec do |mocks|
45
+ mocks.verify_partial_doubles = true
46
+ end
47
+
48
+ config.shared_context_metadata_behavior = :apply_to_host_groups
49
+ config.filter_run_when_matching :focus
50
+ config.example_status_persistence_file_path = 'spec/examples.txt'
51
+ config.disable_monkey_patching!
52
+
53
+ config.default_formatter = 'doc' if config.files_to_run.one?
54
+
55
+ config.profile_examples = 2
56
+ config.order = :random
57
+ Kernel.srand config.seed
58
+
59
+ config.before do
60
+ DatabaseCleaner.start
61
+ I18n.locale = I18n.default_locale = :en
62
+ Globalize.locale = nil
63
+ end
64
+
65
+ config.after do
66
+ DatabaseCleaner.clean
67
+ end
68
+
69
+ config.after(:all) do
70
+ FileUtils.rm_rf TEST_ASSETS_PATH if File.exist?(TEST_ASSETS_PATH)
71
+ end
72
+ end