mobility 0.8.13 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +2 -2
- data.tar.gz.sig +0 -0
- data/CHANGELOG.md +63 -0
- data/Gemfile +5 -2
- data/Gemfile.lock +39 -20
- data/README.md +183 -93
- data/lib/mobility.rb +101 -169
- data/lib/mobility/backend.rb +27 -51
- data/lib/mobility/backends.rb +20 -0
- data/lib/mobility/backends/active_record.rb +4 -0
- data/lib/mobility/backends/active_record/column.rb +3 -1
- data/lib/mobility/backends/active_record/container.rb +10 -11
- data/lib/mobility/backends/active_record/hstore.rb +6 -4
- data/lib/mobility/backends/active_record/json.rb +5 -3
- data/lib/mobility/backends/active_record/jsonb.rb +5 -3
- data/lib/mobility/backends/active_record/key_value.rb +31 -13
- data/lib/mobility/backends/active_record/pg_hash.rb +1 -1
- data/lib/mobility/backends/active_record/serialized.rb +6 -0
- data/lib/mobility/backends/active_record/table.rb +17 -10
- data/lib/mobility/backends/column.rb +0 -6
- data/lib/mobility/backends/container.rb +10 -1
- data/lib/mobility/backends/hash.rb +39 -0
- data/lib/mobility/backends/hash_valued.rb +4 -0
- data/lib/mobility/backends/hstore.rb +0 -1
- data/lib/mobility/backends/json.rb +0 -1
- data/lib/mobility/backends/jsonb.rb +1 -2
- data/lib/mobility/backends/key_value.rb +31 -26
- data/lib/mobility/backends/null.rb +2 -0
- data/lib/mobility/backends/sequel.rb +37 -2
- data/lib/mobility/backends/sequel/column.rb +2 -0
- data/lib/mobility/backends/sequel/container.rb +11 -9
- data/lib/mobility/backends/sequel/hstore.rb +3 -1
- data/lib/mobility/backends/sequel/json.rb +3 -0
- data/lib/mobility/backends/sequel/jsonb.rb +3 -1
- data/lib/mobility/backends/sequel/key_value.rb +87 -18
- data/lib/mobility/backends/sequel/pg_hash.rb +6 -6
- data/lib/mobility/backends/sequel/serialized.rb +6 -0
- data/lib/mobility/backends/sequel/table.rb +22 -9
- data/lib/mobility/backends/serialized.rb +1 -3
- data/lib/mobility/backends/table.rb +39 -31
- data/lib/mobility/pluggable.rb +56 -0
- data/lib/mobility/plugin.rb +260 -0
- data/lib/mobility/plugins.rb +27 -24
- data/lib/mobility/plugins/active_model.rb +17 -0
- data/lib/mobility/plugins/active_model/cache.rb +26 -0
- data/lib/mobility/plugins/active_model/dirty.rb +119 -78
- data/lib/mobility/plugins/active_record.rb +37 -0
- data/lib/mobility/plugins/active_record/backend.rb +27 -0
- data/lib/mobility/plugins/active_record/cache.rb +28 -0
- data/lib/mobility/plugins/active_record/dirty.rb +34 -17
- data/lib/mobility/plugins/active_record/query.rb +43 -31
- data/lib/mobility/plugins/active_record/uniqueness_validation.rb +64 -0
- data/lib/mobility/plugins/arel.rb +125 -0
- data/lib/mobility/plugins/arel/nodes.rb +15 -0
- data/lib/mobility/plugins/arel/nodes/pg_ops.rb +134 -0
- data/lib/mobility/plugins/attribute_methods.rb +29 -20
- data/lib/mobility/plugins/attributes.rb +72 -0
- data/lib/mobility/plugins/backend.rb +161 -0
- data/lib/mobility/plugins/backend_reader.rb +34 -0
- data/lib/mobility/plugins/cache.rb +68 -26
- data/lib/mobility/plugins/default.rb +22 -17
- data/lib/mobility/plugins/dirty.rb +12 -33
- data/lib/mobility/plugins/fallbacks.rb +52 -44
- data/lib/mobility/plugins/fallthrough_accessors.rb +19 -23
- data/lib/mobility/plugins/locale_accessors.rb +22 -35
- data/lib/mobility/plugins/presence.rb +28 -21
- data/lib/mobility/plugins/query.rb +8 -17
- data/lib/mobility/plugins/reader.rb +50 -0
- data/lib/mobility/plugins/sequel.rb +34 -0
- data/lib/mobility/plugins/sequel/backend.rb +25 -0
- data/lib/mobility/plugins/sequel/cache.rb +24 -0
- data/lib/mobility/plugins/sequel/dirty.rb +34 -23
- data/lib/mobility/plugins/sequel/query.rb +21 -6
- data/lib/mobility/plugins/writer.rb +44 -0
- data/lib/mobility/translations.rb +95 -0
- data/lib/mobility/version.rb +12 -1
- data/lib/rails/generators/mobility/templates/create_string_translations.rb +0 -1
- data/lib/rails/generators/mobility/templates/create_text_translations.rb +0 -1
- data/lib/rails/generators/mobility/templates/initializer.rb +104 -78
- metadata +35 -40
- metadata.gz.sig +0 -0
- data/lib/mobility/active_model.rb +0 -4
- data/lib/mobility/active_model/backend_resetter.rb +0 -26
- data/lib/mobility/active_record.rb +0 -23
- data/lib/mobility/active_record/backend_resetter.rb +0 -26
- data/lib/mobility/active_record/model_translation.rb +0 -14
- data/lib/mobility/active_record/string_translation.rb +0 -10
- data/lib/mobility/active_record/text_translation.rb +0 -10
- data/lib/mobility/active_record/translation.rb +0 -14
- data/lib/mobility/active_record/uniqueness_validator.rb +0 -60
- data/lib/mobility/arel.rb +0 -49
- data/lib/mobility/arel/nodes.rb +0 -13
- data/lib/mobility/arel/nodes/pg_ops.rb +0 -132
- data/lib/mobility/arel/visitor.rb +0 -61
- data/lib/mobility/attributes.rb +0 -324
- data/lib/mobility/backend/orm_delegator.rb +0 -44
- data/lib/mobility/backend_resetter.rb +0 -50
- data/lib/mobility/configuration.rb +0 -138
- data/lib/mobility/fallbacks.rb +0 -28
- data/lib/mobility/interface.rb +0 -0
- data/lib/mobility/loaded.rb +0 -4
- data/lib/mobility/plugins/active_record/attribute_methods.rb +0 -38
- data/lib/mobility/plugins/cache/translation_cacher.rb +0 -40
- data/lib/mobility/sequel.rb +0 -9
- data/lib/mobility/sequel/backend_resetter.rb +0 -23
- data/lib/mobility/sequel/column_changes.rb +0 -28
- data/lib/mobility/sequel/hash_initializer.rb +0 -21
- data/lib/mobility/sequel/model_translation.rb +0 -20
- data/lib/mobility/sequel/sql.rb +0 -16
- data/lib/mobility/sequel/string_translation.rb +0 -10
- data/lib/mobility/sequel/text_translation.rb +0 -10
- data/lib/mobility/sequel/translation.rb +0 -53
- data/lib/mobility/translates.rb +0 -73
data/lib/mobility.rb
CHANGED
|
@@ -6,100 +6,94 @@ require 'mobility/version'
|
|
|
6
6
|
=begin
|
|
7
7
|
|
|
8
8
|
Mobility is a gem for storing and retrieving localized data through attributes
|
|
9
|
-
on a class.
|
|
10
|
-
support defining backend accessors on a class.
|
|
9
|
+
on a class.
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
There are two ways to translate attributes on a class, both of which are
|
|
12
|
+
variations on the same basic mechanism. The first and most common way is to
|
|
13
|
+
extend the `Mobility` module, which adds a class method +translates+.
|
|
14
|
+
Translated attributes can then be defined like this:
|
|
15
15
|
|
|
16
|
-
class
|
|
16
|
+
class Post
|
|
17
17
|
extend Mobility
|
|
18
18
|
translates :title, backend: :key_value
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
in backends to define gem-dependent behavior.
|
|
21
|
+
Behind the scenes, +translates+ simply creates an instance of
|
|
22
|
+
+Mobility.translations_class+, passes it whatever arguments are passed to
|
|
23
|
+
+translates+, and includes the instance (which is a module) into the class.
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
module Mobility
|
|
28
|
-
require "mobility/attributes"
|
|
29
|
-
require "mobility/backend"
|
|
30
|
-
require "mobility/backends"
|
|
31
|
-
require "mobility/backend_resetter"
|
|
32
|
-
require "mobility/configuration"
|
|
33
|
-
require "mobility/fallbacks"
|
|
34
|
-
require "mobility/loaded"
|
|
35
|
-
require "mobility/plugins"
|
|
36
|
-
require "mobility/translates"
|
|
25
|
+
So the above example is equivalent to:
|
|
37
26
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
27
|
+
class Post
|
|
28
|
+
Mobility.translations_class.new(:title, backend: :key_value)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
`Mobility.translations_class` is a subclass of `Mobility::Translations` created
|
|
32
|
+
when `Mobility.configure` is called to configure Mobility. In fact, when you
|
|
33
|
+
call `Mobility.configure`, it is the subclass of `Mobility::Translations` which
|
|
34
|
+
is passed to the block as `config`. Plugins and plugin configuration is all
|
|
35
|
+
applied to the same `Mobility.translations_class`.
|
|
36
|
+
|
|
37
|
+
There is another way to use Mobility, which is to create your own subclass or
|
|
38
|
+
subclasses of +Mobility::Translations+ and include them explicitly, without
|
|
39
|
+
using +translates+.
|
|
42
40
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
41
|
+
For example:
|
|
42
|
+
|
|
43
|
+
class Translations < Mobility::Translations
|
|
44
|
+
plugins do
|
|
45
|
+
backend :key_value
|
|
46
|
+
# ...
|
|
47
|
+
end
|
|
49
48
|
end
|
|
50
49
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
raise VersionNotSupportedError, "Mobility is only compatible with ActiveRecord 4.2 and greater" if ::ActiveRecord::VERSION::STRING < "4.2"
|
|
54
|
-
Loaded::ActiveRecord = true
|
|
55
|
-
rescue LoadError => e
|
|
56
|
-
raise unless e.message =~ /active_record/
|
|
57
|
-
Loaded::ActiveRecord = false
|
|
50
|
+
class Post
|
|
51
|
+
include Translations.new(:title)
|
|
58
52
|
end
|
|
59
53
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
This usage might be handy if, for example, you want to have more complex
|
|
55
|
+
configuration, where some models use some plugins while others do not. Since
|
|
56
|
+
`Mobility::Translations` is a class like any other, you can subclass it and
|
|
57
|
+
define plugins specifically on the subclass which are not present on its
|
|
58
|
+
parent:
|
|
59
|
+
|
|
60
|
+
class TranslationsWithFallbacks < Translations
|
|
61
|
+
plugins do
|
|
62
|
+
fallbacks
|
|
65
63
|
end
|
|
66
64
|
end
|
|
67
65
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
raise VersionNotSupportedError, "Mobility is only compatible with Sequel 4.0 and greater" if ::Sequel::MAJOR < 4
|
|
71
|
-
require "sequel/plugins/mobility"
|
|
72
|
-
unless defined?(ActiveSupport::Inflector)
|
|
73
|
-
# TODO: avoid automatically including the inflector extension
|
|
74
|
-
require "sequel/extensions/inflector"
|
|
75
|
-
end
|
|
76
|
-
require "sequel/plugins/dirty"
|
|
77
|
-
require "mobility/sequel"
|
|
78
|
-
Loaded::Sequel = true
|
|
79
|
-
rescue LoadError => e
|
|
80
|
-
raise unless e.message =~ /sequel/
|
|
81
|
-
Loaded::Sequel = false
|
|
66
|
+
class Comment
|
|
67
|
+
include TranslationsWithFallbacks.new(:author)
|
|
82
68
|
end
|
|
83
69
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
70
|
+
In this case, +Comment+ uses +TranslationsWithFallbacks+ and thus has the
|
|
71
|
+
fallbacks plugin, whereas +Post+ uses +Translations+ which does not have that
|
|
72
|
+
plugin enabled.
|
|
87
73
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
74
|
+
=end
|
|
75
|
+
module Mobility
|
|
76
|
+
# A generic exception used by Mobility.
|
|
77
|
+
class Error < StandardError
|
|
78
|
+
end
|
|
92
79
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
80
|
+
require "mobility/backend"
|
|
81
|
+
require "mobility/backends"
|
|
82
|
+
require "mobility/plugin"
|
|
83
|
+
require "mobility/plugins"
|
|
84
|
+
require "mobility/translations"
|
|
96
85
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
86
|
+
# General error for version compatibility conflicts
|
|
87
|
+
class VersionNotSupportedError < ArgumentError; end
|
|
88
|
+
CALL_COMPILABLE_REGEXP = /\A[a-zA-Z_]\w*[!?]?\z/
|
|
89
|
+
private_constant :CALL_COMPILABLE_REGEXP
|
|
100
90
|
|
|
101
|
-
|
|
102
|
-
|
|
91
|
+
require "rails/generators/mobility/generators" if defined?(Rails)
|
|
92
|
+
|
|
93
|
+
class << self
|
|
94
|
+
def extended(model_class)
|
|
95
|
+
def model_class.translates(*args, **options)
|
|
96
|
+
include Mobility.translations_class.new(*args, **options)
|
|
103
97
|
end
|
|
104
98
|
end
|
|
105
99
|
|
|
@@ -110,6 +104,38 @@ module Mobility
|
|
|
110
104
|
model_class.extend self
|
|
111
105
|
end
|
|
112
106
|
|
|
107
|
+
# Alias to default backend defined on *translations_class+.
|
|
108
|
+
# @return [Symbol,Class]
|
|
109
|
+
def default_backend
|
|
110
|
+
translations_class.defaults[:backend]
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# Configure Mobility
|
|
114
|
+
# @yield [Mobility::Translations]
|
|
115
|
+
def configure(&block)
|
|
116
|
+
translates_with(Class.new(Translations)) unless @translations_class
|
|
117
|
+
if block.arity == 0
|
|
118
|
+
translations_class.instance_exec(&block)
|
|
119
|
+
else
|
|
120
|
+
yield translations_class
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def translates_with(pluggable)
|
|
125
|
+
raise ArgumentError, "translations class must be a subclass of Module." unless Module === pluggable
|
|
126
|
+
@translations_class = pluggable
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def translations_class
|
|
130
|
+
@translations_class ||
|
|
131
|
+
raise(Error, "Mobility has not been configured. "\
|
|
132
|
+
"Configure with Mobility.configure, or assign a translations class with Mobility.translates_with(<class>)")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def reset_translations_class
|
|
136
|
+
@translations_class = nil
|
|
137
|
+
end
|
|
138
|
+
|
|
113
139
|
# @!group Locale Accessors
|
|
114
140
|
# @return [Symbol] Mobility locale
|
|
115
141
|
def locale
|
|
@@ -144,55 +170,6 @@ module Mobility
|
|
|
144
170
|
RequestStore.store
|
|
145
171
|
end
|
|
146
172
|
|
|
147
|
-
# @!group Configuration Methods
|
|
148
|
-
# @return [Mobility::Configuration] Mobility configuration
|
|
149
|
-
def config
|
|
150
|
-
@configuration ||= Configuration.new
|
|
151
|
-
end
|
|
152
|
-
|
|
153
|
-
# (see Mobility::Configuration#accessor_method)
|
|
154
|
-
# @!method accessor_method
|
|
155
|
-
#
|
|
156
|
-
# (see Mobility::Configuration#query_method)
|
|
157
|
-
# @!method query_method
|
|
158
|
-
|
|
159
|
-
# (see Mobility::Configuration#new_fallbacks)
|
|
160
|
-
# @!method new_fallbacks
|
|
161
|
-
|
|
162
|
-
# (see Mobility::Configuration#default_backend)
|
|
163
|
-
# @!method default_backend
|
|
164
|
-
|
|
165
|
-
# (see Mobility::Configuration#default_options)
|
|
166
|
-
# @!method default_options
|
|
167
|
-
#
|
|
168
|
-
# (see Mobility::Configuration#plugins)
|
|
169
|
-
# @!method plugins
|
|
170
|
-
#
|
|
171
|
-
# (see Mobility::Configuration#default_accessor_locales)
|
|
172
|
-
# @!method default_accessor_locales
|
|
173
|
-
%w[accessor_method query_method default_backend default_options plugins default_accessor_locales].each do |method_name|
|
|
174
|
-
define_method method_name do
|
|
175
|
-
config.public_send(method_name)
|
|
176
|
-
end
|
|
177
|
-
end
|
|
178
|
-
|
|
179
|
-
# TODO: Remove in v1.0
|
|
180
|
-
def default_fallbacks(*args)
|
|
181
|
-
config.public_send(:default_fallbacks, *args)
|
|
182
|
-
end
|
|
183
|
-
|
|
184
|
-
# TODO: Make private in v1.0
|
|
185
|
-
def new_fallbacks(*args)
|
|
186
|
-
config.public_send(:new_fallbacks, *args)
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
# Configure Mobility
|
|
190
|
-
# @yield [Mobility::Configuration] Mobility configuration
|
|
191
|
-
def configure
|
|
192
|
-
yield config
|
|
193
|
-
end
|
|
194
|
-
# @!endgroup
|
|
195
|
-
|
|
196
173
|
# Return normalized locale
|
|
197
174
|
# @param [String,Symbol] locale
|
|
198
175
|
# @return [String] Normalized locale
|
|
@@ -228,17 +205,7 @@ module Mobility
|
|
|
228
205
|
# @param [String,Symbol] locale
|
|
229
206
|
# @raise [InvalidLocale] if locale is present but not available
|
|
230
207
|
def enforce_available_locales!(locale)
|
|
231
|
-
|
|
232
|
-
if I18n.enforce_available_locales
|
|
233
|
-
raise Mobility::InvalidLocale.new(locale) unless (I18n.locale_available?(locale) || locale.nil?)
|
|
234
|
-
else
|
|
235
|
-
warn <<-EOL
|
|
236
|
-
WARNING: You called Mobility.enforce_available_locales! in a situation where
|
|
237
|
-
I18n.enforce_available_locales is false. In the past, Mobility would do nothing
|
|
238
|
-
in this case, but as of the next major release Mobility will ignore the I18n
|
|
239
|
-
setting and enforce available locales whenever this method is called.
|
|
240
|
-
EOL
|
|
241
|
-
end
|
|
208
|
+
raise Mobility::InvalidLocale.new(locale) unless (locale.nil? || available_locales.include?(locale.to_sym))
|
|
242
209
|
end
|
|
243
210
|
|
|
244
211
|
# Returns available locales. Defaults to I18n.available_locales, but will
|
|
@@ -250,8 +217,8 @@ EOL
|
|
|
250
217
|
# simply default to +I18n.available_locales+, we may define many more
|
|
251
218
|
# methods (in LocaleAccessors) than is really necessary.
|
|
252
219
|
def available_locales
|
|
253
|
-
if
|
|
254
|
-
Rails.application.config.i18n.available_locales || I18n.available_locales
|
|
220
|
+
if defined?(Rails) && Rails.application
|
|
221
|
+
Rails.application.config.i18n.available_locales&.map(&:to_sym) || I18n.available_locales
|
|
255
222
|
else
|
|
256
223
|
I18n.available_locales
|
|
257
224
|
end
|
|
@@ -270,41 +237,6 @@ EOL
|
|
|
270
237
|
end
|
|
271
238
|
end
|
|
272
239
|
|
|
273
|
-
# TODO: Remove entire module in v1.0
|
|
274
|
-
module InstanceMethods
|
|
275
|
-
# Fetch backend for an attribute
|
|
276
|
-
# @deprecated Use mobility_backends[:<attribute>] instead.
|
|
277
|
-
# @param [String] attribute Attribute
|
|
278
|
-
def mobility_backend_for(attribute)
|
|
279
|
-
warn %{
|
|
280
|
-
WARNING: mobility_backend_for is deprecated and will be removed in the next
|
|
281
|
-
version of Mobility. Use <post>.<attribute>_backend instead.}
|
|
282
|
-
mobility_backends[attribute.to_sym]
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
def mobility
|
|
286
|
-
warn %{
|
|
287
|
-
WARNING: <post>.mobility is deprecated and will be removed in the next
|
|
288
|
-
version of Mobility. To get backends, use <post>.<attribute>_backend instead.}
|
|
289
|
-
@mobility ||= Adapter.new(self)
|
|
290
|
-
end
|
|
291
|
-
|
|
292
|
-
class Adapter < Struct.new(:model)
|
|
293
|
-
def backend_for(attribute)
|
|
294
|
-
model.mobility_backends[attribute.to_sym]
|
|
295
|
-
end
|
|
296
|
-
end
|
|
297
|
-
private_constant :Adapter
|
|
298
|
-
end
|
|
299
|
-
|
|
300
|
-
module ClassMethods
|
|
301
|
-
# Return translated attribute names on this model.
|
|
302
|
-
# @return [Array<String>] Attribute names
|
|
303
|
-
def mobility_attributes
|
|
304
|
-
[]
|
|
305
|
-
end
|
|
306
|
-
end
|
|
307
|
-
|
|
308
240
|
class InvalidLocale < I18n::InvalidLocale; end
|
|
309
241
|
class NotImplementedError < StandardError; end
|
|
310
242
|
end
|
data/lib/mobility/backend.rb
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
# frozen-string-literal: true
|
|
2
|
-
require "mobility/backend/orm_delegator"
|
|
3
|
-
|
|
4
2
|
module Mobility
|
|
5
3
|
=begin
|
|
6
4
|
|
|
@@ -9,10 +7,9 @@ Defines a minimum set of shared components included in any backend. These are:
|
|
|
9
7
|
- a reader returning the +model+ on which the backend is defined ({#model})
|
|
10
8
|
- a reader returning the +attribute+ for which the backend is defined
|
|
11
9
|
({#attribute})
|
|
12
|
-
- a constructor setting these two elements (+model+, +attribute+)
|
|
13
|
-
extracting fallbacks from the options hash ({#initialize})
|
|
10
|
+
- a constructor setting these two elements (+model+, +attribute+)
|
|
14
11
|
- a +setup+ method adding any configuration code to the model class
|
|
15
|
-
({
|
|
12
|
+
({ClassMethods#setup})
|
|
16
13
|
|
|
17
14
|
On top of this, a backend will normally:
|
|
18
15
|
|
|
@@ -50,7 +47,7 @@ On top of this, a backend will normally:
|
|
|
50
47
|
end
|
|
51
48
|
end
|
|
52
49
|
|
|
53
|
-
@see Mobility::
|
|
50
|
+
@see Mobility::Translations
|
|
54
51
|
|
|
55
52
|
=end
|
|
56
53
|
|
|
@@ -66,9 +63,9 @@ On top of this, a backend will normally:
|
|
|
66
63
|
# @!macro [new] backend_constructor
|
|
67
64
|
# @param model Model on which backend is defined
|
|
68
65
|
# @param [String] attribute Backend attribute
|
|
69
|
-
def initialize(
|
|
70
|
-
@model =
|
|
71
|
-
@attribute =
|
|
66
|
+
def initialize(*args)
|
|
67
|
+
@model = args[0]
|
|
68
|
+
@attribute = args[1]
|
|
72
69
|
end
|
|
73
70
|
|
|
74
71
|
# @!macro [new] backend_reader
|
|
@@ -103,7 +100,7 @@ On top of this, a backend will normally:
|
|
|
103
100
|
# @param [Symbol] locale Locale to read
|
|
104
101
|
# @return [TrueClass,FalseClass] Whether translation is present for locale
|
|
105
102
|
def present?(locale, options = {})
|
|
106
|
-
Util.present?(read(locale, options))
|
|
103
|
+
Util.present?(read(locale, **options))
|
|
107
104
|
end
|
|
108
105
|
|
|
109
106
|
# @!method model_class
|
|
@@ -118,21 +115,18 @@ On top of this, a backend will normally:
|
|
|
118
115
|
# Extend included class with +setup+ method and other class methods
|
|
119
116
|
def self.included(base)
|
|
120
117
|
base.extend ClassMethods
|
|
121
|
-
|
|
122
|
-
@options
|
|
123
|
-
end
|
|
124
|
-
base.option_reader :model_class
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# @param [String] attribute
|
|
128
|
-
# @return [String] name of backend reader method
|
|
129
|
-
def self.method_name(attribute)
|
|
130
|
-
@backend_method_names ||= {}
|
|
131
|
-
@backend_method_names[attribute] ||= "#{attribute}_backend"
|
|
118
|
+
base.singleton_class.attr_reader :options, :model_class
|
|
132
119
|
end
|
|
133
120
|
|
|
134
121
|
# Defines setup hooks for backend to customize model class.
|
|
135
122
|
module ClassMethods
|
|
123
|
+
# Returns valid option keys for this backend. This is overriden in
|
|
124
|
+
# backends to define which keys are valid for each backend class.
|
|
125
|
+
# @return [Array]
|
|
126
|
+
def valid_keys
|
|
127
|
+
[]
|
|
128
|
+
end
|
|
129
|
+
|
|
136
130
|
# Assign block to be called on model class.
|
|
137
131
|
# @yield [attribute_names, options]
|
|
138
132
|
# @note When called multiple times, setup blocks will be appended
|
|
@@ -152,6 +146,7 @@ On top of this, a backend will normally:
|
|
|
152
146
|
def inherited(subclass)
|
|
153
147
|
subclass.instance_variable_set(:@setup_block, @setup_block)
|
|
154
148
|
subclass.instance_variable_set(:@options, @options)
|
|
149
|
+
subclass.instance_variable_set(:@model_class, @model_class)
|
|
155
150
|
end
|
|
156
151
|
|
|
157
152
|
# Call setup block on a class with attributes and options.
|
|
@@ -166,14 +161,14 @@ On top of this, a backend will normally:
|
|
|
166
161
|
# Build a subclass of this backend class for a given set of options
|
|
167
162
|
# @note This method also freezes the options hash to prevent it from
|
|
168
163
|
# being changed.
|
|
164
|
+
# @param [Class] model_class Class
|
|
169
165
|
# @param [Hash] options
|
|
170
166
|
# @return [Class] backend subclass
|
|
171
|
-
def
|
|
172
|
-
configure(options) if respond_to?(:configure)
|
|
173
|
-
options.freeze
|
|
167
|
+
def build_subclass(model_class, options)
|
|
174
168
|
Class.new(self) do
|
|
175
|
-
@
|
|
176
|
-
|
|
169
|
+
@model_class = model_class
|
|
170
|
+
configure(options) if respond_to?(:configure)
|
|
171
|
+
@options = options.freeze
|
|
177
172
|
end
|
|
178
173
|
end
|
|
179
174
|
|
|
@@ -191,27 +186,6 @@ On top of this, a backend will normally:
|
|
|
191
186
|
EOM
|
|
192
187
|
end
|
|
193
188
|
|
|
194
|
-
# {Attributes} uses this method to get a backend class specific to the
|
|
195
|
-
# model using the backend. Backend classes can override this method to
|
|
196
|
-
# return a class specific to the model class using the backend (e.g.
|
|
197
|
-
# either an ActiveRecord or Sequel backend class depending on whether the
|
|
198
|
-
# model is an ActiveRecord model or a Sequel model.)
|
|
199
|
-
# @see OrmDelegator
|
|
200
|
-
# @see Attributes
|
|
201
|
-
# @return [self] returns itself
|
|
202
|
-
def for(_)
|
|
203
|
-
self
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
# Called from plugins to apply custom processing for this backend.
|
|
207
|
-
# Name is the name of the plugin.
|
|
208
|
-
# @param [Symbol] name Name of plugin
|
|
209
|
-
# @return [Boolean] Whether the plugin was applied
|
|
210
|
-
# @note This is currently only called by Plugins::Cache.
|
|
211
|
-
def apply_plugin(_)
|
|
212
|
-
false
|
|
213
|
-
end
|
|
214
|
-
|
|
215
189
|
# Show useful information about this backend class, if it has no name.
|
|
216
190
|
# @return [String]
|
|
217
191
|
def inspect
|
|
@@ -220,10 +194,12 @@ On top of this, a backend will normally:
|
|
|
220
194
|
end
|
|
221
195
|
|
|
222
196
|
Translation = Struct.new(:backend, :locale) do
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
197
|
+
def read(options = {})
|
|
198
|
+
backend.read(locale, options)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def write(value, options = {})
|
|
202
|
+
backend.write(locale, value, options)
|
|
227
203
|
end
|
|
228
204
|
end
|
|
229
205
|
end
|