mobility 0.1.20 → 0.2.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.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +2 -0
  4. data/CHANGELOG.md +17 -0
  5. data/CONTRIBUTING.md +55 -0
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +2 -56
  8. data/README.md +64 -15
  9. data/Rakefile +17 -17
  10. data/lib/mobility.rb +43 -40
  11. data/lib/mobility/active_model.rb +0 -1
  12. data/lib/mobility/active_model/backend_resetter.rb +1 -1
  13. data/lib/mobility/active_record.rb +8 -15
  14. data/lib/mobility/active_record/backend_resetter.rb +2 -0
  15. data/lib/mobility/active_record/model_translation.rb +1 -1
  16. data/lib/mobility/active_record/string_translation.rb +2 -0
  17. data/lib/mobility/active_record/text_translation.rb +2 -0
  18. data/lib/mobility/attributes.rb +74 -71
  19. data/lib/mobility/backend.rb +64 -25
  20. data/lib/mobility/backend/orm_delegator.rb +17 -7
  21. data/lib/mobility/backend/stringify_locale.rb +18 -0
  22. data/lib/mobility/backend_resetter.rb +8 -5
  23. data/lib/mobility/backends.rb +4 -0
  24. data/lib/mobility/backends/active_record.rb +20 -0
  25. data/lib/mobility/{backend → backends}/active_record/column.rb +25 -13
  26. data/lib/mobility/{backend → backends}/active_record/column/query_methods.rb +5 -3
  27. data/lib/mobility/backends/active_record/hstore.rb +29 -0
  28. data/lib/mobility/{backend → backends}/active_record/hstore/query_methods.rb +2 -2
  29. data/lib/mobility/{backend → backends}/active_record/jsonb.rb +6 -6
  30. data/lib/mobility/{backend → backends}/active_record/jsonb/query_methods.rb +4 -2
  31. data/lib/mobility/{backend → backends}/active_record/key_value.rb +10 -44
  32. data/lib/mobility/{backend → backends}/active_record/key_value/query_methods.rb +4 -2
  33. data/lib/mobility/{backend/active_record/hash_valued.rb → backends/active_record/pg_hash.rb} +13 -21
  34. data/lib/mobility/{backend → backends}/active_record/query_methods.rb +2 -2
  35. data/lib/mobility/{backend → backends}/active_record/serialized.rb +12 -28
  36. data/lib/mobility/{backend → backends}/active_record/serialized/query_methods.rb +5 -8
  37. data/lib/mobility/{backend → backends}/active_record/table.rb +11 -60
  38. data/lib/mobility/{backend → backends}/active_record/table/query_methods.rb +5 -3
  39. data/lib/mobility/{backend → backends}/column.rb +8 -4
  40. data/lib/mobility/backends/hash_valued.rb +29 -0
  41. data/lib/mobility/{backend → backends}/hstore.rb +4 -4
  42. data/lib/mobility/{backend → backends}/jsonb.rb +4 -4
  43. data/lib/mobility/backends/key_value.rb +111 -0
  44. data/lib/mobility/{backend → backends}/null.rb +4 -4
  45. data/lib/mobility/backends/sequel.rb +20 -0
  46. data/lib/mobility/backends/sequel/column.rb +52 -0
  47. data/lib/mobility/{backend → backends}/sequel/column/query_methods.rb +5 -3
  48. data/lib/mobility/backends/sequel/hstore.rb +29 -0
  49. data/lib/mobility/{backend → backends}/sequel/hstore/query_methods.rb +4 -3
  50. data/lib/mobility/{backend → backends}/sequel/jsonb.rb +6 -6
  51. data/lib/mobility/{backend → backends}/sequel/jsonb/query_methods.rb +4 -3
  52. data/lib/mobility/{backend → backends}/sequel/key_value.rb +28 -39
  53. data/lib/mobility/{backend → backends}/sequel/key_value/query_methods.rb +4 -5
  54. data/lib/mobility/backends/sequel/pg_hash.rb +46 -0
  55. data/lib/mobility/{backend → backends}/sequel/postgres_query_methods.rb +1 -2
  56. data/lib/mobility/{backend → backends}/sequel/query_methods.rb +6 -4
  57. data/lib/mobility/{backend → backends}/sequel/serialized.rb +17 -38
  58. data/lib/mobility/backends/sequel/serialized/query_methods.rb +17 -0
  59. data/lib/mobility/{backend → backends}/sequel/table.rb +29 -60
  60. data/lib/mobility/{backend → backends}/sequel/table/query_methods.rb +5 -3
  61. data/lib/mobility/{backend → backends}/serialized.rb +27 -5
  62. data/lib/mobility/{backend → backends}/table.rb +69 -29
  63. data/lib/mobility/configuration.rb +40 -0
  64. data/lib/mobility/{orm.rb → loaded.rb} +0 -0
  65. data/lib/mobility/plugins.rb +35 -0
  66. data/lib/mobility/plugins/active_model.rb +6 -0
  67. data/lib/mobility/plugins/active_model/dirty.rb +81 -0
  68. data/lib/mobility/plugins/active_record.rb +6 -0
  69. data/lib/mobility/plugins/active_record/dirty.rb +59 -0
  70. data/lib/mobility/plugins/cache.rb +54 -0
  71. data/lib/mobility/plugins/cache/translation_cacher.rb +40 -0
  72. data/lib/mobility/plugins/default.rb +73 -0
  73. data/lib/mobility/plugins/dirty.rb +61 -0
  74. data/lib/mobility/{backend → plugins}/fallbacks.rb +36 -31
  75. data/lib/mobility/plugins/fallthrough_accessors.rb +66 -0
  76. data/lib/mobility/plugins/locale_accessors.rb +84 -0
  77. data/lib/mobility/{backend → plugins}/presence.rb +15 -6
  78. data/lib/mobility/plugins/sequel.rb +6 -0
  79. data/lib/mobility/plugins/sequel/dirty.rb +59 -0
  80. data/lib/mobility/sequel.rb +5 -14
  81. data/lib/mobility/sequel/backend_resetter.rb +4 -6
  82. data/lib/mobility/sequel/column_changes.rb +4 -4
  83. data/lib/mobility/sequel/model_translation.rb +1 -1
  84. data/lib/mobility/sequel/string_translation.rb +2 -0
  85. data/lib/mobility/sequel/text_translation.rb +2 -0
  86. data/lib/mobility/translates.rb +1 -5
  87. data/lib/mobility/util.rb +126 -0
  88. data/lib/mobility/version.rb +1 -1
  89. data/lib/mobility/wrapper.rb +1 -1
  90. data/lib/rails/generators/mobility/translations_generator.rb +7 -3
  91. metadata +85 -55
  92. metadata.gz.sig +0 -0
  93. data/lib/mobility/backend/active_model.rb +0 -7
  94. data/lib/mobility/backend/active_model/dirty.rb +0 -95
  95. data/lib/mobility/backend/active_record.rb +0 -29
  96. data/lib/mobility/backend/active_record/dirty.rb +0 -54
  97. data/lib/mobility/backend/active_record/hstore.rb +0 -29
  98. data/lib/mobility/backend/cache.rb +0 -117
  99. data/lib/mobility/backend/dirty.rb +0 -38
  100. data/lib/mobility/backend/key_value.rb +0 -85
  101. data/lib/mobility/backend/sequel.rb +0 -29
  102. data/lib/mobility/backend/sequel/column.rb +0 -39
  103. data/lib/mobility/backend/sequel/dirty.rb +0 -57
  104. data/lib/mobility/backend/sequel/hash_valued.rb +0 -51
  105. data/lib/mobility/backend/sequel/hstore.rb +0 -29
  106. data/lib/mobility/backend/sequel/serialized/query_methods.rb +0 -20
  107. data/lib/mobility/core_ext/object.rb +0 -30
  108. data/lib/mobility/core_ext/string.rb +0 -16
  109. data/lib/mobility/fallthrough_accessors.rb +0 -57
  110. data/lib/mobility/locale_accessors.rb +0 -55
