mobility 0.1.5 → 0.1.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|