mobility 0.1.5 → 0.1.6
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/Gemfile.lock +1 -1
- data/README.md +16 -8
- data/lib/mobility/attributes.rb +19 -8
- data/lib/mobility/backend/active_model/dirty.rb +8 -5
- data/lib/mobility/backend/active_record/column.rb +1 -1
- data/lib/mobility/backend/active_record/hash_valued.rb +2 -2
- data/lib/mobility/backend/active_record/hstore.rb +1 -1
- data/lib/mobility/backend/active_record/key_value.rb +3 -3
- data/lib/mobility/backend/active_record/query_methods.rb +1 -2
- data/lib/mobility/backend/active_record/serialized.rb +2 -2
- data/lib/mobility/backend/active_record/table.rb +4 -4
- data/lib/mobility/backend/cache.rb +3 -4
- data/lib/mobility/backend/column.rb +3 -3
- data/lib/mobility/backend/sequel/column.rb +1 -1
- data/lib/mobility/backend/sequel/dirty.rb +6 -4
- data/lib/mobility/backend/sequel/hash_valued.rb +2 -2
- data/lib/mobility/backend/sequel/hstore.rb +1 -1
- data/lib/mobility/backend/sequel/key_value.rb +2 -2
- data/lib/mobility/backend/sequel/query_methods.rb +1 -2
- data/lib/mobility/backend/sequel/serialized.rb +2 -2
- data/lib/mobility/backend/sequel/table.rb +3 -3
- data/lib/mobility/backend.rb +0 -2
- data/lib/mobility/configuration.rb +10 -3
- data/lib/mobility/fallthrough_accessors.rb +57 -0
- data/lib/mobility/sequel/column_changes.rb +1 -1
- data/lib/mobility/version.rb +1 -1
- data/lib/mobility.rb +29 -11
- metadata +3 -5
- data/lib/generators/mobility/templates/translations.rb +0 -46
- data/lib/generators/mobility/translations_generator.rb +0 -20
- data/lib/mobility/backend/i18n.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e672887874e0e97c1862c468003721bcabfecb34
|
4
|
+
data.tar.gz: afc6154a1bb62a9e3a633ea7b65a31856441ad9a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5c461d32a74de20c33103be3f038443edf0768e25fca9f654d555fbeaa2b8e1fbf7587cf8b2a39264bc602cd26278929110eb3ac71d68c2f3dda8fb3c0cbfbca
|
7
|
+
data.tar.gz: e59f35065d9be082c7ecb33ec2af3097b9e782b3ae3822749cb4df38fbfb0766927171b8b171f18746b64ecb477ebaa97aecc815c8117096b9d6da8f74d2b42c
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -56,7 +56,7 @@ Mobility](http://dejimata.com/2017/3/3/translating-with-mobility).
|
|
56
56
|
Add this line to your application's Gemfile:
|
57
57
|
|
58
58
|
```ruby
|
59
|
-
gem 'mobility', '~> 0.1.
|
59
|
+
gem 'mobility', '~> 0.1.6'
|
60
60
|
```
|
61
61
|
|
62
62
|
To translate attributes on a model, you must include (or extend) `Mobility`,
|
@@ -169,8 +169,8 @@ The options hash is used to generate the backend, and has several reserved keys:
|
|
169
169
|
Enable [fallbacks](#fallbacks), and optionally configure them.
|
170
170
|
- **`dirty`** (Boolean)<br>
|
171
171
|
Whether to enable [dirty tracking](#dirty).
|
172
|
-
- **`
|
173
|
-
Enable [locale accessors](#
|
172
|
+
- **`locale_accessors`** (Boolean or Array)<br>
|
173
|
+
Enable [locale accessors](#locale-accessors) and optionally configure them.
|
174
174
|
|
175
175
|
In addition to these, each backend may have specific configuration options. For
|
176
176
|
example, the default key-value backend, which stores attributes and their
|
@@ -384,6 +384,14 @@ post.title
|
|
384
384
|
Alternatively, just using `locale_accessors: true` will enable all locales in
|
385
385
|
`I18n.available_locales`.
|
386
386
|
|
387
|
+
An alternative to using the `locale_accessors` option is to use the
|
388
|
+
`fallthrough_accessors` option (defined in {Mobility::FallthroughAccessors})
|
389
|
+
with `fallthrough_accessors: true`. This uses +method_missing+ to implicitly
|
390
|
+
define the same methods as above, but supporting any locale without any method
|
391
|
+
definitions. [Dirty tracking](#dirty) enables fallthrough locales for tracking
|
392
|
+
attribute changes. (Both locale accessors and fallthrough locales can be used
|
393
|
+
together without conflict.)
|
394
|
+
|
387
395
|
For more details, see: {Mobility::Attributes} (specifically, the private method
|
388
396
|
`define_locale_accessors`).
|
389
397
|
|
@@ -465,11 +473,11 @@ dirty tracking is not specific to AR and works for non-persisted models as well)
|
|
465
473
|
```ruby
|
466
474
|
class Post < ActiveRecord::Base
|
467
475
|
include Mobility
|
468
|
-
translates :title,
|
476
|
+
translates :title, dirty: true
|
469
477
|
end
|
470
478
|
```
|
471
479
|
|
472
|
-
Now set the attribute in
|
480
|
+
Now set the attribute in two locales:
|
473
481
|
|
474
482
|
```ruby
|
475
483
|
post.title
|
@@ -512,9 +520,9 @@ post.previous_changes
|
|
512
520
|
}
|
513
521
|
```
|
514
522
|
|
515
|
-
You will notice that Mobility uses locale
|
516
|
-
has changed; dirty tracking is implemented this way to ensure that it is
|
517
|
-
what has changed in which locale, avoiding any possible ambiguity.
|
523
|
+
You will notice that Mobility uses locale accessor methods to indicate which
|
524
|
+
locale has changed; dirty tracking is implemented this way to ensure that it is
|
525
|
+
clear what has changed in which locale, avoiding any possible ambiguity.
|
518
526
|
|
519
527
|
For more details, see: {Mobility::Backend::Dirty}.
|
520
528
|
|
data/lib/mobility/attributes.rb
CHANGED
@@ -119,8 +119,12 @@ with other backends.
|
|
119
119
|
# accessors or specify locales for which accessors should be defined on
|
120
120
|
# this model backend. Will default to +true+ if +dirty+ option is +true+.
|
121
121
|
# @option options_ [Boolean] cache (true) Enable cache for this model backend
|
122
|
-
# @option options_ [Boolean, Hash] fallbacks Enable fallbacks or specify
|
123
|
-
#
|
122
|
+
# @option options_ [Boolean, Hash] fallbacks Enable fallbacks or specify
|
123
|
+
# fallbacks for this model backend
|
124
|
+
# @option options_ [Boolean] dirty Enable dirty tracking for this model
|
125
|
+
# backend
|
126
|
+
# @option options_ [Boolean] fallthrough_accessors Enable fallthrough
|
127
|
+
# locale accessors for this model backend
|
124
128
|
# @raise [ArgumentError] if method is not reader, writer or accessor
|
125
129
|
def initialize(method, *attributes_, **options_)
|
126
130
|
raise ArgumentError, "method must be one of: reader, writer, accessor" unless %i[reader writer accessor].include?(method)
|
@@ -130,16 +134,16 @@ with other backends.
|
|
130
134
|
@backend_name = options.delete(:backend) || Mobility.config.default_backend
|
131
135
|
@backend_class = Class.new(get_backend_class(backend: @backend_name,
|
132
136
|
model_class: model_class))
|
133
|
-
|
134
|
-
|
137
|
+
if (options[:dirty] && options[:fallthrough_accessors] != false)
|
138
|
+
options[:fallthrough_accessors] = true
|
139
|
+
end
|
135
140
|
|
136
141
|
@backend_class.configure!(options) if @backend_class.respond_to?(:configure!)
|
137
142
|
|
138
|
-
@backend_class
|
139
|
-
|
140
|
-
@backend_class.include Backend::Fallbacks if options[:fallbacks]
|
143
|
+
include_backend_modules(@backend_class, options)
|
144
|
+
|
141
145
|
@accessor_locales = options[:locale_accessors]
|
142
|
-
@accessor_locales = Mobility.config.default_accessor_locales
|
146
|
+
@accessor_locales = Mobility.config.default_accessor_locales if @accessor_locales == true
|
143
147
|
|
144
148
|
attributes.each do |attribute|
|
145
149
|
define_backend(attribute)
|
@@ -162,6 +166,13 @@ with other backends.
|
|
162
166
|
end
|
163
167
|
end
|
164
168
|
|
169
|
+
def include_backend_modules(backend_class, options)
|
170
|
+
backend_class.include(Backend::Cache) unless options[:cache] == false
|
171
|
+
backend_class.include(Backend::Dirty.for(options[:model_class])) if options[:dirty]
|
172
|
+
backend_class.include(Backend::Fallbacks) if options[:fallbacks]
|
173
|
+
backend_class.include(FallthroughAccessors.new(attributes)) if options[:fallthrough_accessors]
|
174
|
+
end
|
175
|
+
|
165
176
|
# Add this attributes module to shared {Mobility::Wrapper} and setup model
|
166
177
|
# with backend setup block (see {Mobility::Backend::Setup#setup_model}).
|
167
178
|
# @param model_class [Class] Class of model
|
@@ -23,12 +23,13 @@ value of the translated attribute if passed to it.
|
|
23
23
|
module ActiveModel::Dirty
|
24
24
|
# @!group Backend Accessors
|
25
25
|
# @!macro backend_writer
|
26
|
+
# @param [Hash] options
|
26
27
|
def write(locale, value, **options)
|
27
|
-
locale_accessor =
|
28
|
+
locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
|
28
29
|
if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
|
29
30
|
model.attributes_changed_by_setter.except!(locale_accessor)
|
30
31
|
elsif read(locale, options.merge(fallbacks: false)) != value
|
31
|
-
model.send(:attribute_will_change!,
|
32
|
+
model.send(:attribute_will_change!, locale_accessor)
|
32
33
|
end
|
33
34
|
super
|
34
35
|
end
|
@@ -43,14 +44,14 @@ value of the translated attribute if passed to it.
|
|
43
44
|
# methods for translated attributes onto model class.
|
44
45
|
module ClassMethods
|
45
46
|
# (see Mobility::Backend::Setup#setup_model)
|
46
|
-
def setup_model(model_class, attributes, **)
|
47
|
+
def setup_model(model_class, attributes, **options)
|
47
48
|
super
|
48
49
|
model_class.class_eval do
|
49
50
|
%w[changed? change was will_change! previously_changed? previous_change].each do |suffix|
|
50
51
|
attributes.each do |attribute|
|
51
52
|
class_eval <<-EOM, __FILE__, __LINE__ + 1
|
52
53
|
def #{attribute}_#{suffix}
|
53
|
-
attribute_#{suffix}("#{attribute}
|
54
|
+
attribute_#{suffix}(Mobility.normalize_locale_accessor("#{attribute}"))
|
54
55
|
end
|
55
56
|
EOM
|
56
57
|
end
|
@@ -59,8 +60,8 @@ value of the translated attribute if passed to it.
|
|
59
60
|
|
60
61
|
restore_methods = Module.new do
|
61
62
|
attributes.each do |attribute|
|
62
|
-
locale_accessor = "#{attribute}_#{Mobility.locale}"
|
63
63
|
define_method "restore_#{attribute}!" do
|
64
|
+
locale_accessor = Mobility.normalize_locale_accessor(attribute)
|
64
65
|
if attribute_changed?(locale_accessor)
|
65
66
|
__send__("#{attribute}=", changed_attributes[locale_accessor])
|
66
67
|
end
|
@@ -77,6 +78,8 @@ value of the translated attribute if passed to it.
|
|
77
78
|
private :restore_attribute!
|
78
79
|
end
|
79
80
|
model_class.include restore_methods
|
81
|
+
|
82
|
+
model_class.include(FallthroughAccessors.new(*attributes))
|
80
83
|
end
|
81
84
|
end
|
82
85
|
end
|
@@ -4,7 +4,7 @@ module Mobility
|
|
4
4
|
|
5
5
|
Implements the {Mobility::Backend::Column} backend for ActiveRecord models.
|
6
6
|
|
7
|
-
@note This backend disables the +
|
7
|
+
@note This backend disables the +locale_accessors+ option, which would
|
8
8
|
otherwise interfere with column methods.
|
9
9
|
|
10
10
|
@example
|
@@ -11,12 +11,12 @@ Internal class used by ActiveRecord backends that store values as a hash.
|
|
11
11
|
# @!group Backend Accessors
|
12
12
|
#
|
13
13
|
# @!macro backend_reader
|
14
|
-
def read(locale, **)
|
14
|
+
def read(locale, **_)
|
15
15
|
translations[locale]
|
16
16
|
end
|
17
17
|
|
18
18
|
# @!macro backend_writer
|
19
|
-
def write(locale, value, **)
|
19
|
+
def write(locale, value, **_)
|
20
20
|
translations[locale] = value
|
21
21
|
end
|
22
22
|
# @!endgroup
|
@@ -18,7 +18,7 @@ Implements the {Mobility::Backend::Hstore} backend for ActiveRecord models.
|
|
18
18
|
|
19
19
|
# @!group Backend Accessors
|
20
20
|
# @!macro backend_writer
|
21
|
-
def write(locale, value, **)
|
21
|
+
def write(locale, value, **_)
|
22
22
|
translations[locale] = value && value.to_s
|
23
23
|
end
|
24
24
|
# @!endgroup
|
@@ -28,19 +28,19 @@ Implements the {Mobility::Backend::KeyValue} backend for ActiveRecord models.
|
|
28
28
|
|
29
29
|
# @!macro backend_constructor
|
30
30
|
# @option options [Symbol] association_name Name of association
|
31
|
-
def initialize(model, attribute, **)
|
31
|
+
def initialize(model, attribute, **options)
|
32
32
|
super
|
33
33
|
@association_name = options[:association_name]
|
34
34
|
end
|
35
35
|
|
36
36
|
# @!group Backend Accessors
|
37
37
|
# @!macro backend_reader
|
38
|
-
def read(locale, **)
|
38
|
+
def read(locale, **_)
|
39
39
|
translation_for(locale).value
|
40
40
|
end
|
41
41
|
|
42
42
|
# @!macro backend_reader
|
43
|
-
def write(locale, value, **)
|
43
|
+
def write(locale, value, **_)
|
44
44
|
translation_for(locale).tap { |t| t.value = value }.value
|
45
45
|
end
|
46
46
|
# @!endgroup
|
@@ -9,8 +9,7 @@ models. For details see backend-specific subclasses.
|
|
9
9
|
=end
|
10
10
|
class QueryMethods < Module
|
11
11
|
# @param [Array<String>] attributes Translated attributes
|
12
|
-
|
13
|
-
def initialize(attributes, **)
|
12
|
+
def initialize(attributes, **_)
|
14
13
|
@attributes = attributes
|
15
14
|
@attributes_extractor = lambda do |opts|
|
16
15
|
opts.is_a?(Hash) && (opts.keys.map(&:to_s) & attributes).presence
|
@@ -28,12 +28,12 @@ Implements {Mobility::Backend::Serialized} backend for ActiveRecord models.
|
|
28
28
|
# @!group Backend Accessors
|
29
29
|
#
|
30
30
|
# @!macro backend_reader
|
31
|
-
def read(locale, **)
|
31
|
+
def read(locale, **_)
|
32
32
|
translations[locale]
|
33
33
|
end
|
34
34
|
|
35
35
|
# @!macro backend_reader
|
36
|
-
def write(locale, value, **)
|
36
|
+
def write(locale, value, **_)
|
37
37
|
translations[locale] = value
|
38
38
|
end
|
39
39
|
# @!endgroup
|
@@ -84,19 +84,19 @@ Implements the {Mobility::Backend::Table} backend for ActiveRecord models.
|
|
84
84
|
|
85
85
|
# @!macro backend_constructor
|
86
86
|
# @option options [Symbol] association_name Name of association
|
87
|
-
def initialize(model, attribute, **)
|
87
|
+
def initialize(model, attribute, **options)
|
88
88
|
super
|
89
89
|
@association_name = options[:association_name]
|
90
90
|
end
|
91
91
|
|
92
92
|
# @!group Backend Accessors
|
93
93
|
# @!macro backend_reader
|
94
|
-
def read(locale, **)
|
94
|
+
def read(locale, **_)
|
95
95
|
translation_for(locale).send(attribute)
|
96
96
|
end
|
97
97
|
|
98
98
|
# @!macro backend_reader
|
99
|
-
def write(locale, value, **)
|
99
|
+
def write(locale, value, **_)
|
100
100
|
translation_for(locale).tap { |t| t.send("#{attribute}=", value) }.send(attribute)
|
101
101
|
end
|
102
102
|
# @!endgroup
|
@@ -177,7 +177,7 @@ Implements the {Mobility::Backend::Table} backend for ActiveRecord models.
|
|
177
177
|
private
|
178
178
|
|
179
179
|
def translation_for(locale)
|
180
|
-
translation = translations.find { |t| t.locale == locale.to_s }
|
180
|
+
translation = translations.find { |t| t.locale == locale.to_s.freeze }
|
181
181
|
translation ||= translations.build(locale: locale)
|
182
182
|
translation
|
183
183
|
end
|
@@ -35,7 +35,7 @@ this).
|
|
35
35
|
module Cache
|
36
36
|
# @group Backend Accessors
|
37
37
|
# @!macro backend_reader
|
38
|
-
def read(locale, **)
|
38
|
+
def read(locale, **_)
|
39
39
|
if write_to_cache? || cache.has_key?(locale)
|
40
40
|
cache[locale]
|
41
41
|
else
|
@@ -44,7 +44,7 @@ this).
|
|
44
44
|
end
|
45
45
|
|
46
46
|
# @!macro backend_writer
|
47
|
-
def write(locale, value, **)
|
47
|
+
def write(locale, value, **_)
|
48
48
|
cache[locale] = write_to_cache? ? value : super
|
49
49
|
end
|
50
50
|
# @!endgroup
|
@@ -56,8 +56,7 @@ this).
|
|
56
56
|
module Setup
|
57
57
|
# @param model_class Model class
|
58
58
|
# @param [Array<String>] attributes Backend attributes
|
59
|
-
|
60
|
-
def setup_model(model_class, attributes, **)
|
59
|
+
def setup_model(model_class, attributes, **_)
|
61
60
|
super
|
62
61
|
model_class.include BackendResetter.for(model_class).new(attributes) { clear_cache }
|
63
62
|
end
|
@@ -22,12 +22,12 @@ be ignored if set, since it would cause a conflict with column accessors.
|
|
22
22
|
# @!group Backend Accessors
|
23
23
|
#
|
24
24
|
# @!macro backend_reader
|
25
|
-
def read(locale, **)
|
25
|
+
def read(locale, **_)
|
26
26
|
model.send(column(locale))
|
27
27
|
end
|
28
28
|
|
29
29
|
# @!macro backend_writer
|
30
|
-
def write(locale, value, **)
|
30
|
+
def write(locale, value, **_)
|
31
31
|
model.send("#{column(locale)}=", value)
|
32
32
|
end
|
33
33
|
# @!endgroup
|
@@ -44,7 +44,7 @@ be ignored if set, since it would cause a conflict with column accessors.
|
|
44
44
|
# @param [Symbol] locale
|
45
45
|
# @return [String]
|
46
46
|
def self.column_name_for(attribute, locale = Mobility.locale)
|
47
|
-
normalized_locale =
|
47
|
+
normalized_locale = Mobility.normalize_locale(locale)
|
48
48
|
"#{attribute}_#{normalized_locale}".to_sym
|
49
49
|
end
|
50
50
|
end
|
@@ -4,7 +4,7 @@ module Mobility
|
|
4
4
|
|
5
5
|
Implements the {Mobility::Backend::Column} backend for Sequel models.
|
6
6
|
|
7
|
-
@note This backend disables the +
|
7
|
+
@note This backend disables the +locale_accessors+ option, which would
|
8
8
|
otherwise interfere with column methods.
|
9
9
|
=end
|
10
10
|
class Sequel::Column
|
@@ -12,12 +12,12 @@ Automatically includes dirty plugin in model class when enabled.
|
|
12
12
|
# @!group Backend Accessors
|
13
13
|
# @!macro backend_writer
|
14
14
|
def write(locale, value, **options)
|
15
|
-
locale_accessor =
|
15
|
+
locale_accessor = Mobility.normalize_locale_accessor(attribute, locale).to_sym
|
16
16
|
if model.column_changes.has_key?(locale_accessor) && model.initial_values[locale_accessor] == value
|
17
17
|
super
|
18
18
|
[model.changed_columns, model.initial_values].each { |h| h.delete(locale_accessor) }
|
19
19
|
elsif read(locale, options.merge(fallbacks: false)) != value
|
20
|
-
model.will_change_column(
|
20
|
+
model.will_change_column(locale_accessor)
|
21
21
|
super
|
22
22
|
end
|
23
23
|
end
|
@@ -32,7 +32,7 @@ Automatically includes dirty plugin in model class when enabled.
|
|
32
32
|
# methods for translated attributes onto model class.
|
33
33
|
module ClassMethods
|
34
34
|
# (see Mobility::Backend::Setup#setup_model)
|
35
|
-
def setup_model(model_class, attributes, **)
|
35
|
+
def setup_model(model_class, attributes, **options)
|
36
36
|
super
|
37
37
|
model_class.plugin :dirty
|
38
38
|
model_class.class_eval do
|
@@ -40,7 +40,7 @@ Automatically includes dirty plugin in model class when enabled.
|
|
40
40
|
%w[initial_value column_change column_changed? reset_column].each do |method_name|
|
41
41
|
define_method method_name do |column|
|
42
42
|
if attributes.map(&:to_sym).include?(column)
|
43
|
-
super(
|
43
|
+
super(Mobility.normalize_locale_accessor(column).to_sym)
|
44
44
|
else
|
45
45
|
super(column)
|
46
46
|
end
|
@@ -49,6 +49,8 @@ Automatically includes dirty plugin in model class when enabled.
|
|
49
49
|
end
|
50
50
|
include mod
|
51
51
|
end
|
52
|
+
|
53
|
+
model_class.include(FallthroughAccessors.new(*attributes))
|
52
54
|
end
|
53
55
|
end
|
54
56
|
end
|
@@ -9,12 +9,12 @@ Internal class used by Sequel backends that store values as a hash.
|
|
9
9
|
include Backend
|
10
10
|
|
11
11
|
# @!macro backend_reader
|
12
|
-
def read(locale, **)
|
12
|
+
def read(locale, **_)
|
13
13
|
translations[locale.to_s]
|
14
14
|
end
|
15
15
|
|
16
16
|
# @!macro backend_writer
|
17
|
-
def write(locale, value, **)
|
17
|
+
def write(locale, value, **_)
|
18
18
|
translations[locale.to_s] = value
|
19
19
|
end
|
20
20
|
|
@@ -18,7 +18,7 @@ Implements the {Mobility::Backend::Hstore} backend for Sequel models.
|
|
18
18
|
|
19
19
|
# @!group Backend Accessors
|
20
20
|
# @!macro backend_writer
|
21
|
-
def write(locale, value, **)
|
21
|
+
def write(locale, value, **_)
|
22
22
|
translations[locale.to_s] = value && value.to_s
|
23
23
|
end
|
24
24
|
# @!endgroup
|
@@ -31,12 +31,12 @@ Implements the {Mobility::Backend::KeyValue} backend for Sequel models.
|
|
31
31
|
|
32
32
|
# @!group Backend Accessors
|
33
33
|
# @!macro backend_reader
|
34
|
-
def read(locale, **)
|
34
|
+
def read(locale, **_)
|
35
35
|
translation_for(locale).value
|
36
36
|
end
|
37
37
|
|
38
38
|
# @!macro backend_writer
|
39
|
-
def write(locale, value, **)
|
39
|
+
def write(locale, value, **_)
|
40
40
|
translation_for(locale).tap { |t| t.value = value }.value
|
41
41
|
end
|
42
42
|
# @!endgroup
|
@@ -9,8 +9,7 @@ models. For details see backend-specific subclasses.
|
|
9
9
|
=end
|
10
10
|
class QueryMethods < Module
|
11
11
|
# @param [Array<String>] attributes Translated attributes
|
12
|
-
|
13
|
-
def initialize(attributes, **)
|
12
|
+
def initialize(attributes, **_)
|
14
13
|
@attributes = attributes.map! &:to_sym
|
15
14
|
@attributes_extractor = lambda do |cond|
|
16
15
|
cond.is_a?(Hash) && (cond.keys & attributes).presence
|
@@ -35,12 +35,12 @@ Sequel serialization plugin.
|
|
35
35
|
# @!group Backend Accessors
|
36
36
|
#
|
37
37
|
# @!macro backend_reader
|
38
|
-
def read(locale, **)
|
38
|
+
def read(locale, **_)
|
39
39
|
translations[locale]
|
40
40
|
end
|
41
41
|
|
42
42
|
# @!macro backend_reader
|
43
|
-
def write(locale, value, **)
|
43
|
+
def write(locale, value, **_)
|
44
44
|
translations[locale] = value
|
45
45
|
end
|
46
46
|
# @!endgroup
|
@@ -15,19 +15,19 @@ Implements the {Mobility::Backend::Table} backend for Sequel models.
|
|
15
15
|
|
16
16
|
# @!macro backend_constructor
|
17
17
|
# @option options [Symbol] association_name Name of association
|
18
|
-
def initialize(model, attribute, **)
|
18
|
+
def initialize(model, attribute, **options)
|
19
19
|
super
|
20
20
|
@association_name = options[:association_name]
|
21
21
|
end
|
22
22
|
|
23
23
|
# @!group Backend Accessors
|
24
24
|
# @!macro backend_reader
|
25
|
-
def read(locale, **)
|
25
|
+
def read(locale, **_)
|
26
26
|
translation_for(locale).send(attribute)
|
27
27
|
end
|
28
28
|
|
29
29
|
# @!macro backend_reader
|
30
|
-
def write(locale, value, **)
|
30
|
+
def write(locale, value, **_)
|
31
31
|
translation_for(locale).tap { |t| t.send("#{attribute}=", value) }.send(attribute)
|
32
32
|
end
|
33
33
|
|
data/lib/mobility/backend.rb
CHANGED
@@ -87,13 +87,11 @@ On top of this, a backend will normally:
|
|
87
87
|
|
88
88
|
# @!macro [new] backend_reader
|
89
89
|
# @param [Symbol] locale Locale to read
|
90
|
-
# @param [Hash] options
|
91
90
|
# @return [Object] Value of translation
|
92
91
|
#
|
93
92
|
# @!macro [new] backend_writer
|
94
93
|
# @param [Symbol] locale Locale to write
|
95
94
|
# @param [Object] value Value to write
|
96
|
-
# @param [Hash] options
|
97
95
|
# @return [Object] Updated value
|
98
96
|
|
99
97
|
# Extend included class with +setup+ method
|
@@ -17,10 +17,17 @@ Stores shared Mobility configuration referenced by all backends.
|
|
17
17
|
# @return [Symbol,Class]
|
18
18
|
attr_accessor :default_backend
|
19
19
|
|
20
|
-
#
|
21
|
-
#
|
20
|
+
# Returns set of default accessor locles to use (defaults to
|
21
|
+
# +I18n.available_locales+)
|
22
22
|
# @return [Array<Symbol>]
|
23
|
-
|
23
|
+
def default_accessor_locales
|
24
|
+
if @default_accessor_locales.is_a?(Proc)
|
25
|
+
@default_accessor_locales.call
|
26
|
+
else
|
27
|
+
@default_accessor_locales
|
28
|
+
end
|
29
|
+
end
|
30
|
+
attr_writer :default_accessor_locales
|
24
31
|
|
25
32
|
def initialize
|
26
33
|
@accessor_method = :translates
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen-string-literal: true
|
2
|
+
|
3
|
+
module Mobility
|
4
|
+
=begin
|
5
|
+
|
6
|
+
Defines +method_missing+ and +respond_to_missing?+ methods for a set of
|
7
|
+
attributes such that a method call using a locale accessor, like:
|
8
|
+
|
9
|
+
article.title_pt_br
|
10
|
+
|
11
|
+
will return the value of +article.title+ with the locale set to +pt-BR+ around
|
12
|
+
the method call. The class is called "FallthroughAccessors" because when
|
13
|
+
included in a model class, locale-specific methods will be available even if
|
14
|
+
not explicitly defined with the +locale_accessors+ option.
|
15
|
+
|
16
|
+
This is a less efficient (but more open-ended) implementation of locale
|
17
|
+
accessors, for use in cases where the locales to be used are not known when the
|
18
|
+
model class is generated.
|
19
|
+
|
20
|
+
@example Using fallthrough locales on a plain old ruby class
|
21
|
+
class Post
|
22
|
+
def title
|
23
|
+
"title in #{Mobility.locale}"
|
24
|
+
end
|
25
|
+
include Mobility::FallthroughAccessors.new("title")
|
26
|
+
end
|
27
|
+
|
28
|
+
Mobility.locale = :en
|
29
|
+
post = Post.new
|
30
|
+
post.title
|
31
|
+
#=> "title in en"
|
32
|
+
post.title_fr
|
33
|
+
#=> "title in fr"
|
34
|
+
|
35
|
+
=end
|
36
|
+
class FallthroughAccessors < Module
|
37
|
+
# @param [Array<String>] Array of attributes
|
38
|
+
def initialize(*attributes)
|
39
|
+
method_name_regex = /\A(#{attributes.join('|'.freeze)})_([a-z]{2}(_[a-z]{2})?)(=?)\z/.freeze
|
40
|
+
|
41
|
+
define_method :method_missing do |method_name, *arguments, &block|
|
42
|
+
if method_name =~ method_name_regex
|
43
|
+
attribute = $1.to_sym
|
44
|
+
locale, suffix = $2.split('_'.freeze)
|
45
|
+
locale = "#{locale}-#{suffix.upcase}".freeze if suffix
|
46
|
+
Mobility.with_locale(locale) { public_send("#{attribute}#{$4}".freeze, *arguments) }
|
47
|
+
else
|
48
|
+
super(method_name, *arguments, &block)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
define_method :respond_to_missing? do |method_name, include_private = false|
|
53
|
+
(method_name =~ method_name_regex) || super(method_name, include_private)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -14,7 +14,7 @@ is called.
|
|
14
14
|
define_method :mobility_set do |attribute, value, locale: Mobility.locale|
|
15
15
|
if attributes.include?(attribute)
|
16
16
|
column = attribute.to_sym
|
17
|
-
column_with_locale = :"#{attribute}_#{locale}"
|
17
|
+
column_with_locale = :"#{attribute}_#{Mobility.normalize_locale(locale)}"
|
18
18
|
if mobility_get(attribute) != value
|
19
19
|
@changed_columns << column_with_locale if !changed_columns.include?(column_with_locale)
|
20
20
|
@changed_columns << column if !changed_columns.include?(column)
|
data/lib/mobility/version.rb
CHANGED
data/lib/mobility.rb
CHANGED
@@ -32,13 +32,14 @@ in backends to define gem-dependent behavior.
|
|
32
32
|
|
33
33
|
=end
|
34
34
|
module Mobility
|
35
|
-
autoload :Attributes,
|
36
|
-
autoload :Backend,
|
37
|
-
autoload :BackendResetter,
|
38
|
-
autoload :Configuration,
|
39
|
-
autoload :
|
40
|
-
autoload :
|
41
|
-
autoload :
|
35
|
+
autoload :Attributes, "mobility/attributes"
|
36
|
+
autoload :Backend, "mobility/backend"
|
37
|
+
autoload :BackendResetter, "mobility/backend_resetter"
|
38
|
+
autoload :Configuration, "mobility/configuration"
|
39
|
+
autoload :FallthroughAccessors, "mobility/fallthrough_accessors"
|
40
|
+
autoload :InstanceMethods, "mobility/instance_methods"
|
41
|
+
autoload :Translates, "mobility/translates"
|
42
|
+
autoload :Wrapper, "mobility/wrapper"
|
42
43
|
|
43
44
|
require "mobility/orm"
|
44
45
|
|
@@ -122,7 +123,8 @@ module Mobility
|
|
122
123
|
|
123
124
|
# Sets Mobility locale
|
124
125
|
# @param [Symbol] locale Locale to set
|
125
|
-
# @raise [InvalidLocale] if locale is nil or not in
|
126
|
+
# @raise [InvalidLocale] if locale is nil or not in
|
127
|
+
# +I18n.available_locales+ (if +I18n.enforce_available_locales+ is +true+)
|
126
128
|
# @return [Symbol] Locale
|
127
129
|
def locale=(locale)
|
128
130
|
set_locale(locale)
|
@@ -185,8 +187,22 @@ module Mobility
|
|
185
187
|
# #=> "ja"
|
186
188
|
# Mobility.normalize_locale("pt-BR")
|
187
189
|
# #=> "pt_br"
|
188
|
-
def normalize_locale(locale)
|
189
|
-
"#{locale.to_s.downcase.sub("-", "_")}"
|
190
|
+
def normalize_locale(locale = Mobility.locale)
|
191
|
+
"#{locale.to_s.downcase.sub("-", "_")}".freeze
|
192
|
+
end
|
193
|
+
alias_method :normalized_locale, :normalize_locale
|
194
|
+
|
195
|
+
# Return normalized locale accessor name
|
196
|
+
# @param [String,Symbol] attribute
|
197
|
+
# @param [String,Symbol] locale
|
198
|
+
# @return [String] Normalized locale accessor name
|
199
|
+
# @example
|
200
|
+
# Mobility.normalize_locale_accessor(:foo, :ja)
|
201
|
+
# #=> "foo_ja"
|
202
|
+
# Mobility.normalize_locale_accessor(:bar, "pt-BR")
|
203
|
+
# #=> "bar_pt_br"
|
204
|
+
def normalize_locale_accessor(attribute, locale = Mobility.locale)
|
205
|
+
"#{attribute}_#{normalize_locale(locale)}".freeze
|
190
206
|
end
|
191
207
|
|
192
208
|
protected
|
@@ -197,7 +213,9 @@ module Mobility
|
|
197
213
|
|
198
214
|
def set_locale(locale)
|
199
215
|
locale = locale.to_sym if locale
|
200
|
-
|
216
|
+
if I18n.enforce_available_locales
|
217
|
+
raise Mobility::InvalidLocale.new(locale) unless (I18n.available_locales.include?(locale) || locale.nil?)
|
218
|
+
end
|
201
219
|
storage[:mobility_locale] = locale
|
202
220
|
end
|
203
221
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mobility
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Chris Salzberg
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-03-
|
11
|
+
date: 2017-03-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: request_store
|
@@ -140,8 +140,6 @@ files:
|
|
140
140
|
- lib/generators/mobility/install_generator.rb
|
141
141
|
- lib/generators/mobility/templates/create_string_translations.rb
|
142
142
|
- lib/generators/mobility/templates/create_text_translations.rb
|
143
|
-
- lib/generators/mobility/templates/translations.rb
|
144
|
-
- lib/generators/mobility/translations_generator.rb
|
145
143
|
- lib/mobility.rb
|
146
144
|
- lib/mobility/active_model.rb
|
147
145
|
- lib/mobility/active_model/attribute_methods.rb
|
@@ -176,7 +174,6 @@ files:
|
|
176
174
|
- lib/mobility/backend/dirty.rb
|
177
175
|
- lib/mobility/backend/fallbacks.rb
|
178
176
|
- lib/mobility/backend/hstore.rb
|
179
|
-
- lib/mobility/backend/i18n.rb
|
180
177
|
- lib/mobility/backend/jsonb.rb
|
181
178
|
- lib/mobility/backend/key_value.rb
|
182
179
|
- lib/mobility/backend/null.rb
|
@@ -203,6 +200,7 @@ files:
|
|
203
200
|
- lib/mobility/configuration.rb
|
204
201
|
- lib/mobility/core_ext/object.rb
|
205
202
|
- lib/mobility/core_ext/string.rb
|
203
|
+
- lib/mobility/fallthrough_accessors.rb
|
206
204
|
- lib/mobility/instance_methods.rb
|
207
205
|
- lib/mobility/orm.rb
|
208
206
|
- lib/mobility/sequel.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
|
2
|
-
<%- if migration_action == 'add' -%>
|
3
|
-
def change
|
4
|
-
<% attributes.each do |attribute| -%>
|
5
|
-
<%- if attribute.reference? -%>
|
6
|
-
add_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
|
7
|
-
<%- elsif attribute.token? -%>
|
8
|
-
add_column :<%= table_name %>, :<%= attribute.name %>, :string<%= attribute.inject_options %>
|
9
|
-
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>, unique: true
|
10
|
-
<%- else -%>
|
11
|
-
add_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
|
12
|
-
<%- if attribute.has_index? -%>
|
13
|
-
add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
14
|
-
<%- end -%>
|
15
|
-
<%- end -%>
|
16
|
-
<%- end -%>
|
17
|
-
end
|
18
|
-
<%- elsif migration_action == 'join' -%>
|
19
|
-
def change
|
20
|
-
create_join_table :<%= join_tables.first %>, :<%= join_tables.second %> do |t|
|
21
|
-
<%- attributes.each do |attribute| -%>
|
22
|
-
<%- if attribute.reference? -%>
|
23
|
-
t.references :<%= attribute.name %><%= attribute.inject_options %>
|
24
|
-
<%- else -%>
|
25
|
-
<%= '# ' unless attribute.has_index? -%>t.index <%= attribute.index_name %><%= attribute.inject_index_options %>
|
26
|
-
<%- end -%>
|
27
|
-
<%- end -%>
|
28
|
-
end
|
29
|
-
end
|
30
|
-
<%- else -%>
|
31
|
-
def change
|
32
|
-
<% attributes.each do |attribute| -%>
|
33
|
-
<%- if migration_action -%>
|
34
|
-
<%- if attribute.reference? -%>
|
35
|
-
remove_reference :<%= table_name %>, :<%= attribute.name %><%= attribute.inject_options %>
|
36
|
-
<%- else -%>
|
37
|
-
<%- if attribute.has_index? -%>
|
38
|
-
remove_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
|
39
|
-
<%- end -%>
|
40
|
-
remove_column :<%= table_name %>, :<%= attribute.name %>, :<%= attribute.type %><%= attribute.inject_options %>
|
41
|
-
<%- end -%>
|
42
|
-
<%- end -%>
|
43
|
-
<%- end -%>
|
44
|
-
end
|
45
|
-
<%- end -%>
|
46
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require "rails/generators"
|
2
|
-
require "rails/generators/active_record/migration/migration_generator"
|
3
|
-
|
4
|
-
module Mobility
|
5
|
-
class TranslationsGenerator < ::Rails::Generators::NamedBase
|
6
|
-
include Rails::Generators::Migration
|
7
|
-
|
8
|
-
argument :attributes, type: :array, default: [], banner: "field[:type] field[:type]"
|
9
|
-
source_root File.expand_path("../templates", __FILE__)
|
10
|
-
class_option(
|
11
|
-
:backend,
|
12
|
-
type: :string,
|
13
|
-
desc: "Backend to use for translations (defaults to Mobility.default_backend)"
|
14
|
-
)
|
15
|
-
|
16
|
-
def self.next_migration_number(dirname)
|
17
|
-
::ActiveRecord::Generators::Base.next_migration_number(dirname)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
@@ -1,28 +0,0 @@
|
|
1
|
-
# module Mobility
|
2
|
-
# module Backend
|
3
|
-
# class I18n
|
4
|
-
# include Backend
|
5
|
-
|
6
|
-
# attr_reader :i18n_key
|
7
|
-
# attr_reader :mapping
|
8
|
-
|
9
|
-
# def initialize(model, attribute, **)
|
10
|
-
# super
|
11
|
-
# @key_map = options[:key_map]
|
12
|
-
# end
|
13
|
-
|
14
|
-
# def read(locale, **)
|
15
|
-
# I18n.t(i18n_key)
|
16
|
-
# end
|
17
|
-
|
18
|
-
# def self.configure!(options)
|
19
|
-
# raise ArgumentError, "missing key_map" unless options[:key_map].present?
|
20
|
-
# end
|
21
|
-
|
22
|
-
# private
|
23
|
-
|
24
|
-
# def i18n_key
|
25
|
-
# key_map.call(model, attribute))
|
26
|
-
# end
|
27
|
-
# end
|
28
|
-
# end
|