@@ -1,10 +1,14 @@
1
1
  # frozen-string-literal: true
2
+ require "mobility/backends/active_record"
3
+ require "mobility/backends/key_value"
4
+ require "mobility/active_record/string_translation"
5
+ require "mobility/active_record/text_translation"
2
6
 
3
7
  module Mobility
4
- module Backend
8
+ module Backends
5
9
  =begin
6
10
 
7
- Implements the {Mobility::Backend::KeyValue} backend for ActiveRecord models.
11
+ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
8
12
 
9
13
  @example
10
14
  class Post < ActiveRecord::Base
@@ -24,33 +28,11 @@ Implements the {Mobility::Backend::KeyValue} backend for ActiveRecord models.
24
28
  include ActiveRecord
25
29
  include KeyValue
26
30
 
27
- require 'mobility/backend/active_record/key_value/query_methods'
28
-
29
- # @return [Symbol] Name of the association
30
- attr_reader :association_name
31
-
32
- # @!macro backend_constructor
33
- # @option options [Symbol] association_name Name of association
34
- def initialize(model, attribute, **options)
35
- super
36
- @association_name = options[:association_name]
37
- end
38
-
39
- # @!group Backend Accessors
40
- # @!macro backend_reader
41
- def read(locale, **_)
42
- translation_for(locale).value
43
- end
44
-
45
- # @!macro backend_reader
46
- def write(locale, value, **_)
47
- translation_for(locale).tap { |t| t.value = value }.value
48
- end
49
- # @!endgroup
31
+ require 'mobility/backends/active_record/key_value/query_methods'
50
32
 
