serial_translator 1.1.0 → 2.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -0
- data/.tool-versions +1 -0
- data/.travis.yml +6 -5
- data/.utilsrc +26 -0
- data/README.md +4 -0
- data/lib/serial_translator.rb +23 -14
- data/lib/serial_translator/serial_translator_length_validator.rb +1 -1
- data/lib/serial_translator/serial_translator_presence_validator.rb +6 -2
- data/lib/serial_translator/translation_type.rb +23 -0
- data/lib/serial_translator/version.rb +1 -1
- data/serial_translator.gemspec +5 -3
- data/spec/lib/serial_translator/serial_translator_length_validator_spec.rb +1 -1
- data/spec/lib/serial_translator/serial_translator_presence_validator_spec.rb +1 -1
- data/spec/lib/serial_translator/translation_type_spec.rb +33 -0
- data/spec/lib/serial_translator_spec.rb +21 -1
- data/spec/spec_helper.rb +2 -2
- data/spec/support/{fake_object.rb → fake_env.rb} +17 -19
- metadata +61 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e67a98e574e71655f1d1c1de15b35356db3bd0501e06c464d207591a2d8a4da6
|
4
|
+
data.tar.gz: c2ab2da70fdb53ab500912f5ec061e6a504765735a5a518be73869b0839eb2e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c98bb5a850f094b31691f12165095187db6e5df31cc2a46624df1059136c9b58cd8fa3b9115b34d37f336d3ee06c80f90a5fe1b9067abe036029f65236f19458
|
7
|
+
data.tar.gz: a33d2d1793c60dfc441f4c7ced0397cc09bcddfba6904fedc49d63c2e74034d3adc260c9662eea9905c2f5a9e06ccf085395ef760080f711281a8be2466752d3
|
data/.gitignore
CHANGED
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.0.0
|
data/.travis.yml
CHANGED
data/.utilsrc
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# vim: set ft=ruby:
|
2
|
+
|
3
|
+
search do
|
4
|
+
prune_dirs /\A(\.svn|\.git|CVS|tmp|tags|coverage|pkg)\z/
|
5
|
+
skip_files /(\A\.|\.sw[pon]\z|\.(log|fnm|jpg|jpeg|png|pdf|svg)\z|tags|~\z)/i
|
6
|
+
end
|
7
|
+
|
8
|
+
discover do
|
9
|
+
prune_dirs /\A(\.svn|\.git|CVS|tmp|tags|coverage|pkg)\z/
|
10
|
+
skip_files /(\A\.|\.sw[pon]\z|\.log\z|~\z)/
|
11
|
+
binary false
|
12
|
+
end
|
13
|
+
|
14
|
+
strip_spaces do
|
15
|
+
prune_dirs /\A(\..*|CVS|pkg)\z/
|
16
|
+
skip_files /(\A\.|\.sw[pon]\z|\.log\z|~\z)/
|
17
|
+
end
|
18
|
+
|
19
|
+
probe do
|
20
|
+
test_framework :rspec
|
21
|
+
#include_dirs 'features'
|
22
|
+
end
|
23
|
+
|
24
|
+
ssh_tunnel do
|
25
|
+
terminal_multiplexer :tmux
|
26
|
+
end
|
data/README.md
CHANGED
@@ -6,6 +6,10 @@
|
|
6
6
|
|
7
7
|
Translate ActiveRecord object attributes without the use of additional models.
|
8
8
|
|
9
|
+
## Changes from 1.* to 2.*
|
10
|
+
|
11
|
+
`serial_translator` will now store all translations in JSON format per default rather than in YAML. However, it is still able to read YAML serialized translations and will convert them in the background.
|
12
|
+
|
9
13
|
## Installation
|
10
14
|
|
11
15
|
Add it to your Gemfile:
|
data/lib/serial_translator.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
require 'active_support'
|
2
2
|
require 'active_model'
|
3
|
+
require 'active_record'
|
3
4
|
|
4
5
|
require 'serial_translator/serial_translator_length_validator'
|
5
6
|
require 'serial_translator/serial_translator_presence_validator'
|
7
|
+
require 'serial_translator/translation_type'
|
8
|
+
require 'serial_translator/version'
|
6
9
|
|
7
10
|
module SerialTranslator
|
8
11
|
extend ActiveSupport::Concern
|
@@ -11,48 +14,54 @@ module SerialTranslator
|
|
11
14
|
attr_writer :current_translation_locale, :translation_fallback
|
12
15
|
end
|
13
16
|
|
17
|
+
class InvalidLocaleError < StandardError
|
18
|
+
end
|
19
|
+
|
14
20
|
module ClassMethods
|
15
21
|
attr_reader :serial_translator_attributes
|
16
22
|
|
17
23
|
def serial_translator_for(*attributes)
|
18
24
|
@serial_translator_attributes = attributes
|
19
25
|
|
20
|
-
attributes.each do |
|
21
|
-
|
26
|
+
attributes.each do |attr_name|
|
27
|
+
attribute :"#{attr_name}_translations", SerialTranslator::TranslationType.new
|
22
28
|
|
23
29
|
# Define the normal getter, that respects the
|
24
30
|
# current translation locale
|
25
|
-
define_method
|
26
|
-
translations = translations_for(
|
31
|
+
define_method attr_name do |locale = current_translation_locale|
|
32
|
+
translations = translations_for(attr_name)
|
27
33
|
result = translations[locale] if translations[locale].present?
|
28
34
|
result ||= translations.values.detect(&:present?) if translation_fallback?
|
29
35
|
result
|
30
36
|
end
|
31
37
|
|
32
|
-
define_method :"#{
|
33
|
-
__send__(
|
38
|
+
define_method :"#{attr_name}?" do |locale = current_translation_locale|
|
39
|
+
__send__(attr_name.to_sym, locale).present?
|
34
40
|
end
|
35
41
|
|
36
42
|
# Define the normal setter, that respects the
|
37
43
|
# current translation locale
|
38
|
-
define_method "#{
|
39
|
-
|
40
|
-
|
44
|
+
define_method "#{attr_name}=" do |value|
|
45
|
+
unless I18n.available_locales.include?(current_translation_locale)
|
46
|
+
raise InvalidLocaleError, "current_translation_locale #{current_translation_locale.inspect} is not a member of I18n.available_locales: #{I18n.available_locales.inspect}"
|
47
|
+
end
|
48
|
+
__send__(:"#{attr_name}_translations_will_change!")
|
49
|
+
translations = translations_for(attr_name)
|
41
50
|
if value.present?
|
42
51
|
translations[current_translation_locale] = value
|
43
52
|
else
|
44
53
|
translations.delete(current_translation_locale)
|
45
54
|
end
|
46
|
-
__send__(:"#{
|
55
|
+
__send__(:"#{attr_name}_translations=", translations)
|
47
56
|
end
|
48
57
|
|
49
58
|
# Define getters for each specific available locale
|
50
59
|
I18n.available_locales.each do |available_locale|
|
51
|
-
define_method "#{
|
60
|
+
define_method "#{attr_name}_#{available_locale.to_s.underscore}" do
|
52
61
|
begin
|
53
62
|
old_locale = I18n.locale
|
54
63
|
I18n.locale = available_locale
|
55
|
-
__send__(
|
64
|
+
__send__(attr_name)
|
56
65
|
ensure
|
57
66
|
I18n.locale = old_locale
|
58
67
|
end
|
@@ -61,11 +70,11 @@ module SerialTranslator
|
|
61
70
|
|
62
71
|
# Define setters for each specific available locale
|
63
72
|
I18n.available_locales.each do |available_locale|
|
64
|
-
define_method "#{
|
73
|
+
define_method "#{attr_name}_#{available_locale.to_s.underscore}=" do |value|
|
65
74
|
begin
|
66
75
|
old_locale = I18n.locale
|
67
76
|
I18n.locale = available_locale
|
68
|
-
__send__(:"#{
|
77
|
+
__send__(:"#{attr_name}=", value)
|
69
78
|
ensure
|
70
79
|
I18n.locale = old_locale
|
71
80
|
end
|
@@ -29,7 +29,7 @@ module SerialTranslator
|
|
29
29
|
|
30
30
|
default_message = options[MESSAGES[key]]
|
31
31
|
error_options[:message] ||= default_message if default_message
|
32
|
-
record.errors.add(attribute, MESSAGES[key], error_options)
|
32
|
+
record.errors.add(attribute, MESSAGES[key], **error_options)
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
@@ -3,9 +3,13 @@ module SerialTranslator
|
|
3
3
|
def validate_each(record, attribute, _value)
|
4
4
|
translations = record.__send__("#{attribute}_translations") || {}
|
5
5
|
return if translations.values.any?(&:present?)
|
6
|
-
record.
|
6
|
+
if record.send(attribute).blank?
|
7
|
+
record.errors.add(attribute, :blank, **options)
|
8
|
+
end
|
7
9
|
end
|
8
10
|
|
9
|
-
def kind
|
11
|
+
def kind
|
12
|
+
:presence
|
13
|
+
end
|
10
14
|
end
|
11
15
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class SerialTranslator::TranslationType < ActiveRecord::Type::String
|
2
|
+
def cast(value)
|
3
|
+
case value
|
4
|
+
when nil
|
5
|
+
{}
|
6
|
+
when Hash
|
7
|
+
value
|
8
|
+
when /\A---/
|
9
|
+
YAML.load(value)
|
10
|
+
else
|
11
|
+
JSON.parse(value).symbolize_keys
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def serialize(value)
|
16
|
+
case value
|
17
|
+
when String
|
18
|
+
super
|
19
|
+
else
|
20
|
+
JSON(value)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/serial_translator.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
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 'serial_translator/version'
|
@@ -18,11 +17,14 @@ Gem::Specification.new do |spec|
|
|
18
17
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
18
|
spec.require_paths = ["lib"]
|
20
19
|
|
21
|
-
spec.add_dependency 'activemodel', '>=
|
20
|
+
spec.add_dependency 'activemodel', '>= 5'
|
21
|
+
spec.add_dependency 'activerecord', '>= 5'
|
22
22
|
|
23
|
-
spec.add_development_dependency 'bundler'
|
23
|
+
spec.add_development_dependency 'bundler'
|
24
24
|
spec.add_development_dependency 'rake'
|
25
25
|
spec.add_development_dependency 'rspec'
|
26
26
|
spec.add_development_dependency 'rspec-collection_matchers'
|
27
|
+
spec.add_development_dependency 'json', '~>2'
|
27
28
|
spec.add_development_dependency 'simplecov'
|
29
|
+
spec.add_development_dependency 'sqlite3'
|
28
30
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SerialTranslator::TranslationType do
|
4
|
+
let(:type) { SerialTranslator::TranslationType.new }
|
5
|
+
|
6
|
+
describe '#cast' do
|
7
|
+
it 'works for JSON' do
|
8
|
+
expect(type.cast('{"foo":"bar"}')).to eq(foo: 'bar')
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'works for YAML' do
|
12
|
+
expect(type.cast("---\nfoo: bar")).to eq('foo' => 'bar')
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'does nothing if already a Hash' do
|
16
|
+
expect(type.cast({foo: :bar})).to eq(foo: :bar)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'defaults to empty hash' do
|
20
|
+
expect(type.cast(nil)).to eq({})
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#serialize' do
|
25
|
+
it 'converts to JSON' do
|
26
|
+
expect(type.serialize({foo: :bar})).to eq('{"foo":"bar"}')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'leaves strings alone (to avoid double serialization)' do
|
30
|
+
expect(type.serialize('foo')).to eq 'foo'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe SerialTranslator do
|
4
|
-
let(:object) {
|
4
|
+
let(:object) { Fake.new }
|
5
5
|
|
6
6
|
describe 'getting a translated value' do
|
7
7
|
it 'returns the translated value in the requested locale' do
|
@@ -48,6 +48,12 @@ describe SerialTranslator do
|
|
48
48
|
expect(object.title_translations).to eq({ de: 'Deutsch' })
|
49
49
|
end
|
50
50
|
|
51
|
+
it 'raises an error if current translation is not an I18n locale' do
|
52
|
+
object.current_translation_locale = :foobar
|
53
|
+
expect { object.title = 'Deutsch' }.to raise_error(SerialTranslator::InvalidLocaleError)
|
54
|
+
expect(object.title_translations).to eq({})
|
55
|
+
end
|
56
|
+
|
51
57
|
it 'nil removes the value for the current text locale' do
|
52
58
|
object.title_translations = { de: 'Deutsch' }
|
53
59
|
object.current_translation_locale = :de
|
@@ -136,4 +142,18 @@ describe SerialTranslator do
|
|
136
142
|
expect(object).to_not be_translated_into :yml
|
137
143
|
end
|
138
144
|
end
|
145
|
+
|
146
|
+
context 'use active record methods' do
|
147
|
+
it 'works with where and LIKE' do
|
148
|
+
expect {
|
149
|
+
Fake.where('title_translations LIKE ?', '%foobar').count
|
150
|
+
}.not_to raise_error
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'works with where and Hash syntax' do
|
154
|
+
expect {
|
155
|
+
Fake.where(title_translations: 'foobar').count
|
156
|
+
}.not_to raise_error
|
157
|
+
end
|
158
|
+
end
|
139
159
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,27 +1,25 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
1
|
+
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'
|
2
|
+
|
3
|
+
ActiveRecord::Schema.define do
|
4
|
+
self.verbose = false
|
5
|
+
|
6
|
+
create_table :fakes, force: true do |t|
|
7
|
+
t.text :description_translations
|
8
|
+
t.text :title_translations
|
9
|
+
t.text :subtitle_translations
|
10
|
+
t.text :summary_translations
|
11
|
+
t.text :credits_translations
|
12
|
+
t.text :imprint_translations
|
13
|
+
end
|
14
|
+
end
|
7
15
|
|
8
|
-
|
16
|
+
class Fake < ActiveRecord::Base
|
17
|
+
include SerialTranslator
|
9
18
|
|
10
19
|
# Has to be set in this context to test it correctly
|
11
20
|
I18n.available_locales = [:en, :de, :'en-GB']
|
12
21
|
|
13
|
-
|
14
|
-
|
15
|
-
serial_translator_for(*TRANSLATED_ATTRIBUTES)
|
16
|
-
|
17
|
-
TRANSLATED_ATTRIBUTES.map {|ta| "#{ta}_translations" }.each do |hash_name|
|
18
|
-
attr_accessor hash_name
|
19
|
-
define_method("#{hash_name}_will_change!") { changes << hash_name.to_sym }
|
20
|
-
end
|
21
|
-
|
22
|
-
def changes
|
23
|
-
@changes ||= []
|
24
|
-
end
|
22
|
+
serial_translator_for(*%w(description title subtitle summary credits imprint))
|
25
23
|
|
26
24
|
validates :description, serial_translator_presence: true
|
27
25
|
validates :title, serial_translator_length: { within: 5..25 }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serial_translator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- betterplace development team
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-02-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -16,28 +16,42 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: '5'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
26
|
+
version: '5'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activerecord
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '5'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '5'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: bundler
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- - "
|
45
|
+
- - ">="
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
47
|
+
version: '0'
|
34
48
|
type: :development
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- - "
|
52
|
+
- - ">="
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
54
|
+
version: '0'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -80,6 +94,20 @@ dependencies:
|
|
80
94
|
- - ">="
|
81
95
|
- !ruby/object:Gem::Version
|
82
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: json
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '2'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '2'
|
83
111
|
- !ruby/object:Gem::Dependency
|
84
112
|
name: simplecov
|
85
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -94,6 +122,20 @@ dependencies:
|
|
94
122
|
- - ">="
|
95
123
|
- !ruby/object:Gem::Version
|
96
124
|
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: sqlite3
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
97
139
|
description: Translate attribute values without additional models
|
98
140
|
email:
|
99
141
|
- developers@betterplace.org
|
@@ -103,7 +145,9 @@ extra_rdoc_files: []
|
|
103
145
|
files:
|
104
146
|
- ".gitignore"
|
105
147
|
- ".rspec"
|
148
|
+
- ".tool-versions"
|
106
149
|
- ".travis.yml"
|
150
|
+
- ".utilsrc"
|
107
151
|
- Gemfile
|
108
152
|
- LICENSE.txt
|
109
153
|
- README.md
|
@@ -111,18 +155,20 @@ files:
|
|
111
155
|
- lib/serial_translator.rb
|
112
156
|
- lib/serial_translator/serial_translator_length_validator.rb
|
113
157
|
- lib/serial_translator/serial_translator_presence_validator.rb
|
158
|
+
- lib/serial_translator/translation_type.rb
|
114
159
|
- lib/serial_translator/version.rb
|
115
160
|
- serial_translator.gemspec
|
116
161
|
- spec/lib/serial_translator/serial_translator_length_validator_spec.rb
|
117
162
|
- spec/lib/serial_translator/serial_translator_presence_validator_spec.rb
|
163
|
+
- spec/lib/serial_translator/translation_type_spec.rb
|
118
164
|
- spec/lib/serial_translator_spec.rb
|
119
165
|
- spec/spec_helper.rb
|
120
|
-
- spec/support/
|
166
|
+
- spec/support/fake_env.rb
|
121
167
|
homepage: http://www.betterplace.org
|
122
168
|
licenses:
|
123
169
|
- WTFPL
|
124
170
|
metadata: {}
|
125
|
-
post_install_message:
|
171
|
+
post_install_message:
|
126
172
|
rdoc_options: []
|
127
173
|
require_paths:
|
128
174
|
- lib
|
@@ -137,14 +183,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
183
|
- !ruby/object:Gem::Version
|
138
184
|
version: '0'
|
139
185
|
requirements: []
|
140
|
-
|
141
|
-
|
142
|
-
signing_key:
|
186
|
+
rubygems_version: 3.2.3
|
187
|
+
signing_key:
|
143
188
|
specification_version: 4
|
144
189
|
summary: Translate attribute values without additional models
|
145
190
|
test_files:
|
146
191
|
- spec/lib/serial_translator/serial_translator_length_validator_spec.rb
|
147
192
|
- spec/lib/serial_translator/serial_translator_presence_validator_spec.rb
|
193
|
+
- spec/lib/serial_translator/translation_type_spec.rb
|
148
194
|
- spec/lib/serial_translator_spec.rb
|
149
195
|
- spec/spec_helper.rb
|
150
|
-
- spec/support/
|
196
|
+
- spec/support/fake_env.rb
|