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/backends.rb
CHANGED
|
@@ -1,4 +1,24 @@
|
|
|
1
1
|
module Mobility
|
|
2
2
|
module Backends
|
|
3
|
+
@backends = {}
|
|
4
|
+
|
|
5
|
+
class << self
|
|
6
|
+
# @param [Symbol, Object] backend Name of backend to load.
|
|
7
|
+
def load_backend(name)
|
|
8
|
+
return name if Module === name || name.nil?
|
|
9
|
+
|
|
10
|
+
unless (backend = @backends[name])
|
|
11
|
+
require "mobility/backends/#{name}"
|
|
12
|
+
raise LoadError, "backend #{name} did not register itself correctly in Mobility::Backends" unless (backend = @backends[name])
|
|
13
|
+
end
|
|
14
|
+
backend
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def self.register_backend(name, mod)
|
|
19
|
+
@backends[name] = mod
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class LoadError < Error; end
|
|
3
23
|
end
|
|
4
24
|
end
|
|
@@ -57,7 +57,7 @@ can be run again to add new attributes or locales.)
|
|
|
57
57
|
# on model table
|
|
58
58
|
def self.build_node(attr, locale)
|
|
59
59
|
model_class.arel_table[Column.column_name_for(attr, locale)]
|
|
60
|
-
.extend(::
|
|
60
|
+
.extend(Plugins::Arel::MobilityExpressions)
|
|
61
61
|
end
|
|
62
62
|
|
|
63
63
|
private
|
|
@@ -73,5 +73,7 @@ can be run again to add new attributes or locales.)
|
|
|
73
73
|
end.compact
|
|
74
74
|
end
|
|
75
75
|
end
|
|
76
|
+
|
|
77
|
+
register_backend(:active_record_column, ActiveRecord::Column)
|
|
76
78
|
end
|
|
77
79
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
require "mobility/backends/active_record"
|
|
3
|
-
require "mobility/
|
|
3
|
+
require "mobility/backends/container"
|
|
4
|
+
require "mobility/plugins/arel/nodes/pg_ops"
|
|
4
5
|
|
|
5
6
|
module Mobility
|
|
6
7
|
module Backends
|
|
@@ -11,11 +12,7 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
|
|
|
11
12
|
=end
|
|
12
13
|
class ActiveRecord::Container
|
|
13
14
|
include ActiveRecord
|
|
14
|
-
|
|
15
|
-
# @!method column_name
|
|
16
|
-
# Returns name of json or jsonb column used to store translations
|
|
17
|
-
# @return [Symbol] (:translations) Name of translations column
|
|
18
|
-
option_reader :column_name
|
|
15
|
+
include Container
|
|
19
16
|
|
|
20
17
|
# @!group Backend Accessors
|
|
21
18
|
#
|
|
@@ -52,15 +49,15 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
|
|
|
52
49
|
|
|
53
50
|
# @param [String] attr Attribute name
|
|
54
51
|
# @param [Symbol] locale Locale
|
|
55
|
-
# @return [Mobility::Arel::Nodes::Json,Mobility::Arel::Nodes::Jsonb] Arel
|
|
52
|
+
# @return [Mobility::Plugins::Arel::Nodes::Json,Mobility::Arel::Nodes::Jsonb] Arel
|
|
56
53
|
# node for attribute on json or jsonb column
|
|
57
54
|
def build_node(attr, locale)
|
|
58
55
|
column = model_class.arel_table[column_name]
|
|
59
56
|
case column_type
|
|
60
57
|
when :json
|
|
61
|
-
Arel::Nodes::JsonContainer.new(column, build_quoted(locale), build_quoted(attr))
|
|
58
|
+
Plugins::Arel::Nodes::JsonContainer.new(column, build_quoted(locale), build_quoted(attr))
|
|
62
59
|
when :jsonb
|
|
63
|
-
Arel::Nodes::JsonbContainer.new(column, build_quoted(locale), build_quoted(attr))
|
|
60
|
+
Plugins::Arel::Nodes::JsonbContainer.new(column, build_quoted(locale), build_quoted(attr))
|
|
64
61
|
end
|
|
65
62
|
end
|
|
66
63
|
|
|
@@ -71,7 +68,7 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
|
|
|
71
68
|
private
|
|
72
69
|
|
|
73
70
|
def get_column_type
|
|
74
|
-
|
|
71
|
+
model_class.type_for_attribute(options[:column_name].to_s).try(:type).tap do |type|
|
|
75
72
|
unless %i[json jsonb].include? type
|
|
76
73
|
raise InvalidColumnType, "#{options[:column_name]} must be a column of type json or jsonb"
|
|
77
74
|
end
|
|
@@ -122,7 +119,7 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
|
|
|
122
119
|
|
|
123
120
|
class Coder
|
|
124
121
|
def self.dump(obj)
|
|
125
|
-
if obj.is_a? Hash
|
|
122
|
+
if obj.is_a? ::Hash
|
|
126
123
|
obj.inject({}) do |translations, (locale, value)|
|
|
127
124
|
value.each do |k, v|
|
|
128
125
|
(translations[locale] ||= {})[k] = v if v.present?
|
|
@@ -141,5 +138,7 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
|
|
|
141
138
|
|
|
142
139
|
class InvalidColumnType < StandardError; end
|
|
143
140
|
end
|
|
141
|
+
|
|
142
|
+
register_backend(:active_record_container, ActiveRecord::Container)
|
|
144
143
|
end
|
|
145
144
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'mobility/backends/active_record/pg_hash'
|
|
2
|
-
require 'mobility/arel/nodes/pg_ops'
|
|
2
|
+
require 'mobility/plugins/arel/nodes/pg_ops'
|
|
3
3
|
|
|
4
4
|
module Mobility
|
|
5
5
|
module Backends
|
|
@@ -18,19 +18,21 @@ Implements the {Mobility::Backends::Hstore} backend for ActiveRecord models.
|
|
|
18
18
|
|
|
19
19
|
# @!macro backend_writer
|
|
20
20
|
def write(locale, value, options = {})
|
|
21
|
-
super(locale, value && value.to_s, options)
|
|
21
|
+
super(locale, value && value.to_s, **options)
|
|
22
22
|
end
|
|
23
23
|
# @!endgroup
|
|
24
24
|
|
|
25
25
|
# @param [String] attr Attribute name
|
|
26
26
|
# @param [Symbol] locale Locale
|
|
27
|
-
# @return [Mobility::Arel::Nodes::Hstore] Arel node for value of
|
|
27
|
+
# @return [Mobility::Plugins::Arel::Nodes::Hstore] Arel node for value of
|
|
28
28
|
# attribute key on hstore column
|
|
29
29
|
def self.build_node(attr, locale)
|
|
30
30
|
column_name = column_affix % attr
|
|
31
|
-
Arel::Nodes::Hstore.new(model_class.arel_table[column_name], build_quoted(locale))
|
|
31
|
+
Plugins::Arel::Nodes::Hstore.new(model_class.arel_table[column_name], build_quoted(locale))
|
|
32
32
|
end
|
|
33
33
|
end
|
|
34
34
|
end
|
|
35
|
+
|
|
36
|
+
register_backend(:active_record_hstore, ActiveRecord::Hstore)
|
|
35
37
|
end
|
|
36
38
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'mobility/backends/active_record/pg_hash'
|
|
2
|
-
require 'mobility/arel/nodes/pg_ops'
|
|
2
|
+
require 'mobility/plugins/arel/nodes/pg_ops'
|
|
3
3
|
|
|
4
4
|
module Mobility
|
|
5
5
|
module Backends
|
|
@@ -32,13 +32,15 @@ Implements the {Mobility::Backends::Json} backend for ActiveRecord models.
|
|
|
32
32
|
|
|
33
33
|
# @param [String] attr Attribute name
|
|
34
34
|
# @param [Symbol] locale Locale
|
|
35
|
-
# @return [Mobility::Arel::Nodes::Json] Arel node for value of
|
|
35
|
+
# @return [Mobility::Plugins::Arel::Nodes::Json] Arel node for value of
|
|
36
36
|
# attribute key on jsonb column
|
|
37
37
|
def self.build_node(attr, locale)
|
|
38
38
|
column_name = column_affix % attr
|
|
39
|
-
Arel::Nodes::Json.new(model_class.arel_table[column_name], build_quoted(locale))
|
|
39
|
+
Plugins::Arel::Nodes::Json.new(model_class.arel_table[column_name], build_quoted(locale))
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
+
|
|
44
|
+
register_backend(:active_record_json, ActiveRecord::Json)
|
|
43
45
|
end
|
|
44
46
|
end
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
require 'mobility/backends/active_record/pg_hash'
|
|
2
|
-
require 'mobility/arel/nodes/pg_ops'
|
|
2
|
+
require 'mobility/plugins/arel/nodes/pg_ops'
|
|
3
3
|
|
|
4
4
|
module Mobility
|
|
5
5
|
module Backends
|
|
@@ -32,13 +32,15 @@ Implements the {Mobility::Backends::Jsonb} backend for ActiveRecord models.
|
|
|
32
32
|
|
|
33
33
|
# @param [String] attr Attribute name
|
|
34
34
|
# @param [Symbol] locale Locale
|
|
35
|
-
# @return [Mobility::Arel::Nodes::Jsonb] Arel node for value of
|
|
35
|
+
# @return [Mobility::Plugins::Arel::Nodes::Jsonb] Arel node for value of
|
|
36
36
|
# attribute key on jsonb column
|
|
37
37
|
def self.build_node(attr, locale)
|
|
38
38
|
column_name = column_affix % attr
|
|
39
|
-
Arel::Nodes::Jsonb.new(model_class.arel_table[column_name], build_quoted(locale))
|
|
39
|
+
Plugins::Arel::Nodes::Jsonb.new(model_class.arel_table[column_name], build_quoted(locale))
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
end
|
|
43
|
+
|
|
44
|
+
register_backend(:active_record_jsonb, ActiveRecord::Jsonb)
|
|
43
45
|
end
|
|
44
46
|
end
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# frozen-string-literal: true
|
|
2
2
|
require "mobility/backends/active_record"
|
|
3
3
|
require "mobility/backends/key_value"
|
|
4
|
-
require "mobility/active_record/string_translation"
|
|
5
|
-
require "mobility/active_record/text_translation"
|
|
6
4
|
|
|
7
5
|
module Mobility
|
|
8
6
|
module Backends
|
|
@@ -37,21 +35,21 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
|
|
|
37
35
|
super
|
|
38
36
|
if type = options[:type]
|
|
39
37
|
options[:association_name] ||= :"#{options[:type]}_translations"
|
|
40
|
-
options[:class_name] ||=
|
|
38
|
+
options[:class_name] ||= const_get("#{type.capitalize}Translation")
|
|
41
39
|
end
|
|
42
|
-
options[:table_alias_affix] = "#{
|
|
40
|
+
options[:table_alias_affix] = "#{model_class}_%s_#{options[:association_name]}"
|
|
43
41
|
rescue NameError
|
|
44
|
-
raise ArgumentError, "You must define a Mobility::ActiveRecord::#{type.capitalize}Translation class."
|
|
42
|
+
raise ArgumentError, "You must define a Mobility::Backends::ActiveRecord::KeyValue::#{type.capitalize}Translation class."
|
|
45
43
|
end
|
|
46
44
|
# @!endgroup
|
|
47
45
|
|
|
48
46
|
# @param [String] attr Attribute name
|
|
49
47
|
# @param [Symbol] _locale Locale
|
|
50
|
-
# @return [Mobility::Arel::Attribute] Arel attribute for aliased
|
|
48
|
+
# @return [Mobility::Plugins::Arel::Attribute] Arel attribute for aliased
|
|
51
49
|
# translation table value column
|
|
52
50
|
def build_node(attr, locale)
|
|
53
51
|
aliased_table = class_name.arel_table.alias(table_alias(attr, locale))
|
|
54
|
-
Arel::Attribute.new(aliased_table, :value, locale, self,
|
|
52
|
+
Plugins::Arel::Attribute.new(aliased_table, :value, locale, self, attr.to_sym)
|
|
55
53
|
end
|
|
56
54
|
|
|
57
55
|
# Joins translations using either INNER/OUTER join appropriate to the query.
|
|
@@ -119,7 +117,7 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
|
|
|
119
117
|
# The title predicate has a non-nil value, so we can use an INNER JOIN,
|
|
120
118
|
# whereas we are searching for nil content, which requires an OUTER JOIN.
|
|
121
119
|
#
|
|
122
|
-
class Visitor < Arel::Visitor
|
|
120
|
+
class Visitor < Plugins::Arel::Visitor
|
|
123
121
|
private
|
|
124
122
|
|
|
125
123
|
def visit_Arel_Nodes_Equality(object)
|
|
@@ -137,11 +135,11 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
|
|
|
137
135
|
alias :visit_Array :visit_collection
|
|
138
136
|
|
|
139
137
|
def visit_Arel_Nodes_Or(object)
|
|
140
|
-
[object.left, object.right].map(&method(:visit)).compact.inject(
|
|
138
|
+
[object.left, object.right].map(&method(:visit)).compact.inject(:merge).
|
|
141
139
|
transform_values { OUTER_JOIN }
|
|
142
140
|
end
|
|
143
141
|
|
|
144
|
-
def
|
|
142
|
+
def visit_Mobility_Plugins_Arel_Attribute(object)
|
|
145
143
|
if object.backend_class == backend_class && object.locale == locale
|
|
146
144
|
{ object.attribute_name => OUTER_JOIN }
|
|
147
145
|
end
|
|
@@ -194,8 +192,8 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
|
|
|
194
192
|
|
|
195
193
|
# Returns translation for a given locale, or builds one if none is present.
|
|
196
194
|
# @param [Symbol] locale
|
|
197
|
-
# @return [Mobility::ActiveRecord::TextTranslation,Mobility::ActiveRecord::StringTranslation]
|
|
198
|
-
def translation_for(locale,
|
|
195
|
+
# @return [Mobility::Backends::ActiveRecord::KeyValue::TextTranslation,Mobility::Backends::ActiveRecord::KeyValue::StringTranslation]
|
|
196
|
+
def translation_for(locale, **)
|
|
199
197
|
translation = translations.find { |t| t.key == attribute && t.locale == locale.to_s }
|
|
200
198
|
translation ||= translations.build(locale: locale, key: attribute)
|
|
201
199
|
translation
|
|
@@ -205,12 +203,32 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
|
|
|
205
203
|
def self.included(model_class)
|
|
206
204
|
model_class.after_destroy do
|
|
207
205
|
[:string, :text].each do |type|
|
|
208
|
-
Mobility::ActiveRecord.const_get("#{type.capitalize}Translation").
|
|
206
|
+
Mobility::Backends::ActiveRecord::KeyValue.const_get("#{type.capitalize}Translation").
|
|
209
207
|
where(translatable: self).destroy_all
|
|
210
208
|
end
|
|
211
209
|
end
|
|
212
210
|
end
|
|
213
211
|
end
|
|
212
|
+
|
|
213
|
+
class Translation < ::ActiveRecord::Base
|
|
214
|
+
self.abstract_class = true
|
|
215
|
+
|
|
216
|
+
belongs_to :translatable, polymorphic: true, touch: true
|
|
217
|
+
|
|
218
|
+
validates :key, presence: true, uniqueness: { scope: [:translatable_id, :translatable_type, :locale], case_sensitive: true }
|
|
219
|
+
validates :translatable, presence: true
|
|
220
|
+
validates :locale, presence: true
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
class TextTranslation < Translation
|
|
224
|
+
self.table_name = "mobility_text_translations"
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
class StringTranslation < Translation
|
|
228
|
+
self.table_name = "mobility_string_translations"
|
|
229
|
+
end
|
|
214
230
|
end
|
|
231
|
+
|
|
232
|
+
register_backend(:active_record_key_value, ActiveRecord::KeyValue)
|
|
215
233
|
end
|
|
216
234
|
end
|
|
@@ -30,7 +30,7 @@ Internal class used by ActiveRecord backends backed by a Postgres data type
|
|
|
30
30
|
|
|
31
31
|
class Coder
|
|
32
32
|
def self.dump(obj)
|
|
33
|
-
if obj.is_a? Hash
|
|
33
|
+
if obj.is_a? ::Hash
|
|
34
34
|
obj.inject({}) do |translations, (locale, value)|
|
|
35
35
|
translations[locale] = value if value.present?
|
|
36
36
|
translations
|
|
@@ -30,6 +30,10 @@ Implements {Mobility::Backends::Serialized} backend for ActiveRecord models.
|
|
|
30
30
|
include ActiveRecord
|
|
31
31
|
include HashValued
|
|
32
32
|
|
|
33
|
+
def self.valid_keys
|
|
34
|
+
super + [:format]
|
|
35
|
+
end
|
|
36
|
+
|
|
33
37
|
# @!group Backend Configuration
|
|
34
38
|
# @param (see Backends::Serialized.configure)
|
|
35
39
|
# @option (see Backends::Serialized.configure)
|
|
@@ -72,5 +76,7 @@ Implements {Mobility::Backends::Serialized} backend for ActiveRecord models.
|
|
|
72
76
|
EOM
|
|
73
77
|
end
|
|
74
78
|
end
|
|
79
|
+
|
|
80
|
+
register_backend(:active_record_serialized, ActiveRecord::Serialized)
|
|
75
81
|
end
|
|
76
82
|
end
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# frozen-string-literal: true
|
|
2
2
|
require "mobility/backends/active_record"
|
|
3
3
|
require "mobility/backends/table"
|
|
4
|
-
require "mobility/active_record/model_translation"
|
|
5
4
|
|
|
6
5
|
module Mobility
|
|
7
6
|
module Backends
|
|
@@ -101,7 +100,7 @@ columns to that table.
|
|
|
101
100
|
# @option options [Symbol] subclass_name (:Translation) Name of subclass
|
|
102
101
|
# to append to model class to generate translation class
|
|
103
102
|
def configure(options)
|
|
104
|
-
table_name =
|
|
103
|
+
table_name = model_class.table_name
|
|
105
104
|
options[:table_name] ||= "#{table_name.singularize}_translations"
|
|
106
105
|
options[:foreign_key] ||= table_name.downcase.singularize.camelize.foreign_key
|
|
107
106
|
if (association_name = options[:association_name]).present?
|
|
@@ -116,10 +115,10 @@ columns to that table.
|
|
|
116
115
|
|
|
117
116
|
# @param [String] attr Attribute name
|
|
118
117
|
# @param [Symbol] _locale Locale
|
|
119
|
-
# @return [Mobility::Arel::Attribute] Arel node for column on translation table
|
|
118
|
+
# @return [Mobility::Plugins::Arel::Attribute] Arel node for column on translation table
|
|
120
119
|
def build_node(attr, locale)
|
|
121
120
|
aliased_table = model_class.const_get(subclass_name).arel_table.alias(table_alias(locale))
|
|
122
|
-
Arel::Attribute.new(aliased_table, attr, locale, self)
|
|
121
|
+
Plugins::Arel::Attribute.new(aliased_table, attr, locale, self)
|
|
123
122
|
end
|
|
124
123
|
|
|
125
124
|
# Joins translations using either INNER/OUTER join appropriate to the
|
|
@@ -153,7 +152,7 @@ columns to that table.
|
|
|
153
152
|
def already_joined?(relation, locale, join_type)
|
|
154
153
|
if join = get_join(relation, locale)
|
|
155
154
|
return true if (join_type == Visitor::OUTER_JOIN) || (Visitor::INNER_JOIN === join)
|
|
156
|
-
relation.joins_values
|
|
155
|
+
relation.joins_values -= [join]
|
|
157
156
|
end
|
|
158
157
|
false
|
|
159
158
|
end
|
|
@@ -190,7 +189,7 @@ columns to that table.
|
|
|
190
189
|
# we need an OUTER JOIN. In the second case, one attribute is matched
|
|
191
190
|
# against a non-nil value, so we can use an INNER JOIN.
|
|
192
191
|
#
|
|
193
|
-
class Visitor < Arel::Visitor
|
|
192
|
+
class Visitor < Plugins::Arel::Visitor
|
|
194
193
|
private
|
|
195
194
|
|
|
196
195
|
def visit_Arel_Nodes_Equality(object)
|
|
@@ -227,7 +226,7 @@ columns to that table.
|
|
|
227
226
|
end
|
|
228
227
|
end
|
|
229
228
|
|
|
230
|
-
def
|
|
229
|
+
def visit_Mobility_Plugins_Arel_Attribute(object)
|
|
231
230
|
# We compare table names here to ensure that attributes defined on
|
|
232
231
|
# different backends but the same table will correctly get an OUTER
|
|
233
232
|
# join when required. Use options[:table_name] here since we don't
|
|
@@ -245,7 +244,7 @@ columns to that table.
|
|
|
245
244
|
if self.const_defined?(subclass_name, false)
|
|
246
245
|
const_get(subclass_name, false)
|
|
247
246
|
else
|
|
248
|
-
const_set(subclass_name, Class.new(
|
|
247
|
+
const_set(subclass_name, Class.new(Translation))
|
|
249
248
|
end
|
|
250
249
|
|
|
251
250
|
translation_class.table_name = options[:table_name]
|
|
@@ -265,7 +264,7 @@ columns to that table.
|
|
|
265
264
|
touch: true
|
|
266
265
|
|
|
267
266
|
before_save do
|
|
268
|
-
required_attributes = self.class.
|
|
267
|
+
required_attributes = translation_class.attribute_names.select { |name| self.class.mobility_attribute?(name) }
|
|
269
268
|
send(association_name).destroy_empty_translations(required_attributes)
|
|
270
269
|
end
|
|
271
270
|
|
|
@@ -283,7 +282,7 @@ columns to that table.
|
|
|
283
282
|
|
|
284
283
|
# Returns translation for a given locale, or builds one if none is present.
|
|
285
284
|
# @param [Symbol] locale
|
|
286
|
-
def translation_for(locale,
|
|
285
|
+
def translation_for(locale, **)
|
|
287
286
|
translation = translations.in_locale(locale)
|
|
288
287
|
translation ||= translations.build(locale: locale)
|
|
289
288
|
translation
|
|
@@ -303,6 +302,14 @@ columns to that table.
|
|
|
303
302
|
destroy(empty_translations) if empty_translations.any?
|
|
304
303
|
end
|
|
305
304
|
end
|
|
305
|
+
|
|
306
|
+
# Subclassed dynamically to generate translation class.
|
|
307
|
+
class Translation < ::ActiveRecord::Base
|
|
308
|
+
self.abstract_class = true
|
|
309
|
+
validates :locale, presence: true
|
|
310
|
+
end
|
|
306
311
|
end
|
|
312
|
+
|
|
313
|
+
register_backend(:active_record_table, ActiveRecord::Table)
|
|
307
314
|
end
|
|
308
315
|
end
|
|
@@ -27,8 +27,6 @@ be ignored if set, since it would cause a conflict with column accessors.
|
|
|
27
27
|
|
|
28
28
|
=end
|
|
29
29
|
module Column
|
|
30
|
-
extend Backend::OrmDelegator
|
|
31
|
-
|
|
32
30
|
# Returns name of column where translated attribute is stored
|
|
33
31
|
# @param [Symbol] locale
|
|
34
32
|
# @return [String]
|
|
@@ -44,10 +42,6 @@ be ignored if set, since it would cause a conflict with column accessors.
|
|
|
44
42
|
normalized_locale = Mobility.normalize_locale(locale)
|
|
45
43
|
"#{attribute}_#{normalized_locale}".to_sym
|
|
46
44
|
end
|
|
47
|
-
|
|
48
|
-
def self.included(base)
|
|
49
|
-
base.extend Backend::OrmDelegator
|
|
50
|
-
end
|
|
51
45
|
end
|
|
52
46
|
end
|
|
53
47
|
end
|
|
@@ -19,7 +19,16 @@ stored).
|
|
|
19
19
|
|
|
20
20
|
=end
|
|
21
21
|
module Container
|
|
22
|
-
|
|
22
|
+
def self.included(backend_class)
|
|
23
|
+
backend_class.extend ClassMethods
|
|
24
|
+
backend_class.option_reader :column_name
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
def valid_keys
|
|
29
|
+
[:column_name]
|
|
30
|
+
end
|
|
31
|
+
end
|
|
23
32
|
end
|
|
24
33
|
end
|
|
25
34
|
end
|