51
33
  # @!group Backend Configuration
52
34
  # @option options [Symbol] type (:text) Column type to use
53
- # @option options [Symbol] association_name (:mobility_text_translations) Name of association method
35
+ # @option options [Symbol] association_name (:text_translations) Name of association method
54
36
  # @option options [String,Class] class_name ({Mobility::ActiveRecord::TextTranslation}) Translation class
55
37
  # @raise [ArgumentError] if type is not either :text or :string
56
38
  def self.configure(options)
@@ -58,7 +40,7 @@ Implements the {Mobility::Backend::KeyValue} backend for ActiveRecord models.
58
40
  type = options[:type]
59
41
  options[:class_name] ||= Mobility::ActiveRecord.const_get("#{type.capitalize}Translation".freeze)
60
42
  options[:class_name] = options[:class_name].constantize if options[:class_name].is_a?(String)
61
- options[:association_name] ||= options[:class_name].table_name.to_sym
43
+ options[:association_name] ||= :"#{options[:type]}_translations"
62
44
  %i[type association_name].each { |key| options[key] = options[key].to_sym }
63
45
  end
64
46
  # @!endgroup
@@ -101,30 +83,14 @@ Implements the {Mobility::Backend::KeyValue} backend for ActiveRecord models.
101
83
 
102
84
  setup_query_methods(QueryMethods)
103
85
 
104
- # @!group Cache Methods
105
- # @return [KeyValue::TranslationsCache]
106
- def new_cache
107
- KeyValue::TranslationsCache.new(self)
108
- end
109
-
110
- # @return [Boolean]
111
- def write_to_cache?
112
- true
113
- end
114
- # @!endgroup
115
-
116
86
  # Returns translation for a given locale, or builds one if none is present.
117
87
  # @param [Symbol] locale
118
88
  # @return [Mobility::ActiveRecord::TextTranslation,Mobility::ActiveRecord::StringTranslation]
119
- def translation_for(locale)
89
+ def translation_for(locale, _options = {})
120
90
  translation = translations.find { |t| t.key == attribute && t.locale == locale.to_s }
121
91
  translation ||= translations.build(locale: locale, key: attribute)
122
92
  translation
123
93
  end
124
-
125
- def translations
126
- model.send(association_name)
127
- end
128
94
  end
129
95
  end
130
96
  end
@@ -1,7 +1,9 @@
1
+ require "mobility/backends/active_record/query_methods"
2
+
1
3
  module Mobility
2
- module Backend
4
+ module Backends
3
5
  class ActiveRecord::KeyValue::QueryMethods < ActiveRecord::QueryMethods
4
- def initialize(attributes, association_name: nil, class_name: nil, **_)
6
+ def initialize(attributes, association_name: nil, class_name: nil, **)
5
7
  super
6
8
  @association_name = association_name
7
9
 
@@ -1,43 +1,35 @@
1
+ require "mobility/backends/active_record"
2
+ require "mobility/backends/hash_valued"
3
+
1
4
  module Mobility
2
- module Backend
5
+ module Backends
3
6
  =begin
4
7
 
5
- Internal class used by ActiveRecord backends that store values as a hash.
8
+ Internal class used by ActiveRecord backends backed by a Postgres data type
9
+ (hstore, jsonb).
6
10
 
7
11
  =end
8
- class ActiveRecord::HashValued
12
+ class ActiveRecord::PgHash
9
13
  include ActiveRecord
