mobility 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b22675841d6b6330a4db417e3576767b42a81614b80cf376a208088ad9432de4
4
- data.tar.gz: 1b2c44b38c87fc0b1e8ca5e463e9c265c09f0d307d0d663ba3aa39b6b5ca771b
3
+ metadata.gz: c5cedc8fabef42f478f93a4bb4fa1e8764759855dcded4d25f397c018f1811d2
4
+ data.tar.gz: 1fb647fdbcbafa3b8a5a6d47d71500e2481556aa72674c5269ea0dc560d63ca0
5
5
  SHA512:
6
- metadata.gz: 708d6ba16ec279e6a114abc811d107aa759590c711ca389d7f4b86407e100fbaed30a38b7b787ef98008291c480715949b0d4562efc2d5120eba73587fc375db
7
- data.tar.gz: bd8f79dd23f7c482292c011bb800d7db20dc3b1fb06797b53fdf91ecdb9c9895c1634e3b1da06e90cff4e7b32e4aa5ebdf8f5d8b5c76f1fafbc08ca891ac99dc
6
+ metadata.gz: ee138cb5544fc8942dc8a6dbf7fcfd54bf3829329075950755b8fea3ba676c430b880b14366dcfc09b66651b06577957e02130c5b4f2a62d7db96d02f1a150c8
7
+ data.tar.gz: 980502d8c285bedf8e2958a24cb77c129ee39f1cfb946c44bbd83f7cc89b30009a829bfb17b515aac9e02d3f3a810b1433cab416aabec67c1daab9c6f100683d
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -1,7 +1,37 @@
1
1
  # Mobility Changelog
2
2
 
