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
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Mobility
|
|
2
|
+
module Backends
|
|
3
|
+
=begin
|
|
4
|
+
|
|
5
|
+
Backend which stores translations in an in-memory hash.
|
|
6
|
+
|
|
7
|
+
=end
|
|
8
|
+
class Hash
|
|
9
|
+
include Backend
|
|
10
|
+
|
|
11
|
+
# @!group Backend Accessors
|
|
12
|
+
# @!macro backend_reader
|
|
13
|
+
# @return [Object]
|
|
14
|
+
def read(locale, _ = {})
|
|
15
|
+
translations[locale]
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# @!macro backend_writer
|
|
19
|
+
# @return [Object]
|
|
20
|
+
def write(locale, value, _ = {})
|
|
21
|
+
translations[locale] = value
|
|
22
|
+
end
|
|
23
|
+
# @!endgroup
|
|
24
|
+
|
|
25
|
+
# @!macro backend_iterator
|
|
26
|
+
def each_locale
|
|
27
|
+
translations.each { |l, _| yield l }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def translations
|
|
33
|
+
@translations ||= {}
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
register_backend(:hash, Hash)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -36,6 +36,10 @@ Defines read and write methods that access the value at a key with value
|
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
module ClassMethods
|
|
39
|
+
def valid_keys
|
|
40
|
+
[:column_prefix, :column_suffix]
|
|
41
|
+
end
|
|
42
|
+
|
|
39
43
|
def configure(options)
|
|
40
44
|
options[:column_affix] = "#{options[:column_prefix]}%s#{options[:column_suffix]}"
|
|
41
45
|
end
|
|
@@ -6,7 +6,7 @@ Stores translations as hash on Postgres jsonb column.
|
|
|
6
6
|
|
|
7
7
|
==Backend Options
|
|
8
8
|
|
|
9
|
-
===+
|
|
9
|
+
===+column_prefix+ and +column_suffix+
|
|
10
10
|
|
|
11
11
|
Prefix and suffix to add to attribute name to generate jsonb column name.
|
|
12
12
|
|
|
@@ -16,7 +16,6 @@ Prefix and suffix to add to attribute name to generate jsonb column name.
|
|
|
16
16
|
|
|
17
17
|
=end
|
|
18
18
|
module Jsonb
|
|
19
|
-
extend Backend::OrmDelegator
|
|
20
19
|
end
|
|
21
20
|
end
|
|
22
21
|
end
|
|
@@ -44,8 +44,6 @@ other backends on model (otherwise one will overwrite the other).
|
|
|
44
44
|
|
|
45
45
|
=end
|
|
46
46
|
module KeyValue
|
|
47
|
-
extend Backend::OrmDelegator
|
|
48
|
-
|
|
49
47
|
# @!method association_name
|
|
50
48
|
# Returns the name of the polymorphic association.
|
|
51
49
|
# @return [Symbol] Name of the association
|
|
@@ -56,13 +54,13 @@ other backends on model (otherwise one will overwrite the other).
|
|
|
56
54
|
|
|
57
55
|
# @!group Backend Accessors
|
|
58
56
|
# @!macro backend_reader
|
|
59
|
-
def read(locale, options
|
|
60
|
-
translation_for(locale, options).value
|
|
57
|
+
def read(locale, **options)
|
|
58
|
+
translation_for(locale, **options).value
|
|
61
59
|
end
|
|
62
60
|
|
|
63
61
|
# @!macro backend_writer
|
|
64
|
-
def write(locale, value, options
|
|
65
|
-
translation_for(locale, options).value = value
|
|
62
|
+
def write(locale, value, **options)
|
|
63
|
+
translation_for(locale, **options).value = value
|
|
66
64
|
end
|
|
67
65
|
# @!endgroup
|
|
68
66
|
|
|
@@ -85,9 +83,13 @@ other backends on model (otherwise one will overwrite the other).
|
|
|
85
83
|
end
|
|
86
84
|
|
|
87
85
|
module ClassMethods
|
|
86
|
+
def valid_keys
|
|
87
|
+
[:type, :association_name, :class_name]
|
|
88
|
+
end
|
|
89
|
+
|
|
88
90
|
# @!group Backend Configuration
|
|
89
91
|
# @option options [Symbol,String] type Column type to use
|
|
90
|
-
# @option options [Symbol]
|
|
92
|
+
# @option options [Symbol] association_name (:<type>_translations) Name
|
|
91
93
|
# of association method, defaults to +<type>_translations+
|
|
92
94
|
# @option options [Symbol] class_name Translation class, defaults to
|
|
93
95
|
# +Mobility::<ORM>::<type>Translation+
|
|
@@ -98,27 +100,13 @@ other backends on model (otherwise one will overwrite the other).
|
|
|
98
100
|
options[:association_name] &&= options[:association_name].to_sym
|
|
99
101
|
options[:class_name] &&= Util.constantize(options[:class_name])
|
|
100
102
|
if !(options[:type] || (options[:class_name] && options[:association_name]))
|
|
101
|
-
|
|
102
|
-
warn %{
|
|
103
|
-
WARNING: In previous versions, the Mobility KeyValue backend defaulted to a
|
|
104
|
-
text type column, but this behavior is now deprecated and will be removed in
|
|
105
|
-
the next release. Either explicitly specify the type by passing type: :text in
|
|
106
|
-
each translated model, or set a default option in your configuration.
|
|
107
|
-
}
|
|
108
|
-
options[:type] = :text
|
|
103
|
+
raise ArgumentError, "KeyValue backend requires an explicit type option, either text or string."
|
|
109
104
|
end
|
|
110
105
|
end
|
|
111
106
|
|
|
112
|
-
# Apply custom processing for plugin
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def apply_plugin(name)
|
|
116
|
-
if name == :cache
|
|
117
|
-
include self::Cache
|
|
118
|
-
true
|
|
119
|
-
else
|
|
120
|
-
super
|
|
121
|
-
end
|
|
107
|
+
# Apply custom processing for cache plugin
|
|
108
|
+
def include_cache
|
|
109
|
+
include self::Cache
|
|
122
110
|
end
|
|
123
111
|
|
|
124
112
|
def table_alias(attr, locale)
|
|
@@ -127,7 +115,24 @@ each translated model, or set a default option in your configuration.
|
|
|
127
115
|
end
|
|
128
116
|
|
|
129
117
|
module Cache
|
|
130
|
-
|
|
118
|
+
def translation_for(locale, **options)
|
|
119
|
+
return super(locale, options) if options.delete(:cache) == false
|
|
120
|
+
if cache.has_key?(locale)
|
|
121
|
+
cache[locale]
|
|
122
|
+
else
|
|
123
|
+
cache[locale] = super(locale, **options)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def clear_cache
|
|
128
|
+
@cache = {}
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def cache
|
|
134
|
+
@cache ||= {}
|
|
135
|
+
end
|
|
131
136
|
end
|
|
132
137
|
end
|
|
133
138
|
end
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "mobility/backend"
|
|
3
|
+
|
|
1
4
|
module Mobility
|
|
2
5
|
module Backends
|
|
3
6
|
module Sequel
|
|
4
7
|
def self.included(backend_class)
|
|
5
|
-
backend_class.include
|
|
6
|
-
backend_class.extend
|
|
8
|
+
backend_class.include Backend
|
|
9
|
+
backend_class.extend ClassMethods
|
|
7
10
|
end
|
|
8
11
|
|
|
9
12
|
module ClassMethods
|
|
@@ -27,6 +30,38 @@ module Mobility
|
|
|
27
30
|
def prepare_dataset(dataset, _predicate, _locale)
|
|
28
31
|
dataset
|
|
29
32
|
end
|
|
33
|
+
|
|
34
|
+
# Forces Sequel to notice changes when Mobility setter method is
|
|
35
|
+
# called.
|
|
36
|
+
# TODO: Find a better way to do this.
|
|
37
|
+
def define_column_changes(mod, attributes, column_affix: "%s")
|
|
38
|
+
mod.class_eval do
|
|
39
|
+
attributes.each do |attribute|
|
|
40
|
+
define_method "#{attribute}=" do |value, **options|
|
|
41
|
+
if !options[:super] && send(attribute) != value
|
|
42
|
+
locale = options[:locale] || Mobility.locale
|
|
43
|
+
column = (column_affix % attribute).to_sym
|
|
44
|
+
attribute_with_locale = :"#{attribute}_#{Mobility.normalize_locale(locale)}"
|
|
45
|
+
@changed_columns = changed_columns | [column, attribute.to_sym, attribute_with_locale]
|
|
46
|
+
end
|
|
47
|
+
super(value, **options)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Initialize column value(s) by default to a hash.
|
|
54
|
+
# TODO: Find a better way to do this.
|
|
55
|
+
def define_hash_initializer(mod, columns)
|
|
56
|
+
mod.class_eval do
|
|
57
|
+
class_eval <<-EOM, __FILE__, __LINE__ + 1
|
|
58
|
+
def initialize_set(values)
|
|
59
|
+
#{columns.map { |c| "self[:#{c}] = {}" }.join(';')}
|
|
60
|
+
super
|
|
61
|
+
end
|
|
62
|
+
EOM
|
|
63
|
+
end
|
|
64
|
+
end
|
|
30
65
|
end
|
|
31
66
|
end
|
|
32
67
|
end
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
-
require "mobility/backends/sequel
|
|
2
|
+
require "mobility/backends/sequel"
|
|
3
3
|
require "mobility/backends/sequel/jsonb"
|
|
4
|
+
require "mobility/backends/container"
|
|
4
5
|
|
|
5
6
|
module Mobility
|
|
6
7
|
module Backends
|
|
@@ -11,10 +12,7 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
|
|
|
11
12
|
=end
|
|
12
13
|
class Sequel::Container
|
|
13
14
|
include Sequel
|
|
14
|
-
|
|
15
|
-
# @!method column_name
|
|
16
|
-
# @return [Symbol] (:translations) Name of translations column
|
|
17
|
-
option_reader :column_name
|
|
15
|
+
include Container
|
|
18
16
|
|
|
19
17
|
# @!group Backend Accessors
|
|
20
18
|
#
|
|
@@ -44,7 +42,7 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
|
|
|
44
42
|
def self.configure(options)
|
|
45
43
|
options[:column_name] ||= :translations
|
|
46
44
|
options[:column_name] = options[:column_name].to_sym
|
|
47
|
-
column_name, db_schema = options[:column_name],
|
|
45
|
+
column_name, db_schema = options[:column_name], model_class.db_schema
|
|
48
46
|
options[:column_type] = db_schema[column_name] && (db_schema[column_name][:db_type]).to_sym
|
|
49
47
|
unless %i[json jsonb].include?(options[:column_type])
|
|
50
48
|
raise InvalidColumnType, "#{options[:column_name]} must be a column of type json or jsonb"
|
|
@@ -59,9 +57,11 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
|
|
|
59
57
|
end
|
|
60
58
|
end
|
|
61
59
|
|
|
60
|
+
backend = self
|
|
61
|
+
|
|
62
62
|
setup do |attributes, options|
|
|
63
63
|
column_name = options[:column_name]
|
|
64
|
-
|
|
64
|
+
mod = Module.new do
|
|
65
65
|
define_method :before_validation do
|
|
66
66
|
self[column_name].each do |k, v|
|
|
67
67
|
v.delete_if { |_locale, translation| Util.blank?(translation) }
|
|
@@ -70,8 +70,8 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
|
|
|
70
70
|
super()
|
|
71
71
|
end
|
|
72
72
|
end
|
|
73
|
-
include
|
|
74
|
-
|
|
73
|
+
include mod
|
|
74
|
+
backend.define_hash_initializer(mod, [column_name])
|
|
75
75
|
|
|
76
76
|
plugin :defaults_setter
|
|
77
77
|
attributes.each { |attribute| default_values[attribute.to_sym] = {} }
|
|
@@ -114,5 +114,7 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
|
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
end
|
|
117
|
+
|
|
118
|
+
register_backend(:sequel_container, Sequel::Container)
|
|
117
119
|
end
|
|
118
120
|
end
|
|
@@ -20,7 +20,7 @@ Implements the {Mobility::Backends::Hstore} backend for Sequel models.
|
|
|
20
20
|
# @!group Backend Accessors
|
|
21
21
|
# @!macro backend_writer
|
|
22
22
|
def write(locale, value, options = {})
|
|
23
|
-
super(locale, value && value.to_s, options)
|
|
23
|
+
super(locale, value && value.to_s, **options)
|
|
24
24
|
end
|
|
25
25
|
# @!endgroup
|
|
26
26
|
|
|
@@ -35,5 +35,7 @@ Implements the {Mobility::Backends::Hstore} backend for Sequel models.
|
|
|
35
35
|
class HStoreOp < ::Sequel::Postgres::HStoreOp; end
|
|
36
36
|
end
|
|
37
37
|
end
|
|
38
|
+
|
|
39
|
+
register_backend(:sequel_hstore, Sequel::Hstore)
|
|
38
40
|
end
|
|
39
41
|
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'mobility/backends/sequel/pg_hash'
|
|
2
3
|
|
|
3
4
|
Sequel.extension :pg_json, :pg_json_ops
|
|
@@ -42,5 +43,7 @@ Implements the {Mobility::Backends::Json} backend for Sequel models.
|
|
|
42
43
|
class JSONOp < ::Sequel::Postgres::JSONOp; end
|
|
43
44
|
end
|
|
44
45
|
end
|
|
46
|
+
|
|
47
|
+
register_backend(:sequel_json, Sequel::Json)
|
|
45
48
|
end
|
|
46
49
|
end
|
|
@@ -55,7 +55,7 @@ Implements the {Mobility::Backends::Jsonb} backend for Sequel models.
|
|
|
55
55
|
|
|
56
56
|
def =~(other)
|
|
57
57
|
case other
|
|
58
|
-
when Integer, Hash
|
|
58
|
+
when Integer, ::Hash
|
|
59
59
|
to_dash_arrow =~ other.to_json
|
|
60
60
|
when NilClass
|
|
61
61
|
~to_question
|
|
@@ -66,5 +66,7 @@ Implements the {Mobility::Backends::Jsonb} backend for Sequel models.
|
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
|
+
|
|
70
|
+
register_backend(:sequel_jsonb, Sequel::Jsonb)
|
|
69
71
|
end
|
|
70
72
|
end
|
|
@@ -2,11 +2,6 @@
|
|
|
2
2
|
require "mobility/util"
|
|
3
3
|
require "mobility/backends/sequel"
|
|
4
4
|
require "mobility/backends/key_value"
|
|
5
|
-
require "mobility/sequel/column_changes"
|
|
6
|
-
require "mobility/sequel/hash_initializer"
|
|
7
|
-
require "mobility/sequel/string_translation"
|
|
8
|
-
require "mobility/sequel/text_translation"
|
|
9
|
-
require "mobility/sequel/sql"
|
|
10
5
|
|
|
11
6
|
module Mobility
|
|
12
7
|
module Backends
|
|
@@ -34,16 +29,16 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
34
29
|
super
|
|
35
30
|
if type = options[:type]
|
|
36
31
|
options[:association_name] ||= :"#{options[:type]}_translations"
|
|
37
|
-
options[:class_name] ||=
|
|
32
|
+
options[:class_name] ||= const_get("#{type.capitalize}Translation")
|
|
38
33
|
end
|
|
39
|
-
options[:table_alias_affix] = "#{
|
|
34
|
+
options[:table_alias_affix] = "#{model_class}_%s_#{options[:association_name]}"
|
|
40
35
|
rescue NameError
|
|
41
36
|
raise ArgumentError, "You must define a Mobility::Sequel::#{type.capitalize}Translation class."
|
|
42
37
|
end
|
|
43
38
|
# @!endgroup
|
|
44
39
|
|
|
45
40
|
def build_op(attr, locale)
|
|
46
|
-
|
|
41
|
+
QualifiedIdentifier.new(table_alias(attr, locale), :value, locale, self, attr)
|
|
47
42
|
end
|
|
48
43
|
|
|
49
44
|
# @param [Sequel::Dataset] dataset Dataset to prepare
|
|
@@ -75,7 +70,7 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
75
70
|
case predicate
|
|
76
71
|
when Array
|
|
77
72
|
visit_collection(predicate, locale)
|
|
78
|
-
when
|
|
73
|
+
when QualifiedIdentifier
|
|
79
74
|
visit_sql_identifier(predicate, locale)
|
|
80
75
|
when ::Sequel::SQL::BooleanExpression
|
|
81
76
|
visit_boolean(predicate, locale)
|
|
@@ -93,7 +88,7 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
93
88
|
join_type = nils.empty? ? :inner : :left_outer
|
|
94
89
|
# TODO: simplify to hash.transform_values { join_type } when
|
|
95
90
|
# support for Ruby 2.3 is deprecated
|
|
96
|
-
Hash[hash.keys.map { |key| [key, join_type] }]
|
|
91
|
+
::Hash[hash.keys.map { |key| [key, join_type] }]
|
|
97
92
|
else
|
|
98
93
|
{}
|
|
99
94
|
end
|
|
@@ -101,13 +96,13 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
101
96
|
hash = visit(boolean.args, locale)
|
|
102
97
|
# TODO: simplify to hash.transform_values { :inner } when
|
|
103
98
|
# support for Ruby 2.3 is deprecated
|
|
104
|
-
Hash[hash.keys.map { |key| [key, :inner] }]
|
|
99
|
+
::Hash[hash.keys.map { |key| [key, :inner] }]
|
|
105
100
|
elsif boolean.op == :OR
|
|
106
101
|
hash = boolean.args.map { |op| visit(op, locale) }.
|
|
107
|
-
compact.inject(
|
|
102
|
+
compact.inject(:merge)
|
|
108
103
|
# TODO: simplify to hash.transform_values { :left_outer } when
|
|
109
104
|
# support for Ruby 2.3 is deprecated
|
|
110
|
-
Hash[hash.keys.map { |key| [key, :left_outer] }]
|
|
105
|
+
::Hash[hash.keys.map { |key| [key, :left_outer] }]
|
|
111
106
|
else
|
|
112
107
|
visit(boolean.args, locale)
|
|
113
108
|
end
|
|
@@ -128,6 +123,8 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
128
123
|
end
|
|
129
124
|
end
|
|
130
125
|
|
|
126
|
+
backend = self
|
|
127
|
+
|
|
131
128
|
setup do |attributes, options|
|
|
132
129
|
association_name = options[:association_name]
|
|
133
130
|
translations_class = options[:class_name]
|
|
@@ -153,19 +150,20 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
153
150
|
end
|
|
154
151
|
define_method :after_save do
|
|
155
152
|
super()
|
|
156
|
-
attributes.each { |attribute|
|
|
153
|
+
attributes.each { |attribute| mobility_backends[attribute].save_translations }
|
|
157
154
|
end
|
|
158
155
|
end
|
|
159
156
|
include callback_methods
|
|
160
157
|
|
|
161
158
|
include DestroyKeyValueTranslations
|
|
162
|
-
include
|
|
159
|
+
include(mod = Module.new)
|
|
160
|
+
backend.define_column_changes(mod, attributes)
|
|
163
161
|
end
|
|
164
162
|
|
|
165
163
|
# Returns translation for a given locale, or initializes one if none is present.
|
|
166
164
|
# @param [Symbol] locale
|
|
167
|
-
# @return [Mobility::Sequel::TextTranslation,Mobility::Sequel::StringTranslation]
|
|
168
|
-
def translation_for(locale,
|
|
165
|
+
# @return [Mobility::Backends::Sequel::KeyValue::TextTranslation,Mobility::Backends::Sequel::KeyValue::StringTranslation]
|
|
166
|
+
def translation_for(locale, **)
|
|
169
167
|
translation = model.send(association_name).find { |t| t.key == attribute && t.locale == locale.to_s }
|
|
170
168
|
translation ||= class_name.new(locale: locale, key: attribute)
|
|
171
169
|
translation
|
|
@@ -184,7 +182,7 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
184
182
|
def after_destroy
|
|
185
183
|
super
|
|
186
184
|
[:string, :text].freeze.each do |type|
|
|
187
|
-
Mobility::Sequel.const_get("#{type.capitalize}Translation").
|
|
185
|
+
Mobility::Backends::Sequel::KeyValue.const_get("#{type.capitalize}Translation").
|
|
188
186
|
where(translatable_id: id, translatable_type: self.class.name).destroy
|
|
189
187
|
end
|
|
190
188
|
end
|
|
@@ -201,6 +199,77 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
|
|
|
201
199
|
(model.send(association_name) + cache.values).uniq
|
|
202
200
|
end
|
|
203
201
|
end
|
|
202
|
+
|
|
203
|
+
class QualifiedIdentifier < ::Sequel::SQL::QualifiedIdentifier
|
|
204
|
+
attr_reader :backend_class, :locale, :attribute_name
|
|
205
|
+
|
|
206
|
+
def initialize(table, column, locale, backend_class, attribute_name)
|
|
207
|
+
@backend_class = backend_class
|
|
208
|
+
@locale = locale
|
|
209
|
+
@attribute_name = attribute_name || column
|
|
210
|
+
super(table, column)
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
module Translation
|
|
215
|
+
def self.included(base)
|
|
216
|
+
base.class_eval do
|
|
217
|
+
plugin :validation_helpers
|
|
218
|
+
|
|
219
|
+
# Paraphased from sequel_polymorphic gem
|
|
220
|
+
#
|
|
221
|
+
model = underscore(self.to_s)
|
|
222
|
+
plural_model = pluralize(model)
|
|
223
|
+
many_to_one :translatable,
|
|
224
|
+
reciprocal: plural_model.to_sym,
|
|
225
|
+
reciprocal_type: :many_to_one,
|
|
226
|
+
setter: (proc do |able_instance|
|
|
227
|
+
self[:translatable_id] = (able_instance.pk if able_instance)
|
|
228
|
+
self[:translatable_type] = (able_instance.class.name if able_instance)
|
|
229
|
+
end),
|
|
230
|
+
dataset: (proc do
|
|
231
|
+
translatable_type = send :translatable_type
|
|
232
|
+
translatable_id = send :translatable_id
|
|
233
|
+
return if translatable_type.nil? || translatable_id.nil?
|
|
234
|
+
klass = self.class.send(:constantize, translatable_type)
|
|
235
|
+
klass.where(klass.primary_key => translatable_id)
|
|
236
|
+
end),
|
|
237
|
+
eager_loader: (proc do |eo|
|
|
238
|
+
id_map = {}
|
|
239
|
+
eo[:rows].each do |model|
|
|
240
|
+
model_able_type = model.send :translatable_type
|
|
241
|
+
model_able_id = model.send :translatable_id
|
|
242
|
+
model.associations[:translatable] = nil
|
|
243
|
+
((id_map[model_able_type] ||= {})[model_able_id] ||= []) << model if !model_able_type.nil? && !model_able_id.nil?
|
|
244
|
+
end
|
|
245
|
+
id_map.each do |klass_name, id_map|
|
|
246
|
+
klass = constantize(camelize(klass_name))
|
|
247
|
+
klass.where(klass.primary_key=>id_map.keys).all do |related_obj|
|
|
248
|
+
id_map[related_obj.pk].each do |model|
|
|
249
|
+
model.associations[:translatable] = related_obj
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
end
|
|
253
|
+
end)
|
|
254
|
+
|
|
255
|
+
def validate
|
|
256
|
+
super
|
|
257
|
+
validates_presence [:locale, :key, :translatable_id, :translatable_type]
|
|
258
|
+
validates_unique [:locale, :key, :translatable_id, :translatable_type]
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
|
|
264
|
+
class TextTranslation < ::Sequel::Model(:mobility_text_translations)
|
|
265
|
+
include Translation
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
class StringTranslation < ::Sequel::Model(:mobility_string_translations)
|
|
269
|
+
include Translation
|
|
270
|
+
end
|
|
204
271
|
end
|
|
272
|
+
|
|
273
|
+
register_backend(:sequel_key_value, Sequel::KeyValue)
|
|
205
274
|
end
|
|
206
275
|
end
|