14
+ include HashValued
10
15
 
11
- # @!group Backend Accessors
12
- #
13
- # @!macro backend_reader
14
- def read(locale, **_)
15
- translations[locale]
16
- end
17
-
18
- # @!macro backend_writer
19
- def write(locale, value, **_)
20
- translations[locale] = value
16
+ # @!macro backend_iterator
17
+ def each_locale
18
+ super { |l| yield l.to_sym }
21
19
  end
22
- # @!endgroup
23
20
 
24
21
  def translations
25
22
  model.read_attribute(attribute)
26
23
  end
27
- alias_method :new_cache, :translations
28
-
29
- def write_to_cache?
30
- true
31
- end
32
24
 
33
- setup do |attributes, options|
25
+ setup do |attributes|
34
26
  attributes.each { |attribute| store attribute, coder: Coder }
35
27
  end
36
28
 
37
29
  class Coder
38
30
  def self.dump(obj)
39
31
  if obj.is_a? Hash
40
- obj = obj.inject({}) do |translations, (locale, value)|
32
+ obj.inject({}) do |translations, (locale, value)|
41
33
  translations[locale] = value if value.present?
42
34
  translations
43
35
  end
@@ -1,5 +1,5 @@
1
1
  module Mobility
2
- module Backend
2
+ module Backends
3
3
  module ActiveRecord
4
4
  =begin
5
5
 
@@ -9,7 +9,7 @@ models. For details see backend-specific subclasses.
9
9
  =end
10
10
  class QueryMethods < Module
11
11
  # @param [Array<String>] attributes Translated attributes
12
- def initialize(attributes, **_)
12
+ def initialize(attributes, _)
13
13
  @attributes = attributes
14
14
  @attributes_extractor = lambda do |opts|
15
15
  opts.is_a?(Hash) && (opts.keys.map(&:to_s) & attributes).presence
@@ -1,8 +1,12 @@
1
+ require "mobility/backends/active_record"
2
+ require "mobility/backends/hash_valued"
3
+ require "mobility/backends/serialized"
4
+
1
5
  module Mobility
2
- module Backend
6
+ module Backends
3
7
  =begin
4
8
 
5
- Implements {Mobility::Backend::Serialized} backend for ActiveRecord models.
9
+ Implements {Mobility::Backends::Serialized} backend for ActiveRecord models.
6
10
 
7
11
  @example Define attribute with serialized backend
8
12
  class Post < ActiveRecord::Base
@@ -22,29 +26,16 @@ Implements {Mobility::Backend::Serialized} backend for ActiveRecord models.
22
26
  =end
23
27
  class ActiveRecord::Serialized
24
28
  include ActiveRecord
29
+ include HashValued
25
30
 
26
- require 'mobility/backend/active_record/serialized/query_methods'
27
-
28
- # @!group Backend Accessors
29
- #
30
- # @!macro backend_reader
31
- def read(locale, **_)
32
- translations[locale]
33
- end
34
-
35
- # @!macro backend_reader
36
- def write(locale, value, **_)
37
- translations[locale] = value
38
- end
39
- # @!endgroup
31
+ require 'mobility/backends/active_record/serialized/query_methods'
40
32
 
41
33
  # @!group Backend Configuration
42
- # @option options [Symbol] format (:yaml) Serialization format
43
- # @raise [ArgumentError] if a format other than +:yaml+ or +:json+ is passed in
34
+ # @param (see Backends::Serialized.configure)
35
+ # @option (see Backends::Serialized.configure)
36
+ # @raise (see Backends::Serialized.configure)
44
37
  def self.configure(options)
45
- options[:format] ||= :yaml
46
- options[:format] = options[:format].downcase.to_sym
47
- raise ArgumentError, "Serialized backend only supports yaml or json formats." unless [:yaml, :json].include?(options[:format])
38
+ Serialized.configure(options)
48
39
  end
49
40
  # @!endgroup
50
41
 
@@ -61,13 +52,6 @@ Implements {Mobility::Backend::Serialized} backend for ActiveRecord models.
61
52
  def translations
62
53
  model.read_attribute(attribute)
63
54
  end
64
- alias_method :new_cache, :translations
65
-
66
- # @return [Boolean]
67
- def write_to_cache?
68
- true
69
- end
70
- # @!endgroup
71
55
 
72
56
  %w[yaml json].each do |format|
