mobility 1.0.0.alpha → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) 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 +17 -1
  5. data/Gemfile.lock +15 -84
  6. data/README.md +3 -3
  7. data/lib/mobility.rb +6 -2
  8. data/lib/mobility/arel.rb +1 -1
  9. data/lib/mobility/backend.rb +8 -10
  10. data/lib/mobility/backends.rb +1 -1
  11. data/lib/mobility/backends/active_record/container.rb +2 -5
  12. data/lib/mobility/backends/active_record/hstore.rb +1 -1
  13. data/lib/mobility/backends/active_record/key_value.rb +1 -1
  14. data/lib/mobility/backends/active_record/serialized.rb +4 -0
  15. data/lib/mobility/backends/active_record/table.rb +1 -1
  16. data/lib/mobility/backends/container.rb +10 -2
  17. data/lib/mobility/backends/hash_valued.rb +4 -0
  18. data/lib/mobility/backends/jsonb.rb +1 -1
  19. data/lib/mobility/backends/key_value.rb +12 -15
  20. data/lib/mobility/backends/sequel.rb +2 -2
  21. data/lib/mobility/backends/sequel/container.rb +3 -5
  22. data/lib/mobility/backends/sequel/hstore.rb +1 -1
  23. data/lib/mobility/backends/sequel/json.rb +1 -0
  24. data/lib/mobility/backends/sequel/serialized.rb +4 -0
  25. data/lib/mobility/backends/table.rb +18 -23
  26. data/lib/mobility/pluggable.rb +21 -1
  27. data/lib/mobility/plugins.rb +2 -0
  28. data/lib/mobility/plugins/active_model/dirty.rb +11 -5
  29. data/lib/mobility/plugins/active_record/uniqueness_validation.rb +1 -1
  30. data/lib/mobility/plugins/backend.rb +38 -15
  31. data/lib/mobility/plugins/cache.rb +12 -5
  32. data/lib/mobility/plugins/default.rb +1 -1
  33. data/lib/mobility/plugins/fallbacks.rb +4 -4
  34. data/lib/mobility/plugins/fallthrough_accessors.rb +5 -6
  35. data/lib/mobility/plugins/locale_accessors.rb +2 -5
  36. data/lib/mobility/plugins/presence.rb +1 -1
  37. data/lib/mobility/plugins/reader.rb +2 -2
  38. data/lib/mobility/plugins/sequel/dirty.rb +1 -1
  39. data/lib/mobility/plugins/writer.rb +1 -1
  40. data/lib/mobility/version.rb +1 -1
  41. data/lib/rails/generators/mobility/templates/initializer.rb +2 -2
  42. metadata +2 -2
  43. metadata.gz.sig +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2cfc984b6de27771cbdbe1e7cba1864134d7008a3c07a75a4f890ca0007a956
4
- data.tar.gz: b7ea3bc4122a9f536a58bd00dc18b8c47151168e39dc8b315bdc5ade77e6385b
3
+ metadata.gz: a27c475aac12e8c93750cd6b11b7b339912c95bb24ada1e579c8f87598359388
4
+ data.tar.gz: faf2187673842e059b204715e774b2ef22d0a98e6162d7014ef875236a0db192
5
5
  SHA512:
6
- metadata.gz: 745a3462d4ca4b9fe9a392a2c38e95a3a59626c8d560a7eaa5eb3650320c02a2b88797fe16bb5a203a3f0e42a401f632fcf620a5dcc0cc6e1f579dcb132a6a8e
7
- data.tar.gz: 54031f4838a210915a964b954289e435cd4280c663b24c5516b6050318c9a0551b9912d36c968a71c17ac9199d30f0edea40cd4441046f38d4085f5195c73606
6
+ metadata.gz: 51dfb02fb8624897834dbc9260eb7edc67f6120f2971de120f7084e59df0865a027eca3ccae435ba77604fa8086760a1c682b9879a4c625be71368fa21d3b2c7
7
+ data.tar.gz: 5133980f0433ba31d157ebda7e1a8028dc84aa8d8dc7ab6b0df94861c347e60f34b09665eb890341998080be5256bea566f7e0dea62f96f6c85fcfd931319969
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,6 +1,22 @@
1
1
  # Mobility Changelog
2
2
 