3
+ ## Unreleased
4
+ - Assign blank values in pg hash backends
5
+ ([#516](https://github.com/shioyama/mobility/pull/516))
6
+
3
7
  ## 1.1
4
8
 
9
+ ## 1.2
10
+
11
+ ### 1.2.0
12
+ - Add ColumnFallback plugin
13
+ ([#512](https://github.com/shioyama/mobility/pull/512))
14
+ - Fix Sequel querying on untranslated attributes in `i18n` block
15
+ ([#529](https://github.com/shioyama/mobility/pull/529))
16
+ - Allow passing configured backend class as third argument to setup
17
+ ([#528](https://github.com/shioyama/mobility/pull/528))
18
+ - Clearly distinguish backend classes from their configured subclasses
19
+ ([#527](Clearly distinguish backend classes from their configured subclasses))
20
+
21
+ ### 1.1.3
22
+ - Do not swallow keyword args on ruby 3 in fallthrough accessors
23
+ ([#520](https://github.com/shioyama/mobility/pull/520)) thanks
24
+ [doits](https://github.com/doits)!
25
+ - Assign blank values in pg hash backends
26
+ ([#516](https://github.com/shioyama/mobility/pull/516))
27
+
28
+ ### 1.1.2
29
+ - Check whether class responds to mobility_attribute?
30
+ ([#515](https://github.com/shioyama/mobility/pull/515))
31
+
32
+ ### 1.1.1
33
+ - Updated signing key
34
+
5
35
  ### 1.1.0
6
36
  - Remove `Mobility::Plugins::Attributes#each`
7
37
  ([#475](https://github.com/shioyama/mobility/pull/475))
data/Gemfile CHANGED
@@ -12,8 +12,8 @@ group :development, :test do
12
12
  case orm_version
13
13
  when '4.2', '5.0', '5.1', '5.2', '6.0', '6.1'
14
14
  gem 'activerecord', "~> #{orm_version}.0"
15
- when '6.2'
16
- git 'https://github.com/rails/rails.git' do
15
+ when '7.0'
16
+ git 'https://github.com/rails/rails.git', branch: 'main' do
17
17
  gem 'activerecord'
18
18
  gem 'activesupport'
19
19
  end
data/Gemfile.lock CHANGED
@@ -1,31 +1,20 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- mobility (1.0.7)
4
+ mobility (1.2.0.alpha)
5
5
  i18n (>= 0.6.10, < 2)
6
6
  request_store (~> 1.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (6.0.3.4)
12
- activesupport (= 6.0.3.4)
13
- activerecord (6.0.3.4)
14
- activemodel (= 6.0.3.4)
15
- activesupport (= 6.0.3.4)
16
- activesupport (6.0.3.4)
17
- concurrent-ruby (~> 1.0, >= 1.0.2)
18
- i18n (>= 0.7, < 2)
19
- minitest (~> 5.1)
20
- tzinfo (~> 1.1)
21
- zeitwerk (~> 2.2, >= 2.2.2)
22
11
  benchmark-ips (2.8.4)
23
12
  byebug (11.1.3)
24
13
  coderay (1.1.3)
25
- concurrent-ruby (1.1.8)
14
+ concurrent-ruby (1.1.9)
26
15
  database_cleaner (1.99.0)
27
16
  diff-lcs (1.4.4)
28
- ffi (1.14.2)
17
+ ffi (1.15.0)
29
18
  formatador (0.2.5)
30
19
  guard (2.16.2)
31
20
  formatador (>= 0.2.4)
@@ -41,14 +30,13 @@ GEM
41
30
  guard (~> 2.1)
42
31
  guard-compat (~> 1.1)
43
32
  rspec (>= 2.99.0, < 4.0)
44
- i18n (1.8.8)
33
+ i18n (1.8.10)
45
34
  concurrent-ruby (~> 1.0)
46
- listen (3.4.1)
35
+ listen (3.5.1)
47
36
  rb-fsevent (~> 0.10, >= 0.10.3)
48
37
  rb-inotify (~> 0.9, >= 0.9.10)
49
38
  lumberjack (1.2.8)
50
39
  method_source (1.0.0)
51
- minitest (5.14.3)
52
40
  nenv (0.3.0)
53
41
  notiffany (0.1.3)
54
42
  nenv (~> 0.1)
@@ -80,19 +68,15 @@ GEM
80
68
  diff-lcs (>= 1.2.0, < 2.0)
81
69
  rspec-support (~> 3.10.0)
82
70
  rspec-support (3.10.2)
71
+ sequel (5.48.0)
83
72
  shellany (0.0.1)
84
73
  thor (1.1.0)
85
- thread_safe (0.3.6)
86
- tzinfo (1.2.9)
87
- thread_safe (~> 0.1)
88
74
  yard (0.9.26)
89
- zeitwerk (2.4.2)
90
75
 
91
76
  PLATFORMS
92
77
  ruby
93
78
 
94
79
  DEPENDENCIES
95
- activerecord (~> 6.0.0)
96
80
  benchmark-ips
97
81
  database_cleaner (~> 1.5, >= 1.5.3)
98
82
  guard-rspec
@@ -101,6 +85,7 @@ DEPENDENCIES
101
85
  pry-byebug
102
86
  rake (~> 12, >= 12.2.1)
103
87
  rspec (~> 3.0)
88
+ sequel (~> 5.0)
104
89
  yard (~> 0.9.0)
105
90
 
106
91
  BUNDLED WITH
data/README.md CHANGED
@@ -12,7 +12,7 @@ Mobility
12
12
  [docs]: http://www.rubydoc.info/gems/mobility
13
13
  [wiki]: https://github.com/shioyama/mobility/wiki
14
14
 
15
- **This is the readme for version 1.0 of Mobility. If you are using an earlier
15
+ **This is the readme for version 1.x of Mobility. If you are using an earlier
16
16
  version (0.8.x or earlier), you probably want the readme on the [0-8
17
17
  branch](https://github.com/shioyama/mobility/tree/0-8).**
18
18
 
@@ -55,7 +55,7 @@ Installation
55
55
  Add this line to your application's Gemfile:
56
56
 
57
57
  ```ruby
58
- gem 'mobility', '~> 1.1.0'
58
+ gem 'mobility', '~> 1.2.0'
59
59
  ```
60
60
 
61
61
  ### ActiveRecord (Rails)
@@ -130,9 +130,7 @@ default `type` option for the KeyValue backend to `:string`.
130
130
  end
131
131
  ```
132
132
 
133
- We will assume the configuration above in the examples that follow. Other
134
- configuration options are described in the [API
135
- docs](http://www.rubydoc.info/gems/mobility/Mobility/Configuration).
133
+ We will assume the configuration above in the examples that follow.
136
134
 
137
135
  See [Getting Started](#quickstart) to get started translating your models.
138
136
 
@@ -486,9 +484,7 @@ end
486
484
  ```
487
485
 
488
486
  Internally, Mobility assigns the fallbacks hash to an instance of
489
- `I18n::Locale::Fallbacks.new` (this can be customized by setting the
490
- `fallbacks_generator` configuration option, see the [API documentation on
491
- configuration](http://www.rubydoc.info/gems/mobility/Mobility/Configuration)).
487
+ `I18n::Locale::Fallbacks.new`.
492
488
 
493
489
  By setting fallbacks for German and French to Japanese, values will fall
494
490
  through to the Japanese value if none is present for either of these locales,
@@ -1028,6 +1024,9 @@ Integrations
1028
1024
  * [mobility-ransack](https://github.com/shioyama/mobility-ransack): Search
1029
1025
  attributes translated by Mobility with
1030
1026
  [Ransack](https://github.com/activerecord-hackery/ransack).
1027
+ * [mobility-actiontext](https://github.com/sedubois/mobility-actiontext): Translate
1028
+ Rails [Action Text](https://guides.rubyonrails.org/action_text_overview.html) rich text
1029
+ with Mobility.
1031
1030
 
1032
1031
  Tutorials
1033
1032
  ---------
@@ -21,8 +21,8 @@ On top of this, a backend will normally:
21
21
  corresponding to valid keys for configuring this backend.
22
22
  - implement a +configure+ class method to apply any normalization to the
23
23
  keys on the options hash included in +valid_keys+
24
- - call the +setup+ method yielding attributes and options to configure the
25
- model class
24
+ - call the +setup+ method yielding attributes and options (and optionally the
25
+ configured backend class) to configure the model class
26
26
 
27
27
  @example Defining a Backend
28
28
  class MyBackend
@@ -47,6 +47,13 @@ On top of this, a backend will normally:
47
47
  setup do |attributes, options|
48
48
  # Do something with attributes and options in context of model class.
49
49
  end
50
+
51
+ # The block can optionally take the configured backend class as its third
52
+ # argument:
53
+ #
54
+ # setup do |attributes, options, backend_class|
55
+ # ...
56
+ # end
50
57
  end
51
58
 
52
59
  @see Mobility::Translations
@@ -117,7 +124,6 @@ On top of this, a backend will normally:
117
124
  # Extend included class with +setup+ method and other class methods
118
125
  def self.included(base)
119
126
  base.extend ClassMethods
120
- base.singleton_class.attr_reader :options, :model_class
121
127
  end
122
128
 
123
129
  # Defines setup hooks for backend to customize model class.
@@ -136,9 +142,11 @@ On top of this, a backend will normally:
136
142
  def setup &block
137
143
  if @setup_block
138
144
  setup_block = @setup_block
139
- @setup_block = lambda do |*args|
140
- class_exec(*args, &setup_block)
141
- class_exec(*args, &block)
145
+ exec_setup_block = method(:exec_setup_block)
146
+ @setup_block = lambda do |attributes, options, backend_class|
147
+ [setup_block, block].each do |blk|
148
+ exec_setup_block.call(self, attributes, options, backend_class, &blk)
149
+ end
142
150
  end
143
151
  else
144
152
  @setup_block = block
@@ -147,17 +155,6 @@ On top of this, a backend will normally:
147
155
 
148
156
  def inherited(subclass)
149
157
  subclass.instance_variable_set(:@setup_block, @setup_block)
150
- subclass.instance_variable_set(:@options, @options)
151
- subclass.instance_variable_set(:@model_class, @model_class)
152
- end
153
-
154
- # Call setup block on a class with attributes and options.
155
- # @param model_class Class to be setup-ed
156
- # @param [Array<String>] attribute_names
157
- # @param [Hash] options
158
- def setup_model(model_class, attribute_names)
159
- return unless setup_block = @setup_block
160
- model_class.class_exec(attribute_names, options, &setup_block)
161
158
  end
162
159
 
163
160
  # Build a subclass of this backend class for a given set of options
@@ -167,11 +164,7 @@ On top of this, a backend will normally:
167
164
  # @param [Hash] options
168
165
  # @return [Class] backend subclass
169
166
  def build_subclass(model_class, options)
170
- Class.new(self) do
171
- @model_class = model_class
172
- configure(options) if respond_to?(:configure)
173
- @options = options.freeze
174
- end
167
+ ConfiguredBackend.build(self, model_class, options)
175
168
  end
176
169
 
177
170
  # Create instance and class methods to access value on options hash
@@ -188,10 +181,30 @@ On top of this, a backend will normally:
188
181
  EOM
189
182
  end
190
183
 
191
- # Show useful information about this backend class, if it has no name.
192
- # @return [String]
193
- def inspect
194
- name ? super : "#<#{superclass.name}>"
184
+ def options
185
+ raise_unconfigured!(:options)
186
+ end
187
+
188
+ def model_class
189
+ raise_unconfigured!(:model_class)
190
+ end
191
+
192
+ def setup_model(_model_class, _attributes)
193
+ raise_unconfigured!(:setup_model)
194
+ end
195
+
196
+ private
197
+
198
+ def raise_unconfigured!(method_name)
199
+ raise UnconfiguredError, "You are calling #{method_name} on an unconfigured backend class."
200
+ end
201
+
202
+ def exec_setup_block(model_class, *args, &block)
203
+ if block.arity == 3
204
+ model_class.class_exec(*args[0..2], &block)
205
+ else
206
+ model_class.class_exec(*args[0..1], &block)
207
+ end
195
208
  end
196
209
  end
197
210
 
@@ -204,5 +217,48 @@ On top of this, a backend will normally:
204
217
  backend.write(locale, value, options)
205
218
  end
206
219
  end
220
+
221
+ class ConfiguredError < StandardError; end
222
+ class UnconfiguredError < StandardError; end
223
+ =begin
224
+
225
+ Module included in configured backend classes, which in addition to methods on
226
+ the parent backend class also have a +model_class+ and set of +options+.
227
+
228
+ =end
229
+ module ConfiguredBackend
230
+ def self.build(backend_class, model_class, options)
231
+ Class.new(backend_class) do
232
+ extend ConfiguredBackend
233
+
234
+ @model_class = model_class
235
+ configure(options) if respond_to?(:configure)
236
+ @options = options.freeze
237
+ end
238
+ end
239
+
240
+ def self.extended(klass)
241
+ klass.singleton_class.attr_reader :options, :model_class
242
+ end
243
+
244
+ # Call setup block on a class with attributes and options.
245
+ # @param model_class Class to be setup-ed
246
+ # @param [Array<String>] attribute_names
247
+ # @param [Hash] options
248
+ def setup_model(model_class, attribute_names)
249
+ return unless setup_block = @setup_block
250
+ exec_setup_block(model_class, attribute_names, options, self, &setup_block)
251
+ end
252
+
253
+ def inherited(_)
254
+ raise ConfiguredError, "Configured backends cannot be subclassed."
255
+ end
256
+
257
+ # Show subclassed backend class name, if it has one.
258
+ # @return [String]
259
+ def inspect
260
+ (name = superclass.name) ? "#<#{name}>" : super
261
+ end
262
+ end
207
263
  end
208
264
  end
@@ -65,6 +65,69 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
65
65
  end
66
66
  end
67
67
 
68
+ # Called from setup block. Can be overridden to customize behaviour.
69
+ def define_has_many_association(klass, attributes)
70
+ # Track all attributes for this association, so that we can limit the scope
71
+ # of keys for the association to only these attributes. We need to track the
72
+ # attributes assigned to the association in case this setup code is called
73
+ # multiple times, so we don't "forget" earlier attributes.
74
+ #
75
+ attrs_method_name = :"__#{association_name}_attributes"
76
+ association_attributes = (klass.instance_variable_get(:"@#{attrs_method_name}") || []) + attributes
77
+ klass.instance_variable_set(:"@#{attrs_method_name}", association_attributes)
78
+
79
+ b = self
80
+
81
+ klass.has_many association_name, ->{ where b.key_column => association_attributes },
82
+ as: belongs_to,
83
+ class_name: class_name.name,
84
+ inverse_of: belongs_to,
85
+ autosave: true
86
+ end
87
+
88
+ # Called from setup block. Can be overridden to customize behaviour.
89
+ def define_initialize_dup(klass)
90
+ b = self
91
+ module_name = "MobilityArKeyValue#{association_name.to_s.camelcase}"
92
+ unless const_defined?(module_name)
93
+ callback_methods = Module.new do
94
+ define_method :initialize_dup do |source|
95
+ super(source)
96
+ self.send("#{b.association_name}=", source.send(b.association_name).map(&:dup))
97
+ # Set inverse on associations
98
+ send(b.association_name).each do |translation|
99
+ translation.send(:"#{b.belongs_to}=", self)
100
+ end
101
+ end
102
+ end
103
+ klass.include const_set(module_name, callback_methods)
104
+ end
105
+ end
106
+
107
+ # Called from setup block. Can be overridden to customize behaviour.
108
+ def define_before_save_callback(klass)
109
+ b = self
110
+ klass.before_save do
111
+ send(b.association_name).select { |t| t.send(b.value_column).blank? }.each do |translation|
112
+ send(b.association_name).destroy(translation)
113
+ end
114
+ end
115
+ end
116
+
117
+ # Called from setup block. Can be overridden to customize behaviour.
118
+ def define_after_destroy_callback(klass)
119
+ # Ensure we only call after destroy hook once per translations class
120
+ b = self
121
+ translation_classes = [class_name, *Mobility::Backends::ActiveRecord::KeyValue::Translation.descendants].uniq
122
+ klass.after_destroy do
123
+ @mobility_after_destroy_translation_classes = [] unless defined?(@mobility_after_destroy_translation_classes)
124
+ (translation_classes - @mobility_after_destroy_translation_classes).each do |translation_class|
125
+ translation_class.where(b.belongs_to => self).destroy_all
126
+ end
127
+ @mobility_after_destroy_translation_classes += translation_classes
128
+ end
129
+ end
130
+
68
131
  private
69
132
 
70
133
  def join_translations(relation, key, locale, join_type)
@@ -149,55 +212,11 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
149
212
  end
150
213
  end
151
214
 
152
- setup do |attributes, options|
153
- association_name = options[:association_name]
154
- translation_class = options[:class_name]
155
- key_column = options[:key_column]
156
- value_column = options[:value_column]
157
- belongs_to = options[:belongs_to]
158
-
159
- # Track all attributes for this association, so that we can limit the scope
160
- # of keys for the association to only these attributes. We need to track the
161
- # attributes assigned to the association in case this setup code is called
162
- # multiple times, so we don't "forget" earlier attributes.
163
- #
164
- attrs_method_name = :"__#{association_name}_attributes"
165
- association_attributes = (instance_variable_get(:"@#{attrs_method_name}") || []) + attributes
166
- instance_variable_set(:"@#{attrs_method_name}", association_attributes)
167
-
168
- has_many association_name, ->{ where key_column => association_attributes },
169
- as: belongs_to,
170
- class_name: translation_class.name,
171
- inverse_of: belongs_to,
172
- autosave: true
173
- before_save do
174
- send(association_name).select { |t| t.send(value_column).blank? }.each do |translation|
175
- send(association_name).destroy(translation)
176
- end
177
- end
178
-
179
- module_name = "MobilityArKeyValue#{association_name.to_s.camelcase}"
180
- unless const_defined?(module_name)
181
- callback_methods = Module.new do
182
- define_method :initialize_dup do |source|
183
- super(source)
184
- self.send("#{association_name}=", source.send(association_name).map(&:dup))
185
- # Set inverse on associations
186
- send(association_name).each do |translation|
187
- translation.send(:"#{belongs_to}=", self)
188
- end
189
- end
190
- end
191
- include const_set(module_name, callback_methods)
192
- end
193
-
194
- # Ensure we only call after destroy hook once per translations class
195
- translation_classes = [translation_class, *Mobility::Backends::ActiveRecord::KeyValue::Translation.descendants].uniq
196
- after_destroy do
197
- @mobility_after_destroy_translation_classes = [] unless defined?(@mobility_after_destroy_translation_classes)
198
- (translation_classes - @mobility_after_destroy_translation_classes).each { |klass| klass.where(belongs_to => self).destroy_all }
199
- @mobility_after_destroy_translation_classes += translation_classes
200
- end
215
+ setup do |attributes, _options, backend_class|
216
+ backend_class.define_has_many_association(self, attributes)
217
+ backend_class.define_initialize_dup(self)
218
+ backend_class.define_before_save_callback(self)
219
+ backend_class.define_after_destroy_callback(self)
201
220
  end
202
221
 
203
222
  # Returns translation for a given locale, or builds one if none is present.
@@ -32,7 +32,7 @@ Internal class used by ActiveRecord backends backed by a Postgres data type
32
32
  def self.dump(obj)
33
33
  if obj.is_a? ::Hash
34
34
  obj.inject({}) do |translations, (locale, value)|
35
- translations[locale] = value if value.present?
35
+ translations[locale] = value unless value.nil?
36
36
  translations
37
37
  end
38
38
  else
@@ -57,9 +57,7 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
57
57
  end
58
58
  end
59
59
 
60
- backend = self
61
-
62
- setup do |attributes, options|
60
+ setup do |attributes, options, backend_class|
63
61
  column_name = options[:column_name]
64
62
  mod = Module.new do
65
63
  define_method :before_validation do
@@ -71,7 +69,7 @@ Implements the {Mobility::Backends::Container} backend for Sequel models.
71
69
  end
72
70
  end
73
71
  include mod
74
- backend.define_hash_initializer(mod, [column_name])
72
+ backend_class.define_hash_initializer(mod, [column_name])
75
73
 
76
74
  plugin :defaults_setter
77
75
  attributes.each { |attribute| default_values[attribute.to_sym] = {} }
@@ -51,6 +51,63 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
51
51
  end
52
52
  end
53
53
 
54
+ # Called from setup block. Can be overridden to customize behaviour.
55
+ def define_one_to_many_association(klass, attributes)
56
+ belongs_to_id = :"#{belongs_to}_id"
57
+ belongs_to_type = :"#{belongs_to}_type"
58
+
59
+ # Track all attributes for this association, so that we can limit the scope
60
+ # of keys for the association to only these attributes. We need to track the
61
+ # attributes assigned to the association in case this setup code is called
62
+ # multiple times, so we don't "forget" earlier attributes.
63
+ #
64
+ attrs_method_name = :"#{association_name}_attributes"
65
+ association_attributes = (klass.instance_variable_get(:"@#{attrs_method_name}") || []) + attributes
66
+ klass.instance_variable_set(:"@#{attrs_method_name}", association_attributes)
67
+
68
+ klass.one_to_many association_name,
69
+ reciprocal: belongs_to,
70
+ key: belongs_to_id,
71
+ reciprocal_type: :one_to_many,
72
+ conditions: { belongs_to_type => klass.to_s, key_column => association_attributes },
73
+ adder: proc { |translation| translation.update(belongs_to_id => pk, belongs_to_type => self.class.to_s) },
74
+ remover: proc { |translation| translation.update(belongs_to_id => nil, belongs_to_type => nil) },
75
+ clearer: proc { send_(:"#{association_name}_dataset").update(belongs_to_id => nil, belongs_to_type => nil) },
76
+ class: class_name
77
+ end
78
+
79
+ # Called from setup block. Can be overridden to customize behaviour.
80
+ def define_save_callbacks(klass, attributes)
81
+ b = self
82
+ callback_methods = Module.new do
83
+ define_method :before_save do
84
+ super()
85
+ send(b.association_name).select { |t| attributes.include?(t.__send__(b.key_column)) && Util.blank?(t.__send__(b.value_column)) }.each(&:destroy)
86
+ end
87
+ define_method :after_save do
88
+ super()
89
+ attributes.each { |attribute| mobility_backends[attribute].save_translations }
90
+ end
91
+ end
92
+ klass.include callback_methods
93
+ end
94
+
95
+ # Called from setup block. Can be overridden to customize behaviour.
96
+ def define_after_destroy_callback(klass)
97
+ # Clean up *all* leftover translations of this model, only once.
98
+ b = self
99
+ translation_classes = [class_name, *Mobility::Backends::Sequel::KeyValue::Translation.descendants].uniq
100
+ klass.define_method :after_destroy do
101
+ super()
102
+
103
+ @mobility_after_destroy_translation_classes = [] unless defined?(@mobility_after_destroy_translation_classes)
104
+ (translation_classes - @mobility_after_destroy_translation_classes).each do |translation_class|
105
+ translation_class.where(:"#{b.belongs_to}_id" => id, :"#{b.belongs_to}_type" => self.class.name).destroy
106
+ end
107
+ @mobility_after_destroy_translation_classes += translation_classes
108
+ end
109
+ end
110
+
54
111
  private
55
112
 
56
113
  def join_translations(dataset, attr, locale, join_type)
@@ -74,7 +131,7 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
74
131
  visit_sql_identifier(predicate, locale)
75
132
  when ::Sequel::SQL::BooleanExpression
76
133
  visit_boolean(predicate, locale)
77
- when ::Sequel::SQL::Expression
134
+ when ::Sequel::SQL::ComplexExpression
78
135
  visit(predicate.args, locale)
79
136
  else
80
137
  {}
@@ -123,61 +180,13 @@ Implements the {Mobility::Backends::KeyValue} backend for Sequel models.
123
180
  end
124
181
  end
125
182
 
126
- backend = self
127
-
128
- setup do |attributes, options|
129
- association_name = options[:association_name]
130
- translation_class = options[:class_name]
131
- key_column = options[:key_column]
132
- value_column = options[:value_column]
133
- belongs_to = options[:belongs_to]
134
- belongs_to_id = :"#{belongs_to}_id"
135
- belongs_to_type = :"#{belongs_to}_type"
136
-
137
- # Track all attributes for this association, so that we can limit the scope
138
- # of keys for the association to only these attributes. We need to track the
139
- # attributes assigned to the association in case this setup code is called
140
- # multiple times, so we don't "forget" earlier attributes.
141
- #
142
- attrs_method_name = :"#{association_name}_attributes"
143
- association_attributes = (instance_variable_get(:"@#{attrs_method_name}") || []) + attributes
144
- instance_variable_set(:"@#{attrs_method_name}", association_attributes)
145
-
146
- one_to_many association_name,
147
- reciprocal: belongs_to,
148
- key: belongs_to_id,
149
- reciprocal_type: :one_to_many,
150
- conditions: { belongs_to_type => self.to_s, key_column => association_attributes },
151
- adder: proc { |translation| translation.update(belongs_to_id => pk, belongs_to_type => self.class.to_s) },
152
- remover: proc { |translation| translation.update(belongs_to_id => nil, belongs_to_type => nil) },
153
- clearer: proc { send_(:"#{association_name}_dataset").update(belongs_to_id => nil, belongs_to_type => nil) },
154
- class: translation_class
155
-
156
- callback_methods = Module.new do
157
- define_method :before_save do
158
- super()
159
- send(association_name).select { |t| attributes.include?(t.__send__(key_column)) && Util.blank?(t.__send__(value_column)) }.each(&:destroy)
160
- end
161
- define_method :after_save do
162
- super()
163
- attributes.each { |attribute| mobility_backends[attribute].save_translations }
164
- end
165
- end
166
- include callback_methods
167
-
168
- # Clean up *all* leftover translations of this model, only once.
169
- translation_classes = [translation_class, *Mobility::Backends::Sequel::KeyValue::Translation.descendants].uniq
170
- define_method :after_destroy do
171
- super()
183
+ setup do |attributes, _options, backend_class|
184
+ backend_class.define_one_to_many_association(self, attributes)
185
+ backend_class.define_save_callbacks(self, attributes)
186
+ backend_class.define_after_destroy_callback(self)
172
187
 
173
- @mobility_after_destroy_translation_classes = [] unless defined?(@mobility_after_destroy_translation_classes)
174
- (translation_classes - @mobility_after_destroy_translation_classes).each do |klass|
175
- klass.where(belongs_to_id => id, belongs_to_type => self.class.name).destroy
176
- end
177
- @mobility_after_destroy_translation_classes += translation_classes
178
- end
179
188
  include(mod = Module.new)
180
- backend.define_column_changes(mod, attributes)
189
+ backend_class.define_column_changes(mod, attributes)
181
190
  end
182
191
 
183
192
  # Returns translation for a given locale, or initializes one if none is present.
@@ -33,22 +33,20 @@ jsonb).
33
33
  model[column_name.to_sym]
34
34
  end
35
35
 
36
- backend = self
37
-
38
- setup do |attributes, options|
36
+ setup do |attributes, options, backend_class|
39
37
  columns = attributes.map { |attribute| (options[:column_affix] % attribute).to_sym }
40
38
 
41
39
  mod = Module.new do
42
40
  define_method :before_validation do
43
41
  columns.each do |column|
44
- self[column].delete_if { |_, v| Util.blank?(v) }
42
+ self[column].delete_if { |_, v| v.nil? }
45
43
  end
46
44
  super()
47
45
  end
48
46
  end
49
47
  include mod
50
- backend.define_hash_initializer(mod, columns)
51
- backend.define_column_changes(mod, attributes, column_affix: options[:column_affix])
48
+ backend_class.define_hash_initializer(mod, columns)
49
+ backend_class.define_column_changes(mod, attributes, column_affix: options[:column_affix])
52
50
 
53
51
  plugin :defaults_setter
54
52
  columns.each { |column| default_values[column] = {} }
@@ -84,7 +84,7 @@ Implements the {Mobility::Backends::Table} backend for Sequel models.
84
84
  visit_sql_identifier(predicate, locale)
85
85
  when ::Sequel::SQL::BooleanExpression
86
86
  visit_boolean(predicate, locale)
87
- when ::Sequel::SQL::Expression
87
+ when ::Sequel::SQL::ComplexExpression
88
88
  visit(predicate.args, locale)
89
89
  else
90
90
  nil
@@ -116,9 +116,7 @@ Implements the {Mobility::Backends::Table} backend for Sequel models.
116
116
  end
117
117
  end
118
118
 
119
- backend = self
120
-
121
- setup do |attributes, options|
119
+ setup do |attributes, options, backend_class|
122
120
  association_name = options[:association_name]
123
121
  subclass_name = options[:subclass_name]
124
122
 
@@ -155,7 +153,7 @@ Implements the {Mobility::Backends::Table} backend for Sequel models.
155
153
  include callback_methods
156
154
 
157
155
  include(mod = Module.new)
158
- backend.define_column_changes(mod, attributes)
156
+ backend_class.define_column_changes(mod, attributes)
159
157
  end
160
158
 
161
159
  def translation_for(locale, **)
@@ -40,7 +40,7 @@ Format for serialization. Either +:yaml+ (default) or +:json+.
40
40
  return if obj.nil?
41
41
  if obj.is_a? ::Hash
42
42
  obj = obj.inject({}) do |translations, (locale, value)|
43
- translations[locale] = value.to_s if Util.present?(value)
43
+ translations[locale] = value.to_s unless value.nil?
44
44
  translations
45
45
  end
46
46
  else
@@ -0,0 +1,139 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Mobility
4
+ module Plugins
5
+ =begin
6
+
7
+ Plugin to use an original column for a given locale, and otherwise use the backend.
8
+
9
+ =end
10
+ module ActiveRecord
11
+ module ColumnFallback
12
+ extend Plugin
13
+
14
+ requires :column_fallback, include: false
15
+
16
+ included_hook do |_, backend_class|
17
+ case (column_fallback = options[:column_fallback])
18
+ when TrueClass
19
+ backend_class.include I18nDefaultLocaleBackend
20
+ when Array, Proc
21
+ backend_class.include BackendModule.new(column_fallback)
22
+ else
23
+ raise ArgumentError, "column_fallback value must be a boolean, an array of locales or a proc"
24
+ end
25
+ end
26
+
27
+ module I18nDefaultLocaleBackend
28
+ def read(locale, **)
29
+ locale == I18n.default_locale ? model.read_attribute(attribute) : super
30
+ end
31
+
32
+ def write(locale, value, **)
33
+ locale == I18n.default_locale ? model.send(:write_attribute, attribute, value) : super
34
+ end
35
+
36
+ def self.included(base)
37
+ base.extend(ClassMethods)
38
+ end
39
+
40
+ module ClassMethods
41
+ def build_node(attr, locale)
42
+ if locale == I18n.default_locale
43
+ model_class.arel_table[attr]
44
+ else
45
+ super
46
+ end
47
+ end
48
+ end
49
+ end
50
+
51
+ class BackendModule < Module
52
+ def initialize(column_fallback)
53
+ case (@column_fallback = column_fallback)
54
+ when Array
55
+ define_array_accessors
56
+ when Proc
57
+ define_proc_accessors
58
+ end
59
+ end
60
+
61
+ def included(base)
62
+ base.extend(ClassMethods.new(@column_fallback))
63
+ end
64
+
65
+ private
66
+
67
+ def define_array_accessors
68
+ column_fallback = @column_fallback
69
+
70
+ module_eval <<-EOM, __FILE__, __LINE__ + 1
71
+ def read(locale, **)
72
+ if #{column_fallback}.include?(locale)
73
+ model.read_attribute(attribute)
74
+ else
75
+ super
76
+ end
77
+ end
78
+
79
+ def write(locale, value, **)
80
+ if #{column_fallback}.include?(locale)
81
+ model.send(:write_attribute, attribute, value)
82
+ else
83
+ super
84
+ end
85
+ end
86
+ EOM
87
+ end
88
+
89
+ def define_proc_accessors
90
+ column_fallback = @column_fallback
91
+
92
+ define_method :read do |locale, **options|
93
+ if column_fallback.call(locale)
94
+ model.read_attribute(attribute)
95
+ else
96
+ super(locale, **options)
97
+ end
98
+ end
99
+
100
+ define_method :write do |locale, value, **options|
101
+ if column_fallback.call(locale)
102
+ model.send(:write_attribute, attribute, value)
103
+ else
104
+ super(locale, value, **options)
105
+ end
106
+ end
107
+ end
108
+
109
+ class ClassMethods < Module
110
+ def initialize(column_fallback)
111
+ case column_fallback
112
+ when Array
113
+ module_eval <<-EOM, __FILE__, __LINE__ + 1
114
+ def build_node(attr, locale)
115
+ if #{column_fallback}.include?(locale)
116
+ model_class.arel_table[attr]
117
+ else
118
+ super
119
+ end
120
+ end
121
+ EOM
122
+ when Proc
123
+ define_method(:build_node) do |attr, locale|
124
+ if column_fallback.call(locale)
125
+ model_class.arel_table[attr]
126
+ else
127
+ super(attr, locale)
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
136
+
137
+ register_plugin(:active_record_column_fallback, ActiveRecord::ColumnFallback)
138
+ end
139
+ end
@@ -137,6 +137,8 @@ enabled for any one attribute on the model.
137
137
  end
138
138
 
139
139
  def order(opts, *rest)
140
+ return super unless @klass.respond_to?(:mobility_attribute?)
141
+
140
142
  case opts
141
143
  when Symbol, String
142
144
  @klass.mobility_attribute?(opts) ? order({ opts => :asc }, *rest) : super
@@ -161,6 +163,9 @@ enabled for any one attribute on the model.
161
163
  define_method method_name do |*attrs, &block|
162
164
  return super(*attrs, &block) if (method_name == 'select' && block.present?)
163
165
 
166
+ if ::ActiveRecord::VERSION::STRING < '7.0'
167
+ return super(*attrs, &block) unless @klass.respond_to?(:mobility_attribute?)
168
+ end
164
169
  return super(*attrs, &block) unless attrs.any?(&@klass.method(:mobility_attribute?))
165
170
 
166
171
  keys = attrs.dup
@@ -4,6 +4,7 @@ require_relative "./active_record/dirty"
4
4
  require_relative "./active_record/cache"
5
5
  require_relative "./active_record/query"
6
6
  require_relative "./active_record/uniqueness_validation"
7
+ require_relative "./active_record/column_fallback"
7
8
 
8
9
  module Mobility
9
10
  =begin
@@ -24,6 +25,7 @@ dirty for active_record_dirty) is also enabled.
24
25
  requires :active_record_cache
25
26
  requires :active_record_query
26
27
  requires :active_record_uniqueness_validation
28
+ requires :active_record_column_fallback
27
29
 
28
30
 
29
31
  included_hook do |klass|
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mobility
4
+ module Plugins
5
+ module ColumnFallback
6
+ extend Plugin
7
+
8
+ default false
9
+
10
+ requires :backend, include: :before
11
+ end
12
+
13
+ register_plugin(:column_fallback, ColumnFallback)
14
+ end
15
+ end
@@ -55,6 +55,13 @@ model class is generated.
55
55
  end
56
56
  end
57
57
 
58
+ # Following is needed in order to not swallow `kwargs` on ruby >= 3.0.
59
+ # Otherwise `kwargs` are not passed by `super` to a possible other
60
+ # `method_missing` defined like this:
61
+ #
62
+ # def method_missing(name, *args, **kwargs, &block); end
63
+ ruby2_keywords :method_missing
64
+
58
65
  define_method :respond_to_missing? do |method_name, include_private = false|
59
66
  (method_name =~ method_name_regex) || super(method_name, include_private)
60
67
  end
@@ -0,0 +1,133 @@
1
+ # frozen-string-literal: true
2
+
3
+ module Mobility
4
+ =begin
5
+
6
+ Plugin to use an original column for a given locale, and otherwise use the backend.
7
+
8
+ =end
9
+ module Plugins
10
+ module Sequel
11
+ module ColumnFallback
12
+ extend Plugin
13
+
14
+ requires :column_fallback, include: false
15
+
16
+ included_hook do |_, backend_class|
17
+ case (column_fallback = options[:column_fallback])
18
+ when TrueClass
19
+ backend_class.include I18nDefaultLocaleBackend
20
+ when Array, Proc
21
+ backend_class.include BackendModule.new(column_fallback)
22
+ end
23
+ end
24
+
25
+ module I18nDefaultLocaleBackend
26
+ def read(locale, **)
27
+ locale == I18n.default_locale ? model[attribute.to_sym] : super
28
+ end
29
+
30
+ def write(locale, value, **)
31
+ if locale == I18n.default_locale
32
+ model[attribute.to_sym] = value
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def self.included(base)
39
+ base.extend(ClassMethods)
40
+ end
41
+
42
+ module ClassMethods
43
+ def build_op(attr, locale)
44
+ if locale == I18n.default_locale
45
+ ::Sequel::SQL::QualifiedIdentifier.new(model_class.table_name, attr.to_sym)
46
+ else
47
+ super
48
+ end
49
+ end
50
+ end
51
+ end
52
+
53
+ class BackendModule < Module
54
+ def initialize(column_fallback)
55
+ case (@column_fallback = column_fallback)
56
+ when Array
57
+ define_array_accessors
58
+ when Proc
59
+ define_proc_accessors
60
+ end
61
+ end
62
+
63
+ def included(base)
64
+ base.extend(ClassMethods.new(@column_fallback))
65
+ end
66
+
67
+ private
68
+
69
+ def define_array_accessors
70
+ column_fallback = @column_fallback
71
+
72
+ module_eval <<-EOM, __FILE__, __LINE__ + 1
73
+ def read(locale, **)
74
+ #{column_fallback}.include?(locale) ? model[attribute.to_sym] : super
75
+ end
76
+
77
+ def write(locale, value, **)
78
+ if #{column_fallback}.include?(locale)
79
+ model[attribute.to_sym] = value
80
+ else
81
+ super
82
+ end
83
+ end
84
+ EOM
85
+ end
86
+
87
+ def define_proc_accessors
88
+ column_fallback = @column_fallback
89
+
90
+ define_method :read do |locale, **options|
91
+ column_fallback.call(locale) ? model[attribute.to_sym] : super(locale, **options)
92
+ end
93
+
94
+ define_method :write do |locale, value, **options|
95
+ if column_fallback.call(locale)
96
+ model[attribute.to_sym] = value
97
+ else
98
+ super(locale, value, **options)
99
+ end
100
+ end
101
+ end
102
+
103
+ class ClassMethods < Module
104
+ def initialize(column_fallback)
105
+ case column_fallback
106
+ when Array
107
+ module_eval <<-EOM, __FILE__, __LINE__ + 1
108
+ def build_op(attr, locale)
109
+ if #{column_fallback}.include?(locale)
110
+ ::Sequel::SQL::QualifiedIdentifier.new(model_class.table_name, attr.to_sym)
111
+ else
112
+ super
113
+ end
114
+ end
115
+ EOM
116
+ when Proc
117
+ define_method(:build_op) do |attr, locale|
118
+ if column_fallback.call(locale)
119
+ ::Sequel::SQL::QualifiedIdentifier.new(model_class.table_name, attr.to_sym)
120
+ else
121
+ super(attr, locale)
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+
131
+ register_plugin(:sequel_column_fallback, Sequel::ColumnFallback)
132
+ end
133
+ end
@@ -61,7 +61,7 @@ ActiveRecord query plugin.
61
61
  locale = args[0] || @global_locale
62
62
  @locales |= [locale]
63
63
  @model_class.mobility_backend_class(m).build_op(m.to_s, locale)
64
- elsif @model_class.columns.include?(m.to_s)
64
+ elsif @model_class.columns.include?(m)
65
65
  ::Sequel::SQL::QualifiedIdentifier.new(@model_class.table_name, m)
66
66
  else
67
67
  super
@@ -9,6 +9,7 @@ require_relative "./sequel/backend"
9
9
  require_relative "./sequel/dirty"
10
10
  require_relative "./sequel/cache"
11
11
  require_relative "./sequel/query"
12
+ require_relative "./sequel/column_fallback"
12
13
 
13
14
  module Mobility
14
15
  module Plugins
@@ -26,6 +27,7 @@ for sequel_dirty) is also enabled.
26
27
  requires :sequel_dirty
27
28
  requires :sequel_cache
28
29
  requires :sequel_query
30
+ requires :sequel_column_fallback
29
31
 
30
32
  included_hook do |klass|
31
33
  unless sequel_class?(klass)
@@ -7,7 +7,7 @@ module Mobility
7
7
 
8
8
  module VERSION
9
9
  MAJOR = 1
10
- MINOR = 1
10
+ MINOR = 2
11
11
  TINY = 0
12
12
  PRE = nil
13
13
 
data/lib/mobility.rb CHANGED
@@ -73,6 +73,9 @@ fallbacks plugin, whereas +Post+ uses +Translations+ which does not have that
73
73
  plugin enabled.
74
74
 
75
75
  =end
76
+
77
+ def ruby2_keywords(*); end unless respond_to?(:ruby2_keywords, true)
78
+
76
79
  module Mobility
77
80
  # A generic exception used by Mobility.
78
81
  class Error < StandardError
data.tar.gz.sig CHANGED
Binary file
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.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Salzberg
@@ -11,30 +11,30 @@ cert_chain:
11
11
  - |
12
12
  -----BEGIN CERTIFICATE-----
13
13
  MIIEODCCAqCgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhjaHJp
14
- cy9EQz1kZWppbXN0YS9EQz1jb20wHhcNMjAwMjExMDEwMjM1WhcNMjEwMjEwMDEw
15
- MjM1WjAjMSEwHwYDVQQDDBhjaHJpcy9EQz1kZWppbXN0YS9EQz1jb20wggGiMA0G
16
- CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQC99crJF+gE4WQnN7S4xdacGpZWg7hZ
17
- UlXPXM1vX4HVaw8essO6eNGafYqKRQKf3WDW4uM6kqPd4OZTfahGhocVtVScJYGi
18
- 5SRuw9rrJeFlojUkCSqy47on7t858OebbD28eo71sZLTclGmza6UpjiLZqy0AL4P
19
- 9dkK2j9pQJ3jYTNYteq7P6A109ExSGWbaRvkAKU+vTMJsK5MW2bWullsOGHrZiPW
20
- 7PXAaU33X29ddLu/zj/4qe83GVvnrprjw5RRgoQgP0Umw8zKG50XB7nS3TAUiaRz
21
- oD+eKgOIeZpPRwemINf0VsP1L+/FnUS6BkzVCOV9MWhUbrkdxCHLrSB8JL4ooXXR
22
- N/J4KlR5xpv6b+z+i2lScfkrH7r9RF4ZtpiDQzyCxvuIZOQTzUneUSzMIk9BaEN2
23
- 5S19cDUjW5fi75npJ+YnrUN83Ta3sa/Pp4dnUqiBK7WHBDnHMN6j7iASoAjKVTgM
24
- 8F/xjk4qgxA7vjv2obj2zv65CknnQprLCpMCAwEAAaN3MHUwCQYDVR0TBAIwADAL
25
- BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFOO4919GTuKTQA2Klo2QO3jGlbJTMB0GA1Ud
26
- EQQWMBSBEmNocmlzQGRlamltc3RhLmNvbTAdBgNVHRIEFjAUgRJjaHJpc0BkZWpp
27
- bXN0YS5jb20wDQYJKoZIhvcNAQELBQADggGBADfIFBldH77wyUv2RZ1kwvuvRvpL
28
- RNFdQlCbuVSn3abRAmc9rIsh80syhjWjYnml3guf+g2tYB1rU3NeTFRVupdvcUWJ
29
- T6mITUeDHpNoxF6KAp3zSsdoBoEHdOBNH7Jpxp+L3a2LZ0k6fW12xEafmymOD3fp
30
- BmIrE2Vr9aUec2Sk4fbKEYqsxhmXx+o8kKU7tnxVYMv4cX5X3yo45FA7Rh2JQuub
31
- MBT+NALoYFaSTHWIr/4tAolWVt8NNGUKEokaFjjf5gAGM6piq6ohTHl5dCtcEPX1
32
- klHOa2pIFwuUAWoVCpZa9XzRV5qz+mUrU70DF9dX6Cotv/sKOIxiGvQLnwzlSQWH
33
- iXMqkM6Y5FSwViOQy4U2egDDSTB5a16iAnN7/qzqex6SYTsQdSmyc0mWCb9rkIoF
34
- gSQml7TqcC6dZRsZRwYqzD9kUwdAJoCqno2CBUKs2l0yQAjFT36lRrVJznb7uWwa
35
- xpPFnsrtyaZW6Dty8TSG3qzmeGpmpIotA8x1VA==
14
+ cy9EQz1kZWppbWF0YS9EQz1jb20wHhcNMjEwMjE4MTMxMzA5WhcNMjIwMjE4MTMx
15
+ MzA5WjAjMSEwHwYDVQQDDBhjaHJpcy9EQz1kZWppbWF0YS9EQz1jb20wggGiMA0G
16
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDURCKbt5oY0sCp4kYK1u5SLzVHg6Q1
17
+ 2LejeQvUGpR3gulWqrq/507XRxE/9FSpLfgo3cGGYio1/gg2Yp7pBI4ZNEz8d2Vg
18
+ 6caWLHYtHYF0/jlo177UspEF1bt3lCCmaA/ZyQpvoLi76Jf6VCBjepMqhLjeBSsA
19
+ xUqSdgNT8lzduOzdYk/GWf2Trvyz72IN6rY7hSwJ/U4R2DusRNTbKC55iyu0MyqI
20
+ Nks33les0xQERucqes1YzSEnpott/GUQ/fFWV1Qx7M1hMnqbQIm493BueR6X95a2
21
+ B7/aqY7LUVVmn9p65NMBJhbbP/pbAcLYV0C+y1Jy9NaVQTpWmJXVKBpYwlAzOJOQ
22
+ +b/7MBzT5Zzudkq9OlA5rZJB0hFo/Bm38MOCTSTk1/RT+zmoOyb4bx/h400L4ZUt
23
+ bRGON33BZ99gPiYdGfd3Pc/7FooteJASjKIO4Hman2ELRIdu6Bq+fIkTdJBcruS/
24
+ XL6xoRitCG7CX0IqmMKuLiKA/J0amAikHGsCAwEAAaN3MHUwCQYDVR0TBAIwADAL
25
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFMNUGAhS68egZT6DOfJwrfIdCtT/MB0GA1Ud
26
+ EQQWMBSBEmNocmlzQGRlamltYXRhLmNvbTAdBgNVHRIEFjAUgRJjaHJpc0BkZWpp
27
+ bWF0YS5jb20wDQYJKoZIhvcNAQELBQADggGBAH1RnWhD9bum/ijqzAAlkGWYzGza
28
+ h/3seA2bg1r5bbttFjD48f7RepfoAMxAqfiUWcukoukJeu7UY8jWmUIn9ut1oXct
29
+ Fh0YnueLFzzmppCCU+/SX5mc1y7mHYZHiU5n8qy1wJ6ljLWXVeprgJ96NdnmxuVU
30
+ dzPPSDTex/x7xBvHiaPc/uZSLc173N3qdY/Cd0B3/OflYeU2h5UpIHnmXrsONdMC
31
+ Xohy+Rrr2yT09MPYG+llpLHDnXmTnPsOZUSL5Q4c/iolodv4xJZKwLMZwrm2hQl9
32
+ 9Or9Os+qxY0zWxmWuAtTFrskLAMhckCPDEcqSZmW4CT1a/quC2Oh0y1GsXPcqtqt
33
+ hLRuwfTXGor6bg4CrU7GRbSqjvnBepct5lwZiZrOCnMEUpY+9Q8fwmG3o3B+wBsw
34
+ eBMcZq0d1tbtv1M1UXND9mOfhLZ31YvoSTPkrJiRpljUNgD0+ugelnr1/5X/9k8y
35
+ J9QOd3C5jpSShf/HMvpJnFuSYFm19cH9GrHjvw==
36
36
  -----END CERTIFICATE-----
37
- date: 2021-02-06 00:00:00.000000000 Z
37
+ date: 2021-09-26 00:00:00.000000000 Z
38
38
  dependencies:
39
39
  - !ruby/object:Gem::Dependency
40
40
  name: request_store
@@ -198,6 +198,7 @@ files:
198
198
  - lib/mobility/plugins/active_record.rb
199
199
  - lib/mobility/plugins/active_record/backend.rb
200
200
  - lib/mobility/plugins/active_record/cache.rb
201
+ - lib/mobility/plugins/active_record/column_fallback.rb
201
202
  - lib/mobility/plugins/active_record/dirty.rb
202
203
  - lib/mobility/plugins/active_record/query.rb
203
204
  - lib/mobility/plugins/active_record/uniqueness_validation.rb
@@ -209,6 +210,7 @@ files:
209
210
  - lib/mobility/plugins/backend.rb
210
211
  - lib/mobility/plugins/backend_reader.rb
211
212
  - lib/mobility/plugins/cache.rb
213
+ - lib/mobility/plugins/column_fallback.rb
212
214
  - lib/mobility/plugins/default.rb
213
215
  - lib/mobility/plugins/dirty.rb
214
216
  - lib/mobility/plugins/fallbacks.rb
@@ -220,6 +222,7 @@ files:
220
222
  - lib/mobility/plugins/sequel.rb
221
223
  - lib/mobility/plugins/sequel/backend.rb
222
224
  - lib/mobility/plugins/sequel/cache.rb
225
+ - lib/mobility/plugins/sequel/column_fallback.rb
223
226
  - lib/mobility/plugins/sequel/dirty.rb
224
227
  - lib/mobility/plugins/sequel/query.rb
225
228
  - lib/mobility/plugins/writer.rb
metadata.gz.sig CHANGED
Binary file