mobility 0.1.20 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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