copy_tuner_client 0.5.0 → 0.6.2
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 +5 -5
- data/.github/workflows/rspec.yml +53 -0
- data/.rubocop.yml +2 -0
- data/.ruby-version +1 -1
- data/CHANGELOG.md +42 -1
- data/Gemfile +2 -0
- data/Gemfile.lock +183 -135
- data/Rakefile +4 -14
- data/copy_tuner_client.gemspec +3 -6
- data/gemfiles/5.2.gemfile +1 -1
- data/gemfiles/{5.0.gemfile → 6.0.gemfile} +1 -1
- data/lib/copy_tuner_client/cache.rb +14 -14
- data/lib/copy_tuner_client/engine.rb +7 -3
- data/lib/copy_tuner_client/translation_log.rb +3 -4
- data/lib/copy_tuner_client/version.rb +1 -1
- data/lib/tasks/copy_tuner_client_tasks.rake +4 -4
- data/spec/copy_tuner_client/cache_spec.rb +52 -34
- data/spec/copy_tuner_client/client_spec.rb +3 -1
- data/spec/copy_tuner_client/copyray_spec.rb +2 -0
- data/spec/copy_tuner_client/i18n_backend_spec.rb +1 -0
- data/spec/copy_tuner_client/process_guard_spec.rb +2 -1
- metadata +13 -68
- data/.travis.yml +0 -19
- data/Appraisals +0 -11
- data/features/rails.feature +0 -284
- data/features/step_definitions/copycopter_server_steps.rb +0 -64
- data/features/step_definitions/rails_steps.rb +0 -187
- data/features/support/env.rb +0 -11
- data/features/support/rails_server.rb +0 -150
- data/gemfiles/5.1.gemfile +0 -7
- data/init.rb +0 -1
data/Rakefile
CHANGED
@@ -1,26 +1,16 @@
|
|
1
1
|
require 'bundler/gem_tasks'
|
2
|
-
require 'appraisal'
|
3
|
-
require 'cucumber/rake/task'
|
4
2
|
require 'rspec/core/rake_task'
|
5
3
|
require 'yard'
|
6
4
|
|
7
|
-
desc 'Default: run the specs
|
8
|
-
task :
|
5
|
+
desc 'Default: run the specs.'
|
6
|
+
task default: [:spec]
|
9
7
|
|
10
8
|
desc 'Test the copy_tuner_client plugin.'
|
11
9
|
RSpec::Core::RakeTask.new do |t|
|
12
|
-
t.rspec_opts = ['--color',
|
10
|
+
t.rspec_opts = ['--color', '--format progress']
|
13
11
|
t.pattern = 'spec/copy_tuner_client/**/*_spec.rb'
|
14
12
|
end
|
15
13
|
|
16
|
-
desc "Run cucumber features"
|
17
|
-
Cucumber::Rake::Task.new do |t|
|
18
|
-
t.cucumber_opts = [
|
19
|
-
'--tags', '~@wip',
|
20
|
-
'--format', (ENV['CUCUMBER_FORMAT'] || 'progress')
|
21
|
-
]
|
22
|
-
end
|
23
|
-
|
24
14
|
YARD::Rake::YardocTask.new do |t|
|
25
|
-
t.files
|
15
|
+
t.files = ['lib/**/*.rb']
|
26
16
|
end
|
data/copy_tuner_client.gemspec
CHANGED
@@ -3,15 +3,12 @@ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
|
3
3
|
require 'copy_tuner_client/version'
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.required_ruby_version = '>= 2.
|
6
|
+
s.required_ruby_version = '>= 2.5.0'
|
7
7
|
s.add_dependency 'i18n', '>= 0.5.0'
|
8
8
|
s.add_dependency 'json'
|
9
|
-
s.add_development_dependency '
|
10
|
-
s.add_development_dependency 'aruba', '~> 0.6.0'
|
11
|
-
s.add_development_dependency 'cucumber', '~> 1.3.16'
|
12
|
-
s.add_development_dependency 'rails', '~> 4.2.6'
|
9
|
+
s.add_development_dependency 'rails', '~> 5.2.4.2'
|
13
10
|
s.add_development_dependency 'rake'
|
14
|
-
s.add_development_dependency 'rspec'
|
11
|
+
s.add_development_dependency 'rspec', '3.8.0' # NOTE: 3.9.0だとundefined method `synchronize'でコケるテストがある
|
15
12
|
s.add_development_dependency 'sham_rack'
|
16
13
|
s.add_development_dependency 'sinatra'
|
17
14
|
s.add_development_dependency 'sqlite3'
|
data/gemfiles/5.2.gemfile
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'thread'
|
2
1
|
require 'copy_tuner_client/client'
|
3
2
|
require 'copy_tuner_client/dotted_hash'
|
4
3
|
|
@@ -40,9 +39,12 @@ module CopyTunerClient
|
|
40
39
|
# @param value [String] the new contents of the blurb
|
41
40
|
def []=(key, value)
|
42
41
|
return if @exclude_key_regexp && key.match?(@exclude_key_regexp)
|
42
|
+
return unless key.include?('.')
|
43
43
|
return if @locales.present? && !@locales.member?(key.split('.').first)
|
44
|
+
|
44
45
|
lock do
|
45
|
-
return if @blank_keys.member?(key)
|
46
|
+
return if @blank_keys.member?(key) || @blurbs.key?(key)
|
47
|
+
|
46
48
|
@queued[key] = value
|
47
49
|
end
|
48
50
|
end
|
@@ -61,17 +63,15 @@ module CopyTunerClient
|
|
61
63
|
|
62
64
|
# Waits until the first download has finished.
|
63
65
|
def wait_for_download
|
64
|
-
|
65
|
-
logger.info 'Waiting for first download'
|
66
|
+
return unless pending?
|
66
67
|
|
67
|
-
|
68
|
-
logger.flush
|
69
|
-
end
|
68
|
+
logger.info 'Waiting for first download'
|
70
69
|
|
71
|
-
|
72
|
-
|
73
|
-
end
|
70
|
+
if logger.respond_to? :flush
|
71
|
+
logger.flush
|
74
72
|
end
|
73
|
+
|
74
|
+
sleep 0.1 while pending?
|
75
75
|
end
|
76
76
|
|
77
77
|
def flush
|
@@ -82,8 +82,8 @@ module CopyTunerClient
|
|
82
82
|
@last_uploaded_at = Time.now.utc
|
83
83
|
|
84
84
|
res
|
85
|
-
rescue ConnectionError =>
|
86
|
-
logger.error
|
85
|
+
rescue ConnectionError => e
|
86
|
+
logger.error e.message
|
87
87
|
end
|
88
88
|
|
89
89
|
def download
|
@@ -100,8 +100,8 @@ module CopyTunerClient
|
|
100
100
|
@last_downloaded_at = Time.now.utc
|
101
101
|
|
102
102
|
res
|
103
|
-
rescue ConnectionError =>
|
104
|
-
logger.error
|
103
|
+
rescue ConnectionError => e
|
104
|
+
logger.error e.message
|
105
105
|
ensure
|
106
106
|
@downloaded = true
|
107
107
|
end
|
@@ -13,7 +13,13 @@ module CopyTunerClient
|
|
13
13
|
ActionView::Helpers::TranslationHelper.class_eval do
|
14
14
|
def translate_with_copyray_comment(key, options = {})
|
15
15
|
source = translate_without_copyray_comment(key, options)
|
16
|
-
|
16
|
+
# TODO: 0.6.0以降で options[:rescue_format] == text を消す
|
17
|
+
if CopyTunerClient.configuration.disable_copyray_comment_injection || options[:rescue_format] == :text
|
18
|
+
if options[:rescue_format] == :text
|
19
|
+
ActiveSupport::Deprecation.warn('rescue_format option is deprecated in copy_tuner_client@0.6.0')
|
20
|
+
end
|
21
|
+
source
|
22
|
+
else
|
17
23
|
separator = options[:separator] || I18n.default_separator
|
18
24
|
scope = options[:scope]
|
19
25
|
normalized_key =
|
@@ -23,8 +29,6 @@ module CopyTunerClient
|
|
23
29
|
I18n.normalize_keys(nil, key, scope, separator).join(separator)
|
24
30
|
end
|
25
31
|
CopyTunerClient::Copyray.augment_template(source, normalized_key)
|
26
|
-
else
|
27
|
-
source
|
28
32
|
end
|
29
33
|
end
|
30
34
|
if CopyTunerClient.configuration.enable_middleware?
|
@@ -19,12 +19,10 @@ module CopyTunerClient
|
|
19
19
|
def self.install_hook
|
20
20
|
I18n.class_eval do
|
21
21
|
class << self
|
22
|
-
def translate_with_copy_tuner_hook(
|
23
|
-
key = args[0]
|
24
|
-
options = args.last.is_a?(Hash) ? args.last : {}
|
22
|
+
def translate_with_copy_tuner_hook(key, **options)
|
25
23
|
scope = options[:scope]
|
26
24
|
scope = scope.dup if scope.is_a?(Array) || scope.is_a?(String)
|
27
|
-
result = translate_without_copy_tuner_hook(
|
25
|
+
result = translate_without_copy_tuner_hook(key, **options)
|
28
26
|
|
29
27
|
if key.is_a?(Array)
|
30
28
|
key.zip(result).each { |k, v| CopyTunerClient::TranslationLog.add(I18n.normalize_keys(nil, k, scope).join('.'), v) unless v.is_a?(Array) }
|
@@ -33,6 +31,7 @@ module CopyTunerClient
|
|
33
31
|
end
|
34
32
|
result
|
35
33
|
end
|
34
|
+
|
36
35
|
if CopyTunerClient.configuration.enable_middleware?
|
37
36
|
alias_method :translate_without_copy_tuner_hook, :translate
|
38
37
|
alias_method :translate, :translate_with_copy_tuner_hook
|
@@ -6,13 +6,13 @@ namespace :copy_tuner do
|
|
6
6
|
end
|
7
7
|
|
8
8
|
desc "Export CopyTuner blurbs to yaml."
|
9
|
-
task :export => :environment do
|
9
|
+
task :export, %i[path] => :environment do |_, args|
|
10
|
+
args.with_defaults(path: "config/locales/copy_tuner.yml")
|
10
11
|
CopyTunerClient.cache.sync
|
11
12
|
|
12
13
|
if yml = CopyTunerClient.export
|
13
|
-
path
|
14
|
-
|
15
|
-
puts "Successfully exported blurbs to #{path}."
|
14
|
+
File.new("#{Rails.root}/#{args[:path]}", 'w').write(yml)
|
15
|
+
puts "Successfully exported blurbs to #{args[:path]}."
|
16
16
|
else
|
17
17
|
raise "No blurbs have been cached."
|
18
18
|
end
|
@@ -9,7 +9,7 @@ describe CopyTunerClient::Cache do
|
|
9
9
|
CopyTunerClient::Cache.new(client, default_config.update(config))
|
10
10
|
end
|
11
11
|
|
12
|
-
it
|
12
|
+
it 'provides access to downloaded data' do
|
13
13
|
client['en.test.key'] = 'expected'
|
14
14
|
client['en.test.other_key'] = 'expected'
|
15
15
|
|
@@ -18,17 +18,17 @@ describe CopyTunerClient::Cache do
|
|
18
18
|
cache.download
|
19
19
|
|
20
20
|
expect(cache['en.test.key']).to eq('expected')
|
21
|
-
expect(cache.keys).to match_array(%w
|
21
|
+
expect(cache.keys).to match_array(%w[en.test.key en.test.other_key])
|
22
22
|
end
|
23
23
|
|
24
|
-
it
|
24
|
+
it 'exclude data if exclude_key_regexp is set' do
|
25
25
|
cache = build_cache(exclude_key_regexp: /^en\.test\.other_key$/)
|
26
26
|
cache['en.test.key'] = 'expected'
|
27
27
|
cache['en.test.other_key'] = 'expected'
|
28
28
|
|
29
29
|
cache.download
|
30
30
|
|
31
|
-
expect(cache.queued.keys).to match_array(%w
|
31
|
+
expect(cache.queued.keys).to match_array(%w[en.test.key])
|
32
32
|
end
|
33
33
|
|
34
34
|
it "doesn't upload without changes" do
|
@@ -37,7 +37,15 @@ describe CopyTunerClient::Cache do
|
|
37
37
|
expect(client).not_to be_uploaded
|
38
38
|
end
|
39
39
|
|
40
|
-
it "
|
40
|
+
it "Don't upload incorrect key" do
|
41
|
+
cache = build_cache
|
42
|
+
cache['ja'] = 'incorrect key'
|
43
|
+
|
44
|
+
cache.flush
|
45
|
+
expect(client).not_to be_uploaded
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'uploads changes when flushed' do
|
41
49
|
cache = build_cache
|
42
50
|
cache['test.key'] = 'test value'
|
43
51
|
|
@@ -46,7 +54,7 @@ describe CopyTunerClient::Cache do
|
|
46
54
|
expect(client.uploaded).to eq({ 'test.key' => 'test value' })
|
47
55
|
end
|
48
56
|
|
49
|
-
it
|
57
|
+
it 'uploads empties when nil is assigned' do
|
50
58
|
cache = build_cache
|
51
59
|
cache['test.key'] = nil
|
52
60
|
|
@@ -62,7 +70,7 @@ describe CopyTunerClient::Cache do
|
|
62
70
|
|
63
71
|
cache.flush
|
64
72
|
|
65
|
-
expect(client.uploaded).to eq({'en.test.key' => 'uploaded en', 'ja.test.key' => 'uploaded ja'})
|
73
|
+
expect(client.uploaded).to eq({ 'en.test.key' => 'uploaded en', 'ja.test.key' => 'uploaded ja' })
|
66
74
|
end
|
67
75
|
|
68
76
|
it 'upload with locale filter' do
|
@@ -72,10 +80,10 @@ describe CopyTunerClient::Cache do
|
|
72
80
|
|
73
81
|
cache.flush
|
74
82
|
|
75
|
-
expect(client.uploaded).to eq({'en.test.key' => 'uploaded'})
|
83
|
+
expect(client.uploaded).to eq({ 'en.test.key' => 'uploaded' })
|
76
84
|
end
|
77
85
|
|
78
|
-
it
|
86
|
+
it 'downloads changes' do
|
79
87
|
client['test.key'] = 'test value'
|
80
88
|
cache = build_cache
|
81
89
|
|
@@ -84,7 +92,7 @@ describe CopyTunerClient::Cache do
|
|
84
92
|
expect(cache['test.key']).to eq('test value')
|
85
93
|
end
|
86
94
|
|
87
|
-
it
|
95
|
+
it 'downloads and uploads when synced' do
|
88
96
|
cache = build_cache
|
89
97
|
client['test.key'] = 'test value'
|
90
98
|
cache['other.key'] = 'other value'
|
@@ -95,7 +103,7 @@ describe CopyTunerClient::Cache do
|
|
95
103
|
expect(cache['test.key']).to eq('test value')
|
96
104
|
end
|
97
105
|
|
98
|
-
it
|
106
|
+
it 'download included empty keys' do
|
99
107
|
client['en.test.key'] = 'test value'
|
100
108
|
client['en.test.empty'] = ''
|
101
109
|
cache = build_cache
|
@@ -109,11 +117,21 @@ describe CopyTunerClient::Cache do
|
|
109
117
|
expect(cache.queued).to be_empty
|
110
118
|
end
|
111
119
|
|
112
|
-
it
|
113
|
-
|
120
|
+
it 'Do not upload downloaded keys' do
|
121
|
+
client['en.test.key'] = 'test value'
|
122
|
+
cache = build_cache
|
123
|
+
|
124
|
+
cache.download
|
125
|
+
|
126
|
+
cache['en.test.key'] = 'dummy'
|
127
|
+
expect(cache.queued).to be_empty
|
128
|
+
end
|
129
|
+
|
130
|
+
it 'handles connection errors when flushing' do
|
131
|
+
failure = 'server is napping'
|
114
132
|
logger = FakeLogger.new
|
115
133
|
expect(client).to receive(:upload).and_raise(CopyTunerClient::ConnectionError.new(failure))
|
116
|
-
cache = build_cache(:
|
134
|
+
cache = build_cache(logger: logger)
|
117
135
|
cache['upload.key'] = 'upload'
|
118
136
|
|
119
137
|
cache.flush
|
@@ -121,22 +139,22 @@ describe CopyTunerClient::Cache do
|
|
121
139
|
expect(logger).to have_entry(:error, failure)
|
122
140
|
end
|
123
141
|
|
124
|
-
it
|
125
|
-
failure =
|
142
|
+
it 'handles connection errors when downloading' do
|
143
|
+
failure = 'server is napping'
|
126
144
|
logger = FakeLogger.new
|
127
145
|
expect(client).to receive(:download).and_raise(CopyTunerClient::ConnectionError.new(failure))
|
128
|
-
cache = build_cache(:
|
146
|
+
cache = build_cache(logger: logger)
|
129
147
|
|
130
148
|
cache.download
|
131
149
|
|
132
150
|
expect(logger).to have_entry(:error, failure)
|
133
151
|
end
|
134
152
|
|
135
|
-
it
|
153
|
+
it 'blocks until the first download is complete' do
|
136
154
|
logger = FakeLogger.new
|
137
155
|
expect(logger).to receive(:flush)
|
138
156
|
client.delay = true
|
139
|
-
cache = build_cache(:
|
157
|
+
cache = build_cache(logger: logger)
|
140
158
|
|
141
159
|
t_download = Thread.new { cache.download }
|
142
160
|
sleep 0.1 until cache.pending?
|
@@ -144,7 +162,7 @@ describe CopyTunerClient::Cache do
|
|
144
162
|
t_wait = Thread.new do
|
145
163
|
cache.wait_for_download
|
146
164
|
end
|
147
|
-
sleep 0.1 until logger.has_entry?(:info,
|
165
|
+
sleep 0.1 until logger.has_entry?(:info, 'Waiting for first download')
|
148
166
|
client.go
|
149
167
|
expect(t_download.join(1)).not_to be_nil
|
150
168
|
expect(cache.pending?).to be_falsey
|
@@ -153,7 +171,7 @@ describe CopyTunerClient::Cache do
|
|
153
171
|
|
154
172
|
it "doesn't block if the first download fails" do
|
155
173
|
client.delay = true
|
156
|
-
client.error = StandardError.new(
|
174
|
+
client.error = StandardError.new('Failure')
|
157
175
|
cache = build_cache
|
158
176
|
|
159
177
|
error = nil
|
@@ -173,12 +191,12 @@ describe CopyTunerClient::Cache do
|
|
173
191
|
expect(t_download.join(1)).not_to be_nil
|
174
192
|
expect(error).to be_kind_of(StandardError)
|
175
193
|
expect(t_wait.join(1)).not_to be_nil
|
176
|
-
expect { cache.download }.to raise_error(StandardError,
|
194
|
+
expect { cache.download }.to raise_error(StandardError, 'Failure')
|
177
195
|
end
|
178
196
|
|
179
197
|
it "doesn't block before downloading" do
|
180
198
|
logger = FakeLogger.new
|
181
|
-
cache = build_cache(:
|
199
|
+
cache = build_cache(logger: logger)
|
182
200
|
|
183
201
|
finished = false
|
184
202
|
Thread.new do
|
@@ -189,7 +207,7 @@ describe CopyTunerClient::Cache do
|
|
189
207
|
sleep(1)
|
190
208
|
|
191
209
|
expect(finished).to eq(true)
|
192
|
-
expect(logger).not_to have_entry(:info,
|
210
|
+
expect(logger).not_to have_entry(:info, 'Waiting for first download')
|
193
211
|
end
|
194
212
|
|
195
213
|
it "doesn't return blank copy" do
|
@@ -201,13 +219,13 @@ describe CopyTunerClient::Cache do
|
|
201
219
|
expect(cache['en.test.key']).to be_nil
|
202
220
|
end
|
203
221
|
|
204
|
-
describe
|
222
|
+
describe 'given locked mutex' do
|
205
223
|
RSpec::Matchers.define :finish_after_unlocking do |mutex|
|
206
224
|
match do |thread|
|
207
225
|
sleep(0.1)
|
208
226
|
|
209
227
|
if thread.status === false
|
210
|
-
violated(
|
228
|
+
violated('finished before unlocking')
|
211
229
|
else
|
212
230
|
mutex.unlock
|
213
231
|
sleep(0.1)
|
@@ -215,7 +233,7 @@ describe CopyTunerClient::Cache do
|
|
215
233
|
if thread.status === false
|
216
234
|
true
|
217
235
|
else
|
218
|
-
violated(
|
236
|
+
violated('still running after unlocking')
|
219
237
|
end
|
220
238
|
end
|
221
239
|
end
|
@@ -238,20 +256,20 @@ describe CopyTunerClient::Cache do
|
|
238
256
|
allow(Mutex).to receive(:new).and_return(mutex)
|
239
257
|
end
|
240
258
|
|
241
|
-
it
|
259
|
+
it 'synchronizes read access to keys between threads' do
|
242
260
|
expect(Thread.new { cache['test.key'] }).to finish_after_unlocking(mutex)
|
243
261
|
end
|
244
262
|
|
245
|
-
it
|
263
|
+
it 'synchronizes read access to the key list between threads' do
|
246
264
|
expect(Thread.new { cache.keys }).to finish_after_unlocking(mutex)
|
247
265
|
end
|
248
266
|
|
249
|
-
it
|
267
|
+
it 'synchronizes write access to keys between threads' do
|
250
268
|
expect(Thread.new { cache['test.key'] = 'value' }).to finish_after_unlocking(mutex)
|
251
269
|
end
|
252
270
|
end
|
253
271
|
|
254
|
-
it
|
272
|
+
it 'flushes from the top level' do
|
255
273
|
cache = build_cache
|
256
274
|
CopyTunerClient.configure do |config|
|
257
275
|
config.cache = cache
|
@@ -261,7 +279,7 @@ describe CopyTunerClient::Cache do
|
|
261
279
|
CopyTunerClient.flush
|
262
280
|
end
|
263
281
|
|
264
|
-
describe
|
282
|
+
describe '#export' do
|
265
283
|
subject { cache.export }
|
266
284
|
|
267
285
|
let(:cache) do
|
@@ -270,7 +288,7 @@ describe CopyTunerClient::Cache do
|
|
270
288
|
cache
|
271
289
|
end
|
272
290
|
|
273
|
-
it
|
291
|
+
it 'can be invoked from the top-level constant' do
|
274
292
|
CopyTunerClient.configure do |config|
|
275
293
|
config.cache = cache
|
276
294
|
end
|
@@ -282,7 +300,7 @@ describe CopyTunerClient::Cache do
|
|
282
300
|
is_expected.to eq nil
|
283
301
|
end
|
284
302
|
|
285
|
-
context
|
303
|
+
context 'with single-level blurb keys' do
|
286
304
|
before do
|
287
305
|
client['key'] = 'test value'
|
288
306
|
client['other_key'] = 'other test value'
|