73
57
  class_eval <<-EOM, __FILE__, __LINE__ + 1
@@ -1,15 +1,12 @@
1
+ require "mobility/backends/active_record/query_methods"
2
+
1
3
  module Mobility
2
- module Backend
4
+ module Backends
3
5
  class ActiveRecord::Serialized::QueryMethods < ActiveRecord::QueryMethods
4
- def initialize(attributes, **)
6
+ def initialize(attributes, _)
5
7
  super
6
8
  attributes_extractor = @attributes_extractor
7
- opts_checker = @opts_checker = lambda do |opts|
8
- if keys = attributes_extractor.call(opts)
9
- raise ArgumentError,
10
- "You cannot query on mobility attributes translated with the Serialized backend (#{keys.join(", ")})."
11
- end
12
- end
9
+ opts_checker = @opts_checker = Backends::Serialized.attr_checker(attributes_extractor)
13
10
 
14
11
  define_method :where! do |opts, *rest|
15
12
  opts_checker.call(opts) || super(opts, *rest)
@@ -1,10 +1,13 @@
1
1
  # frozen-string-literal: true
2
+ require "mobility/backends/active_record"
3
+ require "mobility/backends/table"
4
+ require "mobility/active_record/model_translation"
2
5
 
3
6
  module Mobility
4
- module Backend
7
+ module Backends
5
8
  =begin
6
9
 
7
- Implements the {Mobility::Backend::Table} backend for ActiveRecord models.
10
+ Implements the {Mobility::Backends::Table} backend for ActiveRecord models.
8
11
 
9
12
  To generate a translation table for a model +Post+, you can use the included
10
13
  +mobility:translations+ generator:
@@ -85,33 +88,15 @@ columns to that table.
85
88
  =end
86
89
  class ActiveRecord::Table
87
90
  include ActiveRecord
91
+ include Table
88
92
 
89
- require 'mobility/backend/active_record/table/query_methods'
93
+ require 'mobility/backends/active_record/table/query_methods'
90
94
 
91
95
  # @return [Symbol] name of the association method
92
96
  attr_reader :association_name
93
97
 
94
- # @!macro backend_constructor
95
- # @option options [Symbol] association_name Name of association
96
- def initialize(model, attribute, **options)
97
- super
98
- @association_name = options[:association_name]
99
- end
100
-
101
- # @!group Backend Accessors
102
- # @!macro backend_reader
103
- def read(locale, **_)
104
- translation_for(locale).send(attribute)
105
- end
106
-
107
- # @!macro backend_reader
108
- def write(locale, value, **_)
109
- translation_for(locale).tap { |t| t.send("#{attribute}=", value) }.send(attribute)
110
- end
111
- # @!endgroup
112
-
113
98
  # @!group Backend Configuration
114
- # @option options [Symbol] association_name (:mobility_model_translations)
99
+ # @option options [Symbol] association_name (:translations)
115
100
  # Name of association method
116
101
  # @option options [Symbol] table_name Name of translation table
117
102
  # @option options [Symbol] foreign_key Name of foreign key
@@ -124,10 +109,10 @@ columns to that table.
124
109
  if (association_name = options[:association_name]).present?
125
110
  options[:subclass_name] ||= association_name.to_s.singularize.camelize.freeze
126
111
  else
127
- options[:association_name] = :mobility_model_translations
112
+ options[:association_name] = :translations
128
113
  options[:subclass_name] ||= :Translation
129
114
  end
130
- %i[foreign_key association_name subclass_name].each { |key| options[key] = options[key].to_sym }
115
+ %i[foreign_key association_name subclass_name table_name].each { |key| options[key] = options[key].to_sym }
131
116
  end
132
117
  # @!endgroup
133
118
 
@@ -135,8 +120,6 @@ columns to that table.
135
120
  association_name = options[:association_name]
136
121
  subclass_name = options[:subclass_name]
137
122
 
138
- attr_accessor :"__#{association_name}_cache"
139
-
140
123
  translation_class =
141
124
  if self.const_defined?(subclass_name, false)
142
125
  const_get(subclass_name, false)
@@ -161,43 +144,11 @@ columns to that table.
161
144
 
162
145
  setup_query_methods(QueryMethods)
163
146
 
