mobility 1.0.0.beta2 → 1.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (52) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +49 -4
  5. data/Gemfile +5 -16
  6. data/Gemfile.lock +20 -1
  7. data/README.md +23 -28
  8. data/lib/mobility.rb +62 -8
  9. data/lib/mobility/backends/active_record.rb +1 -1
  10. data/lib/mobility/backends/active_record/column.rb +1 -1
  11. data/lib/mobility/backends/active_record/container.rb +4 -4
  12. data/lib/mobility/backends/active_record/hstore.rb +3 -3
  13. data/lib/mobility/backends/active_record/json.rb +3 -3
  14. data/lib/mobility/backends/active_record/jsonb.rb +3 -3
  15. data/lib/mobility/backends/active_record/key_value.rb +27 -11
  16. data/lib/mobility/backends/active_record/table.rb +11 -6
  17. data/lib/mobility/backends/sequel.rb +32 -0
  18. data/lib/mobility/backends/sequel/container.rb +5 -3
  19. data/lib/mobility/backends/sequel/key_value.rb +79 -12
  20. data/lib/mobility/backends/sequel/pg_hash.rb +6 -6
  21. data/lib/mobility/backends/sequel/table.rb +18 -8
  22. data/lib/mobility/backends/table.rb +11 -6
  23. data/lib/mobility/plugin.rb +2 -2
  24. data/lib/mobility/plugins/active_record.rb +3 -0
  25. data/lib/mobility/plugins/active_record/backend.rb +2 -0
  26. data/lib/mobility/plugins/active_record/query.rb +7 -7
  27. data/lib/mobility/plugins/active_record/uniqueness_validation.rb +4 -0
  28. data/lib/mobility/plugins/arel.rb +125 -0
  29. data/lib/mobility/plugins/arel/nodes.rb +15 -0
  30. data/lib/mobility/plugins/arel/nodes/pg_ops.rb +134 -0
  31. data/lib/mobility/plugins/sequel/dirty.rb +1 -1
  32. data/lib/mobility/version.rb +2 -2
  33. data/lib/rails/generators/mobility/templates/create_string_translations.rb +0 -1
  34. data/lib/rails/generators/mobility/templates/create_text_translations.rb +0 -1
  35. data/lib/rails/generators/mobility/templates/initializer.rb +9 -1
  36. metadata +14 -20
  37. metadata.gz.sig +0 -0
  38. data/lib/mobility/active_record/model_translation.rb +0 -14
  39. data/lib/mobility/active_record/string_translation.rb +0 -10
  40. data/lib/mobility/active_record/text_translation.rb +0 -10
  41. data/lib/mobility/active_record/translation.rb +0 -14
  42. data/lib/mobility/arel.rb +0 -49
  43. data/lib/mobility/arel/nodes.rb +0 -13
  44. data/lib/mobility/arel/nodes/pg_ops.rb +0 -132
  45. data/lib/mobility/arel/visitor.rb +0 -61
  46. data/lib/mobility/sequel/column_changes.rb +0 -28
  47. data/lib/mobility/sequel/hash_initializer.rb +0 -21
  48. data/lib/mobility/sequel/model_translation.rb +0 -20
  49. data/lib/mobility/sequel/sql.rb +0 -16
  50. data/lib/mobility/sequel/string_translation.rb +0 -10
  51. data/lib/mobility/sequel/text_translation.rb +0 -10
  52. data/lib/mobility/sequel/translation.rb +0 -53
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require "mobility/backends/active_record"
3
3
  require "mobility/backends/container"
4
- require "mobility/arel/nodes/pg_ops"
4
+ require "mobility/plugins/arel/nodes/pg_ops"
5
5
 
6
6
  module Mobility
7
7
  module Backends
@@ -49,15 +49,15 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
49
49
 
50
50
  # @param [String] attr Attribute name
51
51
  # @param [Symbol] locale Locale
52
- # @return [Mobility::Arel::Nodes::Json,Mobility::Arel::Nodes::Jsonb] Arel
52
+ # @return [Mobility::Plugins::Arel::Nodes::Json,Mobility::Arel::Nodes::Jsonb] Arel
53
53
  # node for attribute on json or jsonb column
54
54
  def build_node(attr, locale)
55
55
  column = model_class.arel_table[column_name]
56
56
  case column_type
57
57
  when :json