3
- ## 1.0.0.alpha (unreleased)
3
+ ## 1.0
4
+
5
+ 1.0 is a rewrite of many internals of the gem. Please see the [wiki page on v1.0](https://github.com/shioyama/mobility/wiki/Introduction-to-Mobility-v1.0) for more details on how to upgrade.
6
+
7
+ ## 1.0.0.beta1 (pre-release)
8
+
9
+ - Remove `Mobility::Backend#apply_plugin`
10
+ ([#454](https://github.com/shioyama/mobility/pull/454))
11
+ - Instance exec configure block if it takes no arguments
12
+ ([#456](https://github.com/shioyama/mobility/pull/456))
13
+ - Raise an exception if invalid options are passed to Translations initializer
14
+ ([#457](https://github.com/shioyama/mobility/pull/457/files))
15
+ - Fix Ruby 2.7 deprecation warnings
16
+ ([#460](https://github.com/shioyama/mobility/pull/460))
17
+
18
+ ## 1.0.0.alpha (pre-release)
19
+
4
20
  - Default fallbacks plugin to `true` when enabled
5
21
  ([#447](https://github.com/shioyama/mobility/pull/447))
6
22
  - Remove `Mobility::Backend.method_name`
@@ -1,38 +1,3 @@
1
- GIT
2
- remote: https://github.com/rails/rails.git
3
- revision: 0a608bd987fde4f9bc5bcf4bcebdb181d199cf4f
4
- specs:
5
- actionpack (6.1.0.alpha)
6
- actionview (= 6.1.0.alpha)
7
- activesupport (= 6.1.0.alpha)
8
- rack (~> 2.0, >= 2.0.9)
9
- rack-test (>= 0.6.3)
10
- rails-dom-testing (~> 2.0)
11
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
12
- actionview (6.1.0.alpha)
13
- activesupport (= 6.1.0.alpha)
14
- builder (~> 3.1)
15
- erubi (~> 1.4)
16
- rails-dom-testing (~> 2.0)
17
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
18
- activemodel (6.1.0.alpha)
19
- activesupport (= 6.1.0.alpha)
20
- activerecord (6.1.0.alpha)
21
- activemodel (= 6.1.0.alpha)
22
- activesupport (= 6.1.0.alpha)
23
- activesupport (6.1.0.alpha)
24
- concurrent-ruby (~> 1.0, >= 1.0.2)
25
- i18n (>= 1.6, < 2)
26
- minitest (>= 5.1)
27
- tzinfo (~> 2.0)
28
- zeitwerk (~> 2.3)
29
- railties (6.1.0.alpha)
30
- actionpack (= 6.1.0.alpha)
31
- activesupport (= 6.1.0.alpha)
32
- method_source
33
- rake (>= 0.8.7)
34
- thor (~> 1.0)
35
-
36
1
  PATH
37
2
  remote: .
38
3
  specs:
@@ -43,22 +8,15 @@ PATH
43
8
  GEM
44
9
  remote: https://rubygems.org/
45
10
  specs:
46
- actionmailer (0.6.1)
47
- actionpack (>= 0.9.5)
48
- benchmark-ips (2.8.2)
49
- builder (3.2.4)
11
+ allocation_stats (0.1.5)
12
+ benchmark-ips (2.8.3)
50
13
  byebug (11.1.3)
51
14
  coderay (1.1.3)
52
15
  concurrent-ruby (1.1.7)
53
- crass (1.0.6)
54
16
  database_cleaner (1.8.5)
55
17
  diff-lcs (1.4.4)
56
- erubi (1.9.0)
57
18
  ffi (1.13.1)
58
19
  formatador (0.2.5)
59
- generator_spec (0.9.4)
60
- activesupport (>= 3.0.0)
61
- railties (>= 3.0.0)
62
20
  guard (2.16.2)
63
21
  formatador (>= 0.2.4)
64
22
  listen (>= 2.7, < 4.0)
@@ -78,20 +36,12 @@ GEM
78
36
  listen (3.2.1)
79
37
  rb-fsevent (~> 0.10, >= 0.10.3)
80
38
  rb-inotify (~> 0.9, >= 0.9.10)
81
- loofah (2.7.0)
82
- crass (~> 1.0.2)
83
- nokogiri (>= 1.5.9)
84
- lumberjack (1.2.7)
39
+ lumberjack (1.2.8)
85
40
  method_source (1.0.0)
86
- mini_portile2 (2.4.0)
87
- minitest (5.14.2)
88
41
  nenv (0.3.0)
89
- nokogiri (1.10.10)
90
- mini_portile2 (~> 2.4.0)
91
42
  notiffany (0.1.3)
92
43
  nenv (~> 0.1)
93
44
  shellany (~> 0.0)
94
- pg (1.2.3)
95
45
  pry (0.13.1)
96
46
  coderay (~> 1.1)
97
47
  method_source (~> 1.0)
@@ -99,58 +49,39 @@ GEM
99
49
  byebug (~> 11.0)
100
50
  pry (~> 0.13.0)
101
51
  rack (2.2.3)
102
- rack-test (1.1.0)
103
- rack (>= 1.0, < 3)
104
- rails (0.9.5)
105
- actionmailer (>= 0.6.1)
106
- actionpack (>= 1.4.0)
107
- activerecord (>= 1.6.0)
108
- rake (>= 0.4.15)
109
- rails-dom-testing (2.0.3)
110
- activesupport (>= 4.2.0)
111
- nokogiri (>= 1.6)
112
- rails-html-sanitizer (1.3.0)
113
- loofah (~> 2.3)
114
52
  rake (12.3.3)
115
53
  rb-fsevent (0.10.4)
116
54
  rb-inotify (0.10.1)
117
55
  ffi (~> 1.0)
118
56
  request_store (1.5.0)
119
57
  rack (>= 1.4)
120
- rspec (3.9.0)
121
- rspec-core (~> 3.9.0)
122
- rspec-expectations (~> 3.9.0)
123
- rspec-mocks (~> 3.9.0)
124
- rspec-core (3.9.2)
125
- rspec-support (~> 3.9.3)
126
- rspec-expectations (3.9.2)
58
+ rspec (3.10.0)
59
+ rspec-core (~> 3.10.0)
60
+ rspec-expectations (~> 3.10.0)
61
+ rspec-mocks (~> 3.10.0)
62
+ rspec-core (3.10.0)
63
+ rspec-support (~> 3.10.0)
64
+ rspec-expectations (3.10.0)
127
65
  diff-lcs (>= 1.2.0, < 2.0)
128
- rspec-support (~> 3.9.0)
129
- rspec-mocks (3.9.1)
66
+ rspec-support (~> 3.10.0)
67
+ rspec-mocks (3.10.0)
130
68
  diff-lcs (>= 1.2.0, < 2.0)
131
- rspec-support (~> 3.9.0)
132
- rspec-support (3.9.3)
69
+ rspec-support (~> 3.10.0)
70
+ rspec-support (3.10.0)
133
71
  shellany (0.0.1)
134
72
  thor (1.0.1)
135
- tzinfo (2.0.2)
136
- concurrent-ruby (~> 1.0)
137
73
  yard (0.9.25)
138
- zeitwerk (2.4.0)
139
74
 
140
75
  PLATFORMS
141
76
  ruby
142
77
 
143
78
  DEPENDENCIES
144
- activerecord!
145
- activesupport!
79
+ allocation_stats
146
80
  benchmark-ips
147
81
  database_cleaner (~> 1.5, >= 1.5.3)
148
- generator_spec (~> 0.9.4)
149
82
  guard-rspec
150
83
  mobility!
151
- pg
152
84
  pry-byebug
153
- rails
154
85
  rake (~> 12, >= 12.2.1)
155
86
  rspec (~> 3.0)
156
87
  yard (~> 0.9.0)
data/README.md CHANGED
@@ -13,7 +13,7 @@ Mobility
13
13
  [wiki]: https://github.com/shioyama/mobility/wiki
14
14
 
15
15
  **This is the readme for the [`master`](https://github.com/shioyama/mobility)
16
- branch, which corresponds to v1.0.0.alpha, a pre-release version of Mobility.
16
+ branch, which corresponds to v1.0.0.beta, a pre-release version of Mobility.
17
17
  If you are using an earlier version (0.8.x or earlier), you probably want the
18
18
  readme on the [0-8-stable
19
19
  branch](https://github.com/shioyama/mobility/tree/0-8-stable).**
@@ -54,11 +54,11 @@ section of the wiki.
54
54
  Installation
55
55
  ------------
56
56
 
57
- To use the latest (unreleased) version of Mobility, add this line to your
57
+ To use the latest pre-version of Mobility 1.0, add this line to your
58
58
  application's Gemfile:
59
59
 
60
60
  ```ruby
61
- gem 'mobility', git: 'https://github.com/shioyama/mobility.git'
61
+ gem 'mobility', '~> 1.0.0.beta1'
62
62
  ```
63
63
 
64
64
  For the latest stable version of Mobility, see the readme on the
@@ -57,9 +57,13 @@ module Mobility
57
57
 
58
58
  # Configure Mobility
59
59
  # @yield [Mobility::Translations]
60
- def configure
60
+ def configure(&block)
61
61
  translates_with(Class.new(Translations)) unless @translations_class
62
- yield translations_class
62
+ if block.arity == 0
63
+ translations_class.instance_exec(&block)
64
+ else
65
+ yield translations_class
66
+ end
63
67
  end
64
68
  # @!endgroup
65
69
 
@@ -38,7 +38,7 @@ module Mobility
38
38
  attr_reader :locale
39
39
  attr_reader :attribute_name
40
40
 
41
- def initialize(relation, column_name, locale, backend_class, attribute_name: nil)
41
+ def initialize(relation, column_name, locale, backend_class, attribute_name = nil)
42
42
  @backend_class = backend_class
43
43
  @locale = locale
44
44
  @attribute_name = attribute_name || column_name
@@ -100,7 +100,7 @@ On top of this, a backend will normally:
100
100
  # @param [Symbol] locale Locale to read
101
101
  # @return [TrueClass,FalseClass] Whether translation is present for locale
102
102
  def present?(locale, options = {})
103
- Util.present?(read(locale, options))
103
+ Util.present?(read(locale, **options))
104
104
  end
105
105
 
106
106
  # @!method model_class
@@ -120,6 +120,13 @@ On top of this, a backend will normally:
120
120
 
121
121
  # Defines setup hooks for backend to customize model class.
122
122
  module ClassMethods
123
+ # Returns valid option keys for this backend. This is overriden in
124
+ # backends to define which keys are valid for each backend class.
125
+ # @return [Array]
126
+ def valid_keys
127
+ []
128
+ end
129
+
123
130
  # Assign block to be called on model class.
124
131
  # @yield [attribute_names, options]
125
132
  # @note When called multiple times, setup blocks will be appended
@@ -179,15 +186,6 @@ On top of this, a backend will normally:
179
186
  EOM
180
187
  end
181
188
 
182
- # Called from plugins to apply custom processing for this backend.
183
- # Name is the name of the plugin.
184
- # @param [Symbol] name Name of plugin
185
- # @return [Boolean] Whether the plugin was applied
186
- # @note This is currently only called by Plugins::Cache.
187
- def apply_plugin(_)
188
- false
189
- end
190
-
191
189
  # Show useful information about this backend class, if it has no name.
192
190
  # @return [String]
193
191
  def inspect
@@ -5,7 +5,7 @@ module Mobility
5
5
  class << self
6
6
  # @param [Symbol, Object] backend Name of backend to load.
7
7
  def load_backend(name)
8
- return name if Module === name
8
+ return name if Module === name || name.nil?
9
9
 
10
10
  unless (backend = @backends[name])
11
11
  require "mobility/backends/#{name}"
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "mobility/backends/active_record"
3
+ require "mobility/backends/container"
3
4
  require "mobility/arel/nodes/pg_ops"
4
5
 
5
6
  module Mobility
@@ -11,11 +12,7 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
11
12
  =end
12
13
  class ActiveRecord::Container
13
14
  include ActiveRecord
14
-
15
- # @!method column_name
16
- # Returns name of json or jsonb column used to store translations
17
- # @return [Symbol] (:translations) Name of translations column
18
- option_reader :column_name
15
+ include Container
19
16
 
20
17
  # @!group Backend Accessors
21
18
  #
@@ -18,7 +18,7 @@ Implements the {Mobility::Backends::Hstore} backend for ActiveRecord models.
18
18
 
19
19
  # @!macro backend_writer
20
20
  def write(locale, value, options = {})
21
- super(locale, value && value.to_s, options)
21
+ super(locale, value && value.to_s, **options)
22
22
  end
23
23
  # @!endgroup
24
24
 
@@ -51,7 +51,7 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
51
51
  # translation table value column
52
52
  def build_node(attr, locale)
53
53
  aliased_table = class_name.arel_table.alias(table_alias(attr, locale))
54
- Arel::Attribute.new(aliased_table, :value, locale, self, attribute_name: attr.to_sym)
54
+ Arel::Attribute.new(aliased_table, :value, locale, self, attr.to_sym)
55
55
  end
56
56
 
57
57
  # Joins translations using either INNER/OUTER join appropriate to the query.
@@ -30,6 +30,10 @@ Implements {Mobility::Backends::Serialized} backend for ActiveRecord models.
30
30
  include ActiveRecord
31
31
  include HashValued
32
32
 
33
+ def self.valid_keys
34
+ super + [:format]
35
+ end
36
+
33
37
  # @!group Backend Configuration
34
38
  # @param (see Backends::Serialized.configure)
35
39
  # @option (see Backends::Serialized.configure)
@@ -283,7 +283,7 @@ columns to that table.
283
283
 
284
284
  # Returns translation for a given locale, or builds one if none is present.
285
285
  # @param [Symbol] locale
286
- def translation_for(locale, _)
286
+ def translation_for(locale, **)
287
287
  translation = translations.in_locale(locale)
288
288
  translation ||= translations.build(locale: locale)
289
289
  translation
@@ -19,8 +19,16 @@ stored).
19
19
 
20
20
  =end
21
21
  module Container
22
+ def self.included(backend_class)
23
+ backend_class.extend ClassMethods
24
+ backend_class.option_reader :column_name
25
+ end
26
+
27
+ module ClassMethods
28
+ def valid_keys
29
+ [:column_name]
30
+ end
31
+ end
22
32
  end
23
-
24
- register_backend(:container, Container)
25
33
  end
26
34
  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
- ===+prefix+ and +suffix+
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
 
@@ -54,13 +54,13 @@ other backends on model (otherwise one will overwrite the other).
54
54
 
55
55
  # @!group Backend Accessors
56
56
  # @!macro backend_reader
57
- def read(locale, options = {})
58
- translation_for(locale, options).value
57
+ def read(locale, **options)
58
+ translation_for(locale, **options).value
59
59
  end
60
60
 
61
61
  # @!macro backend_writer
62
- def write(locale, value, options = {})
63
- translation_for(locale, options).value = value
62
+ def write(locale, value, **options)
63
+ translation_for(locale, **options).value = value
64
64
  end
65
65
  # @!endgroup
66
66
 
@@ -83,6 +83,10 @@ other backends on model (otherwise one will overwrite the other).
83
83
  end
84
84
 
85
85
  module ClassMethods
86
+ def valid_keys
87
+ [:type, :association_name, :class_name]
88
+ end
89
+
86
90
  # @!group Backend Configuration
87
91
  # @option options [Symbol,String] type Column type to use
88
92
  # @option options [Symbol] association_name (:<type>_translations) Name
@@ -100,16 +104,9 @@ other backends on model (otherwise one will overwrite the other).
100
104
  end
101
105
  end
102
106
 
103
- # Apply custom processing for plugin
104
- # @param (see Backend::ClassMethods#apply_plugin)
105
- # @return (see Backend::ClassMethods#apply_plugin)
106
- def apply_plugin(name)
107
- if name == :cache
108
- include self::Cache
109
- true
110
- else
111
- super
112
- end
107
+ # Apply custom processing for cache plugin
108
+ def include_cache
109
+ include self::Cache
113
110
  end
114
111
 
115
112
  def table_alias(attr, locale)
@@ -123,7 +120,7 @@ other backends on model (otherwise one will overwrite the other).
123
120
  if cache.has_key?(locale)
124
121
  cache[locale]
125
122
  else
126
- cache[locale] = super(locale, options)
123
+ cache[locale] = super(locale, **options)
127
124
  end
128
125
  end
129
126
 
@@ -5,8 +5,8 @@ module Mobility
5
5
  module Backends
6
6
  module Sequel
7
7
  def self.included(backend_class)
8
- backend_class.include(Backend)
9
- backend_class.extend(ClassMethods)
8
+ backend_class.include Backend
9
+ backend_class.extend ClassMethods
10
10
  end
11
11
 
12
12
  module ClassMethods
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
- require "mobility/backends/sequel/json"
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
  #
@@ -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
 
@@ -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
@@ -36,6 +36,10 @@ Sequel serialization plugin.
36
36
  include Sequel
37
37
  include HashValued
38
38
 
39
+ def self.valid_keys
40
+ super + [:format]
41
+ end
42
+
39
43
  # @!group Backend Configuration
40
44
  # @param (see Backends::Serialized.configure)
41
45
  # @option (see Backends::Serialized.configure)
@@ -83,13 +83,13 @@ set.
83
83
 
84
84
  # @!group Backend Accessors
85
85
  # @!macro backend_reader
86
- def read(locale, options = {})
87
- translation_for(locale, options).send(attribute)
86
+ def read(locale, **options)
87
+ translation_for(locale, **options).send(attribute)
88
88
  end
89
89
 
90
90
  # @!macro backend_writer
91
- def write(locale, value, options = {})
92
- translation_for(locale, options).send("#{attribute}=", value)
91
+ def write(locale, value, **options)
92
+ translation_for(locale, **options).send("#{attribute}=", value)
93
93
  end
94
94
  # @!endgroup
95
95
 
@@ -104,25 +104,22 @@ set.
104
104
  model.send(association_name)
105
105
  end
106
106
 
107
- def self.included(backend)
108
- backend.extend ClassMethods
109
- backend.option_reader :association_name
110
- backend.option_reader :subclass_name
111
- backend.option_reader :foreign_key
112
- backend.option_reader :table_name
107
+ def self.included(backend_class)
108
+ backend_class.extend ClassMethods
109
+ backend_class.option_reader :association_name
110
+ backend_class.option_reader :subclass_name
111
+ backend_class.option_reader :foreign_key
112
+ backend_class.option_reader :table_name
113
113
  end
114
114
 
115
115
  module ClassMethods
116
- # Apply custom processing for plugin
117
- # @param (see Backend::Setup#apply_plugin)
118
- # @return (see Backend::Setup#apply_plugin)
119
- def apply_plugin(name)
120
- if name == :cache
121
- include self::Cache
122
- true
123
- else
124
- super
125
- end
116
+ def valid_keys
117
+ [:association_name, :subclass_name, :foreign_key, :table_name]
118
+ end
119
+
120
+ # Apply custom processing for cache plugin
121
+ def include_cache
122
+ include self::Cache
126
123
  end
127
124
 
128
125
  def table_alias(locale)
@@ -138,7 +135,7 @@ set.
138
135
  if cache.has_key?(locale)
139
136
  cache[locale]
140
137
  else
141
- cache[locale] = super(locale, options)
138
+ cache[locale] = super(locale, **options)
142
139
  end
143
140
  end
144
141
 
@@ -157,7 +154,5 @@ set.
157
154
  end
158
155
  end
159
156
  end
160
-
161
- register_backend(:table, Table)
162
157
  end
163
158
  end
@@ -17,6 +17,10 @@ Works with {Mobility::Plugin}. (Subclassed by {Mobility::Translations}.)
17
17
  Plugin.configure(self, defaults, &block)
18
18
  end
19
19
 
20
+ def included_plugins
21
+ included_modules.grep(Plugin)
22
+ end
23
+
20
24
  def defaults
21
25
  @defaults ||= {}
22
26
  end
@@ -28,9 +32,25 @@ Works with {Mobility::Plugin}. (Subclassed by {Mobility::Translations}.)
28
32
  end
29
33
 
30
34
  def initialize(*, **options)
31
- @options = self.class.defaults.merge(options)
35
+ initialize_options(options)
36
+ validate_options(@options)
32
37
  end
33
38
 
34
39
  attr_reader :options
40
+
41
+ private
42
+
43
+ def initialize_options(options)
44
+ @options = self.class.defaults.merge(options)
45
+ end
46
+
47
+ # This is overridden by backend plugin to exclude mixed-in backend options.
48
+ def validate_options(options)
49
+ plugin_keys = self.class.included_plugins.map { |p| Plugins.lookup_name(p) }
50
+ extra_keys = options.keys - plugin_keys
51
+ raise InvalidOptionKey, "No plugin configured for these keys: #{extra_keys.join(', ')}." unless extra_keys.empty?
52
+ end
53
+
54
+ class InvalidOptionKey < Error; end
35
55
  end
36
56
  end
@@ -14,6 +14,8 @@ declared in any order (dependencies will be resolved).
14
14
  class << self
15
15
  # @param [Symbol] name Name of plugin to load.
16
16
  def load_plugin(name)
17
+ return name if Module === name || name.nil?
18
+
17
19
  unless (plugin = @plugins[name])
18
20
  require "mobility/plugins/#{name}"
19
21
  raise LoadError, "plugin #{name} did not register itself correctly in Mobility::Plugins" unless (plugin = @plugins[name])
@@ -80,7 +80,12 @@ the ActiveRecord dirty plugin for more information.
80
80
  attribute_names.each do |name|
81
81
  dirty_handler_methods.each_pattern(name) do |method_name, attribute_method|
82
82
  define_method(method_name) do |*args|
83
- mutations_from_mobility.send(attribute_method, Dirty.append_locale(name), *args)
83
+ # for %s_changed?(from:, to:) pattern
84
+ if (kwargs = args.last).is_a?(Hash)
85
+ mutations_from_mobility.send(attribute_method, Dirty.append_locale(name), *args[0,-1], **kwargs)
86
+ else
87
+ mutations_from_mobility.send(attribute_method, Dirty.append_locale(name), *args)
88
+ end
84
89
  end
85
90
  end
86
91
 
@@ -130,11 +135,12 @@ the ActiveRecord dirty plugin for more information.
130
135
  public_patterns.each do |pattern|
131
136
  method_name = pattern % 'attribute'
132
137
 
138
+ kwargs = pattern == '%s_changed?' ? ', **kwargs' : ''
133
139
  module_eval <<-EOM, __FILE__, __LINE__ + 1
134
- def #{method_name}(attr_name, *rest)
140
+ def #{method_name}(attr_name, *rest#{kwargs})
135
141
  if (mutations_from_mobility.attribute_changed?(attr_name) ||
136
142
  mutations_from_mobility.attribute_previously_changed?(attr_name))
137
- mutations_from_mobility.send(#{method_name.inspect}, attr_name, *rest)
143
+ mutations_from_mobility.send(#{method_name.inspect}, attr_name, *rest#{kwargs})
138
144
  else
139
145
  super
140
146
  end
@@ -330,11 +336,11 @@ the ActiveRecord dirty plugin for more information.
330
336
  # @!group Backend Accessors
331
337
  # @!macro backend_writer
332
338
  # @param [Hash] options
333
- def write(locale, value, options = {})
339
+ def write(locale, value, **options)
334
340
  locale_accessor = Mobility.normalize_locale_accessor(attribute, locale)
335
341
  if model.changed_attributes.has_key?(locale_accessor) && model.changed_attributes[locale_accessor] == value
336
342
  mutations_from_mobility.restore_attribute!(locale_accessor)
337
- elsif read(locale, options.merge(locale: true)) != value
343
+ elsif read(locale, **options.merge(locale: true)) != value
338
344
  mutations_from_mobility.attribute_will_change!(locale_accessor)
339
345
  end
340
346
  super
@@ -35,7 +35,7 @@ module Mobility
35
35
  error_options = options.except(:case_sensitive, :scope, :conditions)
36
36
  error_options[:value] = value
37
37
 
38
- record.errors.add(attribute, :taken, error_options)
38
+ record.errors.add(attribute, :taken, **error_options)
39
39
  end
40
40
  else
41
41
  super
@@ -32,18 +32,12 @@ Defines:
32
32
 
33
33
  def initialize(*args, **original_options)
34
34
  super
35
- return unless Plugins::Backend.dependencies_satisfied?(self.class)
36
35
 
37
- case options[:backend]
38
- when String, Symbol, Class
39
- @backend, @backend_options = options[:backend], options
40
- when Array
41
- @backend, @backend_options = options[:backend]
42
- @backend_options = @backend_options.merge(original_options)
43
- when NilClass
44
- @backend = @backend_options = nil
45
- else
46
- raise ArgumentError, "backend must be either a backend name, a backend class, or a two-element array"
36
+ # Validate that the default backend from config has valid keys
37
+ if (default = self.class.defaults[:backend])
38
+ name, backend_options = default
39
+ extra_keys = backend_options.keys - backend.valid_keys
40
+ raise InvalidOptionKey, "These are not valid #{name} backend keys: #{extra_keys.join(', ')}." unless extra_keys.empty?
47
41
  end
48
42
 
49
43
  include InstanceMethods
@@ -58,8 +52,7 @@ Defines:
58
52
  klass.extend ClassMethods
59
53
 
60
54
  if backend
61
- @backend_class = load_backend(backend).
62
- build_subclass(klass, backend_options)
55
+ @backend_class = backend.build_subclass(klass, backend_options)
63
56
 
64
57
  backend_class.setup_model(klass, names)
65
58
 
@@ -83,10 +76,38 @@ Defines:
83
76
  raise e, "could not find a #{backend} backend. Did you forget to include an ORM plugin like active_record or sequel?"
84
77
  end
85
78
 
79
+ private
80
+
81
+ # Override to extract backend options from options hash.
82
+ def initialize_options(original_options)
83
+ super
84
+
85
+ case options[:backend]
86
+ when String, Symbol, Class
87
+ @backend, @backend_options = options[:backend], options
88
+ when Array
89
+ @backend, @backend_options = options[:backend]
90
+ @backend_options = @backend_options.merge(original_options)
91
+ when NilClass
92
+ @backend = @backend_options = nil
93
+ else
94
+ raise ArgumentError, "backend must be either a backend name, a backend class, or a two-element array"
95
+ end
96
+
97
+ @backend = load_backend(backend)
98
+ end
99
+
100
+ # Override default validation to exclude backend options, which may be
101
+ # mixed in with plugin options.
102
+ def validate_options(options)
103
+ return super unless backend
104
+ super(options.slice(*(options.keys - backend.valid_keys)))
105
+ end
106
+
86
107
  # Override default argument-handling in DSL to store kwargs passed along
87
108
  # with plugin name.
88
- def self.configure_default(defaults, key, *args, **kwargs)
89
- defaults[key] = [args[0], kwargs] unless args.empty?
109
+ def self.configure_default(defaults, key, backend = nil, backend_options = {})
110
+ defaults[key] = [backend, backend_options] if backend
90
111
  end
91
112
 
92
113
  module InstanceMethods
@@ -131,6 +152,8 @@ Defines:
131
152
  @mobility_backend_classes ||= {}
132
153
  end
133
154
  end
155
+
156
+ class InvalidOptionKey < Error; end
134
157
  end
135
158
 
136
159
  register_plugin(:backend, Backend)
@@ -7,8 +7,7 @@ module Mobility
7
7
  Caches values fetched from the backend so subsequent fetches can be performed
8
8
  more quickly. The cache stores cached values in a simple hash, which is not
9
9
  optimal for some storage strategies, so some backends (KeyValue, Table) use a
10
- custom module through the {Mobility::Backend::Setup#apply_plugin} hook. For
11
- details see the documentation for these backends.
10
+ custom module by defining a method, +include_cache+, on the backend class.
12
11
 
13
12
  The cache is reset when one of a set of events happens (saving, reloading,
14
13
  etc.). See {BackendResetter} for details.
@@ -28,12 +27,20 @@ Values are added to the cache in two ways:
28
27
  # Applies cache plugin to attributes.
29
28
  included_hook do |_, backend_class|
30
29
  if options[:cache]
31
- backend_class.include(BackendMethods) unless backend_class.apply_plugin(:cache)
30
+ if backend_class.respond_to?(:include_cache)
31
+ backend_class.include_cache
32
+ else
33
+ include_cache(backend_class)
34
+ end
32
35
  end
33
36
  end
34
37
 
35
38
  private
36
39
 
40
+ def include_cache(backend_class)
41
+ backend_class.include BackendMethods
42
+ end
43
+
37
44
  # Used in ORM cache plugins
38
45
  def define_cache_hooks(klass, *reset_methods)
39
46
  mod = self
@@ -55,11 +62,11 @@ Values are added to the cache in two ways:
55
62
  # @!method read(locale, value, options = {})
56
63
  # @option options [Boolean] cache *false* to disable cache.
57
64
  def read(locale, **options)
58
- return super(locale, options) if options.delete(:cache) == false
65
+ return super(locale, **options) if options.delete(:cache) == false
59
66
  if cache.has_key?(locale)
60
67
  cache[locale]
61
68
  else
62
- cache[locale] = super(locale, options)
69
+ cache[locale] = super(locale, **options)
63
70
  end
64
71
  end
65
72
 
@@ -90,7 +90,7 @@ The proc can accept zero to three arguments (see examples below)
90
90
  # *false* to disable presence filter.
91
91
  def read(locale, accessor_options = {})
92
92
  default = accessor_options.has_key?(:default) ? accessor_options.delete(:default) : options[:default]
93
- if (value = super(locale, accessor_options)).nil?
93
+ if (value = super(locale, **accessor_options)).nil?
94
94
  Default[default, locale: locale, accessor_options: accessor_options, model: model, attribute: attribute]
95
95
  else
96
96
  value
@@ -47,7 +47,7 @@ the current locale was +nil+.
47
47
  Mobility.locale = :ja
48
48
  post.title
49
49
  #=> "foo"
50
-
50
+
51
51
  post.title = "bar"
52
52
  post.title
53
53
  #=> "bar"
@@ -144,15 +144,15 @@ the current locale was +nil+.
144
144
 
145
145
  def define_read(fallbacks)
146
146
  define_method :read do |locale, fallback: true, **options|
147
- return super(locale, options) if !fallback || options[:locale]
147
+ return super(locale, **options) if !fallback || options[:locale]
148
148
 
149
149
  locales = fallback == true ? fallbacks[locale] : [locale, *fallback]
150
150
  locales.each do |fallback_locale|
151
- value = super(fallback_locale, options)
151
+ value = super(fallback_locale, **options)
152
152
  return value if Util.present?(value)
153
153
  end
154
154
 
155
- super(locale, options)
155
+ super(locale, **options)
156
156
  end
157
157
  end
158
158
 
@@ -24,14 +24,11 @@ model class is generated.
24
24
 
25
25
  default true
26
26
 
27
- requires :reader
28
- requires :writer
29
-
30
27
  # Apply fallthrough accessors plugin to attributes.
31
28
  # @param [Translations] translations
32
29
  # @param [Boolean] option
33
30
  initialize_hook do
34
- if options[:fallthrough_accessors] && options[:reader] && options[:writer]
31
+ if options[:fallthrough_accessors]
35
32
  define_fallthrough_accessors(names)
36
33
  end
37
34
  end
@@ -47,9 +44,11 @@ model class is generated.
47
44
  locale, suffix = $2.split('_')
48
45
  locale = "#{locale}-#{suffix.upcase}" if suffix
49
46
  if $4 == '=' # writer
50
- public_send(attribute_method, args[0], **(args[1] || {}), locale: locale)
47
+ kwargs = args[1].is_a?(Hash) ? args[1] : {}
48
+ public_send(attribute_method, args[0], **kwargs, locale: locale)
51
49
  else # reader
52
- public_send(attribute_method, **(args[0] || {}), locale: locale)
50
+ kwargs = args[0].is_a?(Hash) ? args[0] : {}
51
+ public_send(attribute_method, **kwargs, locale: locale)
53
52
  end
54
53
  else
55
54
  super(method_name, *args, &block)
@@ -19,9 +19,6 @@ available locales for a Rails application) will be used by default.
19
19
 
20
20
  default true
21
21
 
22
- requires :reader
23
- requires :writer
24
-
25
22
  # Apply locale accessors plugin to attributes.
26
23
  # @param [Translations] translations
27
24
  # @param [Boolean] option
@@ -30,8 +27,8 @@ available locales for a Rails application) will be used by default.
30
27
  locales = Mobility.available_locales if locales == true
31
28
  names.each do |name|
32
29
  locales.each do |locale|
33
- define_locale_reader(name, locale) if options[:reader]
34
- define_locale_writer(name, locale) if options[:writer]
30
+ define_locale_reader(name, locale)
31
+ define_locale_writer(name, locale)
35
32
  end
36
33
  end
37
34
  end
@@ -39,7 +39,7 @@ backend.
39
39
  if options.delete(:presence) == false
40
40
  super
41
41
  else
42
- super(locale, Presence[value], options)
42
+ super(locale, Presence[value], **options)
43
43
  end
44
44
  end
45
45
  # @!endgroup
@@ -19,13 +19,13 @@ Defines attribute reader that delegates to +Mobility::Backend#read+.
19
19
  class_eval <<-EOM, __FILE__, __LINE__ + 1
20
20
  def #{name}(locale: nil, **options)
21
21
  #{Reader.setup_source}
22
- mobility_backends[:#{name}].read(locale, options)
22
+ mobility_backends[:#{name}].read(locale, **options)
23
23
  end
24
24
  EOM
25
25
  class_eval <<-EOM, __FILE__, __LINE__ + 1
26
26
  def #{name}?(locale: nil, **options)
27
27
  #{Reader.setup_source}
28
- mobility_backends[:#{name}].present?(locale, options)
28
+ mobility_backends[:#{name}].present?(locale, **options)
29
29
  end
30
30
  EOM
31
31
  end
@@ -56,7 +56,7 @@ Automatically includes dirty plugin in model class when enabled.
56
56
  if model.column_changes.has_key?(locale_accessor) && model.initial_values[locale_accessor] == value
57
57
  super
58
58
  [model.changed_columns, model.initial_values].each { |h| h.delete(locale_accessor) }
59
- elsif read(locale, options.merge(fallback: false)) != value
59
+ elsif read(locale, **options.merge(fallback: false)) != value
60
60
  model.will_change_column(locale_accessor)
61
61
  super
62
62
  end
@@ -19,7 +19,7 @@ Defines attribute writer that delegates to +Mobility::Backend#write+.
19
19
  class_eval <<-EOM, __FILE__, __LINE__ + 1
20
20
  def #{name}=(value, locale: nil, **options)
21
21
  #{Writer.setup_source}
22
- mobility_backends[:#{name}].write(locale, value, options)
22
+ mobility_backends[:#{name}].write(locale, value, **options)
23
23
  end
24
24
  EOM
25
25
  end
@@ -9,7 +9,7 @@ module Mobility
9
9
  MAJOR = 1
10
10
  MINOR = 0
11
11
  TINY = 0
12
- PRE = "alpha"
12
+ PRE = "beta1"
13
13
 
14
14
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
15
15
  end
@@ -1,7 +1,7 @@
1
- Mobility.configure do |config|
1
+ Mobility.configure do
2
2
 
3
3
  # PLUGINS
4
- config.plugins do
4
+ plugins do
5
5
  # Backend
6
6
  #
7
7
  # Sets the default backend to use in models. This can be overridden in models
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mobility
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.alpha
4
+ version: 1.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Salzberg
@@ -34,7 +34,7 @@ cert_chain:
34
34
  gSQml7TqcC6dZRsZRwYqzD9kUwdAJoCqno2CBUKs2l0yQAjFT36lRrVJznb7uWwa
35
35
  xpPFnsrtyaZW6Dty8TSG3qzmeGpmpIotA8x1VA==
36
36
  -----END CERTIFICATE-----
37
- date: 2020-10-25 00:00:00.000000000 Z
37
+ date: 2020-11-03 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: request_store
metadata.gz.sig CHANGED
Binary file