164
- # @!group Cache Methods
165
- # @return [Table::TranslationsCache]
166
- def new_cache
167
- reset_model_cache unless model_cache
168
- model_cache.for(attribute)
169
- end
170
-
171
- # @return [Boolean]
172
- def write_to_cache?
173
- true
174
- end
175
-
176
- def clear_cache
177
- model_cache.try(:clear)
178
- end
179
- # @!endgroup
180
-
181
- private
182
-
183
- def translation_for(locale)
147
+ def translation_for(locale, _)
184
148
  translation = translations.find { |t| t.locale == locale.to_s.freeze }
185
149
  translation ||= translations.build(locale: locale)
186
150
  translation
187
151
  end
188
-
189
- def translations
190
- model.send(association_name)
191
- end
192
-
193
- def model_cache
194
- model.send(:"__#{association_name}_cache")
195
- end
196
-
197
- def reset_model_cache
198
- model.send(:"__#{association_name}_cache=",
199
- Table::TranslationsCache.new { |locale| translation_for(locale) })
200
- end
201
152
  end
202
153
  end
203
154
  end
@@ -1,5 +1,7 @@
1
+ require "mobility/backends/active_record/query_methods"
2
+
1
3
  module Mobility
2
- module Backend
4
+ module Backends
3
5
  class ActiveRecord::Table::QueryMethods < ActiveRecord::QueryMethods
4
6
  def initialize(attributes, association_name: nil, model_class: nil, subclass_name: nil, **options)
5
7
  super
@@ -39,7 +41,7 @@ module Mobility
39
41
 
40
42
  private
41
43
 
42
- def define_join_method(association_name, translation_class, foreign_key: nil, table_name: nil, **_)
44
+ def define_join_method(association_name, translation_class, foreign_key: nil, table_name: nil, **)
43
45
  define_method :"join_#{association_name}" do |**options|
44
46
  return self if (@__mobility_table_joined || []).include?(table_name)
45
47
  (@__mobility_table_joined ||= []) << table_name
@@ -52,7 +54,7 @@ module Mobility
52
54
  end
53
55
  end
54
56
 
55
- def define_query_methods(association_name, translation_class, **_)
57
+ def define_query_methods(association_name, translation_class, **)
56
58
  attributes_extractor = @attributes_extractor
57
59
 
58
60
  # Note that Mobility will try to use inner/outer joins appropriate to the query,
@@ -1,5 +1,5 @@
1
1
  module Mobility
2
- module Backend
2
+ module Backends
3
3
  =begin
4
4
 
5
5
  Stores translated attribute as a column on the model table. To use this
@@ -20,12 +20,12 @@ or locales.)
20
20
  There are no options for this backend. Also, the +locale_accessors+ option will
21
21
  be ignored if set, since it would cause a conflict with column accessors.
22
22
 
23
- @see Mobility::Backend::ActiveRecord::Column
24
- @see Mobility::Backend::Sequel::Column
23
+ @see Mobility::Backends::ActiveRecord::Column
24
+ @see Mobility::Backends::Sequel::Column
25
25
 
26
26
  =end
27
27
  module Column
28
- include OrmDelegator
28
+ extend Backend::OrmDelegator
29
29
 
30
30
  # Returns name of column where translated attribute is stored
31
31
  # @param [Symbol] locale
@@ -42,6 +42,10 @@ be ignored if set, since it would cause a conflict with column accessors.
42
42
  normalized_locale = Mobility.normalize_locale(locale)
43
43
  "#{attribute}_#{normalized_locale}".to_sym
44
44
  end
45
+
46
+ def self.included(base)
47
+ base.extend Backend::OrmDelegator
48
+ end
45
49
  end
46
50
  end
47
51
  end
@@ -0,0 +1,29 @@
1
+ module Mobility
2
+ module Backends
3
+ =begin
4
+
5
+ Defines read and write methods that access the value at a key with value
6
+ +locale+ on a +translations+ hash.
7
+
8
+ =end
9
+ module HashValued
10
+ # @!group Backend Accessors
11
+ #
12
+ # @!macro backend_reader
13
+ def read(locale, _ = {})
14
+ translations[locale]
15
+ end
16
+
17
+ # @!macro backend_writer
18
+ def write(locale, value, _ = {})
19
+ translations[locale] = value
20
+ end
21
+ # @!endgroup
22
+
23
+ # @!macro backend_iterator
24
+ def each_locale
25
+ translations.each { |l, _| yield l }
26
+ end
27
+ end
28
+ end
29
+ end