58
- Arel::Nodes::JsonContainer.new(column, build_quoted(locale), build_quoted(attr))
58
+ Plugins::Arel::Nodes::JsonContainer.new(column, build_quoted(locale), build_quoted(attr))
59
59
  when :jsonb
60
- Arel::Nodes::JsonbContainer.new(column, build_quoted(locale), build_quoted(attr))
60
+ Plugins::Arel::Nodes::JsonbContainer.new(column, build_quoted(locale), build_quoted(attr))
61
61
  end
62
62
  end
63
63
 
@@ -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
@@ -24,11 +24,11 @@ Implements the {Mobility::Backends::Hstore} backend for ActiveRecord models.
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
@@ -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,11 +32,11 @@ 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
@@ -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,11 +32,11 @@ 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
@@ -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] ||= Mobility::ActiveRecord.const_get("#{type.capitalize}Translation")
38
+ options[:class_name] ||= const_get("#{type.capitalize}Translation")
41
39
  end
42
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, attr.to_sym)
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 < ::Mobility::Arel::Visitor
120
+ class Visitor < Plugins::Arel::Visitor
123
121
  private
124
122
 
125
123
  def visit_Arel_Nodes_Equality(object)
@@ -141,7 +139,7 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
141
139
  transform_values { OUTER_JOIN }
142
140
  end
143
141
 
144
- def visit_Mobility_Arel_Attribute(object)
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, _options = {})
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,30 @@ 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
215
231
 
216
232
  register_backend(:active_record_key_value, ActiveRecord::KeyValue)
@@ -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
@@ -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
@@ -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 visit_Mobility_Arel_Attribute(object)
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(Mobility::ActiveRecord::ModelTranslation))
247
+ const_set(subclass_name, Class.new(Translation))
249
248
  end
250
249
 
251
250
  translation_class.table_name = options[:table_name]
@@ -303,6 +302,12 @@ 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
307
312
 
308
313
  register_backend(:active_record_table, ActiveRecord::Table)
@@ -30,6 +30,38 @@ module Mobility
30
30
  def prepare_dataset(dataset, _predicate, _locale)
31
31
  dataset
32
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
33
65
  end
34
66
  end
35
67
  end
@@ -57,9 +57,11 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
57
57
  end
58
58
  end
59
59
 
60
+ backend = self
61
+
60
62
  setup do |attributes, options|
61
63
  column_name = options[:column_name]
62
- before_validation = Module.new do
64
+ mod = Module.new do
63
65
  define_method :before_validation do
64
66
  self[column_name].each do |k, v|
65
67
  v.delete_if { |_locale, translation| Util.blank?(translation) }
@@ -68,8 +70,8 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
68
70
  super()
69
71
  end
70
72
  end
71
- include before_validation
72
- include Mobility::Sequel::HashInitializer.new(column_name)
73
+ include mod
74
+ backend.define_hash_initializer(mod, [column_name])
73
75
 
74
76
  plugin :defaults_setter
75
77
  attributes.each { |attribute| default_values[attribute.to_sym] = {} }
@@ -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,7 +29,7 @@ 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] ||= Mobility::Sequel.const_get("#{type.capitalize}Translation")
32
+ options[:class_name] ||= const_get("#{type.capitalize}Translation")
38
33
  end
39
34
  options[:table_alias_affix] = "#{model_class}_%s_#{options[:association_name]}"
40
35
  rescue NameError
@@ -43,7 +38,7 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
43
38
  # @!endgroup
44
39
 
45
40
  def build_op(attr, locale)
46
- ::Mobility::Sequel::SQL::QualifiedIdentifier.new(table_alias(attr, locale), :value, locale, self, attribute_name: attr)
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 ::Mobility::Sequel::SQL::QualifiedIdentifier
73
+ when QualifiedIdentifier
79
74
  visit_sql_identifier(predicate, locale)
80
75
  when ::Sequel::SQL::BooleanExpression
81
76
  visit_boolean(predicate, locale)
@@ -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]
@@ -159,13 +156,14 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
159
156
  include callback_methods
160
157
 
161
158
  include DestroyKeyValueTranslations
162
- include Mobility::Sequel::ColumnChanges.new(attributes)
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,75 @@ 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
205
272
 
206
273
  register_backend(:sequel_key_value, Sequel::KeyValue)