universalid 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +387 -1094
  3. data/Rakefile +16 -2
  4. data/config/default.yml +1 -1
  5. data/config/example.yml +2 -2
  6. data/lib/universalid/encoder.rb +21 -0
  7. data/lib/universalid/extensions/active_record/base_message_pack_type.rb +15 -0
  8. data/lib/universalid/extensions/active_record/base_packer.rb +170 -0
  9. data/lib/universalid/extensions/active_record/base_unpacker.rb +61 -0
  10. data/lib/universalid/extensions/active_record/relation_message_pack_type.rb +20 -0
  11. data/lib/universalid/extensions/active_support/time_with_zone_message_pack_type.rb +18 -0
  12. data/lib/universalid/extensions/global_id/global_id_model.rb +28 -0
  13. data/lib/universalid/extensions/global_id/global_id_uid_extension.rb +43 -0
  14. data/lib/universalid/extensions/global_id/message_pack_type.rb +16 -0
  15. data/lib/universalid/extensions/signed_global_id/message_pack_type.rb +12 -0
  16. data/lib/{universal_id → universalid}/message_pack_types/ruby/composites/open_struct.rb +2 -0
  17. data/lib/universalid/message_pack_types/ruby/scalars/bigdecimal.rb +10 -0
  18. data/lib/{universal_id → universalid}/message_pack_types/ruby/scalars/date.rb +2 -0
  19. data/lib/{universal_id → universalid}/message_pack_types/ruby/scalars/date_time.rb +2 -0
  20. data/lib/{universal_id → universalid}/message_pack_types.rb +3 -5
  21. data/lib/universalid/packer.rb +19 -0
  22. data/lib/{universal_id → universalid}/prepack_database_options.rb +4 -4
  23. data/lib/{universal_id → universalid}/prepack_options.rb +2 -12
  24. data/lib/{universal_id → universalid}/prepacker.rb +3 -3
  25. data/lib/{universal_id → universalid}/refinements/open_struct_refinement.rb +2 -0
  26. data/lib/universalid/refinements.rb +3 -0
  27. data/lib/{universal_id → universalid}/settings.rb +3 -2
  28. data/lib/{universal_id → universalid}/version.rb +1 -1
  29. data/lib/universalid.rb +28 -1
  30. data/lib/uri/uid.rb +17 -7
  31. metadata +128 -50
  32. data/lib/universal_id/contrib/active_record/base_message_pack_type.rb +0 -11
  33. data/lib/universal_id/contrib/active_record/base_packer.rb +0 -130
  34. data/lib/universal_id/contrib/active_record/base_unpacker.rb +0 -50
  35. data/lib/universal_id/contrib/active_record/relation_message_pack_type.rb +0 -16
  36. data/lib/universal_id/contrib/active_record.rb +0 -4
  37. data/lib/universal_id/contrib/active_support/time_with_zone_message_pack_type.rb +0 -14
  38. data/lib/universal_id/contrib/active_support.rb +0 -3
  39. data/lib/universal_id/contrib/global_id/global_id_model.rb +0 -24
  40. data/lib/universal_id/contrib/global_id/global_id_uid_extension.rb +0 -36
  41. data/lib/universal_id/contrib/global_id/message_pack_type.rb +0 -15
  42. data/lib/universal_id/contrib/global_id.rb +0 -3
  43. data/lib/universal_id/contrib/rails.rb +0 -6
  44. data/lib/universal_id/contrib/signed_global_id/message_pack_type.rb +0 -8
  45. data/lib/universal_id/contrib/signed_global_id.rb +0 -3
  46. data/lib/universal_id/encoder.rb +0 -27
  47. data/lib/universal_id/refinements.rb +0 -8
  48. data/lib/universal_id.rb +0 -29
  49. /data/lib/{universal_id → universalid}/message_pack_factory.rb +0 -0
  50. /data/lib/{universal_id → universalid}/message_pack_types/ruby/composites/module.rb +0 -0
  51. /data/lib/{universal_id → universalid}/message_pack_types/ruby/composites/set.rb +0 -0
  52. /data/lib/{universal_id → universalid}/message_pack_types/ruby/composites/struct.rb +0 -0
  53. /data/lib/{universal_id → universalid}/message_pack_types/ruby/scalars/complex.rb +0 -0
  54. /data/lib/{universal_id → universalid}/message_pack_types/ruby/scalars/range.rb +0 -0
  55. /data/lib/{universal_id → universalid}/message_pack_types/ruby/scalars/rational.rb +0 -0
  56. /data/lib/{universal_id → universalid}/message_pack_types/ruby/scalars/regexp.rb +0 -0
  57. /data/lib/{universal_id → universalid}/message_pack_types/uri/uid/type.rb +0 -0
  58. /data/lib/{universal_id → universalid}/refinements/array_refinement.rb +0 -0
  59. /data/lib/{universal_id → universalid}/refinements/hash_refinement.rb +0 -0
  60. /data/lib/{universal_id → universalid}/refinements/set_refinement.rb +0 -0
data/lib/universalid.rb CHANGED
@@ -1,3 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "universal_id"
3
+ require "active_support/all"
4
+ require "zeitwerk"
5
+
6
+ module UniversalID
7
+ module Extensions; end
8
+
9
+ class << self
10
+ attr_writer :logger
11
+
12
+ def logger
13
+ @logger ||= defined?(Rails) ? Rails.logger : Logger.new(File::NULL)
14
+ end
15
+ end
16
+ end
17
+
18
+ Zeitwerk::Loader.for_gem(warn_on_extra_files: false).tap do |loader|
19
+ loader.inflector = Zeitwerk::GemInflector.new(__dir__)
20
+ loader.ignore "#{__dir__}/universalid/**/*message_pack_type*"
21
+ loader.ignore "#{__dir__}/universalid/extensions"
22
+ loader.inflector.inflect("universalid" => "UniversalID")
23
+ loader.inflector.inflect("uri" => "URI")
24
+ loader.inflector.inflect("uid" => "UID")
25
+ loader.inflector.inflect("version" => "VERSION")
26
+ loader.setup
27
+ loader.eager_load
28
+ end
29
+
30
+ UniversalID::Settings.instance # initialize settings
data/lib/uri/uid.rb CHANGED
@@ -1,12 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "uri"
4
+
3
5
  unless defined?(::URI::UID) || ::URI.scheme_list.include?("UID")
4
6
 
5
7
  module URI
6
8
  class UID < ::URI::Generic
7
9
  VERSION = UniversalID::VERSION
8
10
  SCHEME = "uid"
9
- HOST = "universal-id"
11
+ HOST = "universalid"
10
12
 
11
13
  class << self
12
14
  def encoder
@@ -18,8 +20,13 @@ unless defined?(::URI::UID) || ::URI.scheme_list.include?("UID")
18
20
  end
19
21
 
20
22
  def parse(value)
21
- components = ::URI.split(value.to_s)
22
- new(*components)
23
+ return nil if value.nil?
24
+ return value if value.is_a?(self)
25
+
26
+ value = value.to_s
27
+ return nil if value.strip.empty?
28
+
29
+ new(*::URI.split(value))
23
30
  end
24
31
 
25
32
  def build_string(payload, object = nil)
@@ -87,10 +94,13 @@ unless defined?(::URI::UID) || ::URI.scheme_list.include?("UID")
87
94
  end
88
95
  end
89
96
 
90
- alias_method :fingerprint, :fragment
97
+ def payload
98
+ path[1..]
99
+ end
91
100
 
92
- def payload(truncate: false)
93
- (truncate && path.length > 80) ? "#{path[1..77]}..." : path[1..]
101
+ def fingerprint(decode: false)
102
+ return decode_fingerprint if decode
103
+ fragment
94
104
  end
95
105
 
96
106
  def valid?
@@ -116,7 +126,7 @@ unless defined?(::URI::UID) || ::URI.scheme_list.include?("UID")
116
126
  end
117
127
 
118
128
  def inspect
119
- "#<URI::UID scheme=#{scheme}, host=#{host}, payload=#{payload truncate: true}>"
129
+ "#<URI::UID payload=#{payload.truncate 40}, fingerprint=#{fingerprint.truncate 40}>"
120
130
  end
121
131
 
122
132
  private
metadata CHANGED
@@ -1,15 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: universalid
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nate Hopkins (hopsoft)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-11-17 00:00:00.000000000 Z
11
+ date: 2024-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
13
27
  - !ruby/object:Gem::Dependency
14
28
  name: brotli
15
29
  requirement: !ruby/object:Gem::Requirement
@@ -24,6 +38,20 @@ dependencies:
24
38
  - - ">="
25
39
  - !ruby/object:Gem::Version
26
40
  version: '0.4'
41
+ - !ruby/object:Gem::Dependency
42
+ name: config
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
27
55
  - !ruby/object:Gem::Dependency
28
56
  name: msgpack
29
57
  requirement: !ruby/object:Gem::Requirement
@@ -39,19 +67,33 @@ dependencies:
39
67
  - !ruby/object:Gem::Version
40
68
  version: '1.7'
41
69
  - !ruby/object:Gem::Dependency
42
- name: config
70
+ name: zeitwerk
43
71
  requirement: !ruby/object:Gem::Requirement
44
72
  requirements:
45
73
  - - ">="
46
74
  - !ruby/object:Gem::Version
47
- version: '5.0'
75
+ version: '2.6'
48
76
  type: :runtime
49
77
  prerelease: false
50
78
  version_requirements: !ruby/object:Gem::Requirement
51
79
  requirements:
52
80
  - - ">="
53
81
  - !ruby/object:Gem::Version
54
- version: '5.0'
82
+ version: '2.6'
83
+ - !ruby/object:Gem::Dependency
84
+ name: actionview
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
55
97
  - !ruby/object:Gem::Dependency
56
98
  name: activerecord
57
99
  requirement: !ruby/object:Gem::Requirement
@@ -66,6 +108,20 @@ dependencies:
66
108
  - - ">="
67
109
  - !ruby/object:Gem::Version
68
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: activesupport
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
69
125
  - !ruby/object:Gem::Dependency
70
126
  name: awesome_print
71
127
  requirement: !ruby/object:Gem::Requirement
@@ -108,6 +164,20 @@ dependencies:
108
164
  - - ">="
109
165
  - !ruby/object:Gem::Version
110
166
  version: '1.1'
167
+ - !ruby/object:Gem::Dependency
168
+ name: jbuilder
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :development
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
111
181
  - !ruby/object:Gem::Dependency
112
182
  name: magic_frozen_string_literal
113
183
  requirement: !ruby/object:Gem::Requirement
@@ -150,6 +220,20 @@ dependencies:
150
220
  - - ">="
151
221
  - !ruby/object:Gem::Version
152
222
  version: '0'
223
+ - !ruby/object:Gem::Dependency
224
+ name: oj
225
+ requirement: !ruby/object:Gem::Requirement
226
+ requirements:
227
+ - - ">="
228
+ - !ruby/object:Gem::Version
229
+ version: '0'
230
+ type: :development
231
+ prerelease: false
232
+ version_requirements: !ruby/object:Gem::Requirement
233
+ requirements:
234
+ - - ">="
235
+ - !ruby/object:Gem::Version
236
+ version: '0'
153
237
  - !ruby/object:Gem::Dependency
154
238
  name: pry-byebug
155
239
  requirement: !ruby/object:Gem::Requirement
@@ -249,10 +333,8 @@ dependencies:
249
333
  - !ruby/object:Gem::Version
250
334
  version: '1.32'
251
335
  description: |
252
- Universal ID is a Ruby library that specializes in the serialization of Ruby objects to URL-safe strings,
253
- employing MessagePack and Brotli for optimized encoding. It facilitates efficient data transfer and state
254
- management across various computing processes. Designed to seamlessly integrate with Ruby applications,
255
- it does not rely on Rails-specific dependencies, making it adaptable for diverse Ruby projects.
336
+ Universal ID opens the flood gates with a deluge of profoundly powerful
337
+ yet easily implemented new use-cases for your apps and scripts.
256
338
  email:
257
339
  - natehop@gmail.com
258
340
  executables: []
@@ -263,46 +345,42 @@ files:
263
345
  - Rakefile
264
346
  - config/default.yml
265
347
  - config/example.yml
266
- - lib/universal_id.rb
267
- - lib/universal_id/contrib/active_record.rb
268
- - lib/universal_id/contrib/active_record/base_message_pack_type.rb
269
- - lib/universal_id/contrib/active_record/base_packer.rb
270
- - lib/universal_id/contrib/active_record/base_unpacker.rb
271
- - lib/universal_id/contrib/active_record/relation_message_pack_type.rb
272
- - lib/universal_id/contrib/active_support.rb
273
- - lib/universal_id/contrib/active_support/time_with_zone_message_pack_type.rb
274
- - lib/universal_id/contrib/global_id.rb
275
- - lib/universal_id/contrib/global_id/global_id_model.rb
276
- - lib/universal_id/contrib/global_id/global_id_uid_extension.rb
277
- - lib/universal_id/contrib/global_id/message_pack_type.rb
278
- - lib/universal_id/contrib/rails.rb
279
- - lib/universal_id/contrib/signed_global_id.rb
280
- - lib/universal_id/contrib/signed_global_id/message_pack_type.rb
281
- - lib/universal_id/encoder.rb
282
- - lib/universal_id/message_pack_factory.rb
283
- - lib/universal_id/message_pack_types.rb
284
- - lib/universal_id/message_pack_types/ruby/composites/module.rb
285
- - lib/universal_id/message_pack_types/ruby/composites/open_struct.rb
286
- - lib/universal_id/message_pack_types/ruby/composites/set.rb
287
- - lib/universal_id/message_pack_types/ruby/composites/struct.rb
288
- - lib/universal_id/message_pack_types/ruby/scalars/complex.rb
289
- - lib/universal_id/message_pack_types/ruby/scalars/date.rb
290
- - lib/universal_id/message_pack_types/ruby/scalars/date_time.rb
291
- - lib/universal_id/message_pack_types/ruby/scalars/range.rb
292
- - lib/universal_id/message_pack_types/ruby/scalars/rational.rb
293
- - lib/universal_id/message_pack_types/ruby/scalars/regexp.rb
294
- - lib/universal_id/message_pack_types/uri/uid/type.rb
295
- - lib/universal_id/prepack_database_options.rb
296
- - lib/universal_id/prepack_options.rb
297
- - lib/universal_id/prepacker.rb
298
- - lib/universal_id/refinements.rb
299
- - lib/universal_id/refinements/array_refinement.rb
300
- - lib/universal_id/refinements/hash_refinement.rb
301
- - lib/universal_id/refinements/open_struct_refinement.rb
302
- - lib/universal_id/refinements/set_refinement.rb
303
- - lib/universal_id/settings.rb
304
- - lib/universal_id/version.rb
305
348
  - lib/universalid.rb
349
+ - lib/universalid/encoder.rb
350
+ - lib/universalid/extensions/active_record/base_message_pack_type.rb
351
+ - lib/universalid/extensions/active_record/base_packer.rb
352
+ - lib/universalid/extensions/active_record/base_unpacker.rb
353
+ - lib/universalid/extensions/active_record/relation_message_pack_type.rb
354
+ - lib/universalid/extensions/active_support/time_with_zone_message_pack_type.rb
355
+ - lib/universalid/extensions/global_id/global_id_model.rb
356
+ - lib/universalid/extensions/global_id/global_id_uid_extension.rb
357
+ - lib/universalid/extensions/global_id/message_pack_type.rb
358
+ - lib/universalid/extensions/signed_global_id/message_pack_type.rb
359
+ - lib/universalid/message_pack_factory.rb
360
+ - lib/universalid/message_pack_types.rb
361
+ - lib/universalid/message_pack_types/ruby/composites/module.rb
362
+ - lib/universalid/message_pack_types/ruby/composites/open_struct.rb
363
+ - lib/universalid/message_pack_types/ruby/composites/set.rb
364
+ - lib/universalid/message_pack_types/ruby/composites/struct.rb
365
+ - lib/universalid/message_pack_types/ruby/scalars/bigdecimal.rb
366
+ - lib/universalid/message_pack_types/ruby/scalars/complex.rb
367
+ - lib/universalid/message_pack_types/ruby/scalars/date.rb
368
+ - lib/universalid/message_pack_types/ruby/scalars/date_time.rb
369
+ - lib/universalid/message_pack_types/ruby/scalars/range.rb
370
+ - lib/universalid/message_pack_types/ruby/scalars/rational.rb
371
+ - lib/universalid/message_pack_types/ruby/scalars/regexp.rb
372
+ - lib/universalid/message_pack_types/uri/uid/type.rb
373
+ - lib/universalid/packer.rb
374
+ - lib/universalid/prepack_database_options.rb
375
+ - lib/universalid/prepack_options.rb
376
+ - lib/universalid/prepacker.rb
377
+ - lib/universalid/refinements.rb
378
+ - lib/universalid/refinements/array_refinement.rb
379
+ - lib/universalid/refinements/hash_refinement.rb
380
+ - lib/universalid/refinements/open_struct_refinement.rb
381
+ - lib/universalid/refinements/set_refinement.rb
382
+ - lib/universalid/settings.rb
383
+ - lib/universalid/version.rb
306
384
  - lib/uri/uid.rb
307
385
  homepage: https://github.com/hopsoft/universalid
308
386
  licenses:
@@ -326,8 +404,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
326
404
  - !ruby/object:Gem::Version
327
405
  version: '0'
328
406
  requirements: []
329
- rubygems_version: 3.4.15
407
+ rubygems_version: 3.3.21
330
408
  signing_key:
331
409
  specification_version: 4
332
- summary: URL-Safe String Serialization for any Ruby Object
410
+ summary: Fast, recursive, optimized, URL-Safe serialization for any Ruby object
333
411
  test_files: []
@@ -1,11 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "base_packer"
4
- require_relative "base_unpacker"
5
-
6
- UniversalID::MessagePackFactory.register(
7
- type: ActiveRecord::Base,
8
- recreate_pool: false,
9
- packer: ->(obj, packer) { UniversalID::Contrib::ActiveRecordBasePacker.new(obj).pack_with packer },
10
- unpacker: ->(unpacker) { UniversalID::Contrib::ActiveRecordBaseUnpacker.unpack_with unpacker }
11
- )
@@ -1,130 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class UniversalID::Contrib::ActiveRecordBasePacker
4
- using UniversalID::Refinements::HashRefinement
5
-
6
- # TODO: implement support for has_one
7
- # ActiveRecord::Reflection::HasOneReflection
8
- #
9
- # TODO: implement support for has_and_belongs_to_many
10
- # ActiveRecord::Reflection::HasAndBelongsToManyReflection
11
- #
12
- HAS_MANY_ASSOCIATIONS = [
13
- ActiveRecord::Reflection::HasManyReflection
14
- ]
15
-
16
- DESCENDANTS_KEY = "uid:descendants"
17
-
18
- attr_reader :record
19
-
20
- def initialize(record)
21
- @record = record
22
- end
23
-
24
- def pack_with(packer)
25
- packer.write record.class.name
26
- packer.write packable_attributes
27
- end
28
-
29
- def prepack_options
30
- options = record.instance_variable_get(:@_uid_prepack_options)
31
- options = UniversalID::PrepackOptions.new unless options.is_a?(UniversalID::PrepackOptions)
32
- options
33
- end
34
-
35
- def prepack_database_options
36
- prepack_options.database_options
37
- end
38
-
39
- private
40
-
41
- def packable_attributes
42
- return record.attributes.slice(record.class.primary_key) if id_only?(prepack_database_options)
43
-
44
- hash = record.attributes
45
- reject_keys! hash if prepack_database_options.exclude_keys?
46
- reject_timestamps! hash if prepack_database_options.exclude_timestamps?
47
- reject_unsaved_changes! hash if prepack_database_options.exclude_unsaved_changes?
48
- add_descendants! hash if include_descendants?
49
-
50
- hash.prepack prepack_options
51
- end
52
-
53
- # helpers ..................................................................................................
54
- def id_only?(prepack_database_options)
55
- return false if record.new_record?
56
- return false if prepack_database_options.include_descendants?
57
- prepack_database_options.exclude_unsaved_changes?
58
- end
59
-
60
- def include_descendants?
61
- return false unless prepack_database_options.include_descendants?
62
-
63
- max_depth = prepack_database_options.descendant_depth.to_i
64
- record_depth = record.instance_variable_get(:@_uid_depth).to_i
65
- record_depth < max_depth
66
- end
67
-
68
- # attribute mutators .......................................................................................
69
-
70
- def reject_keys!(hash)
71
- hash.delete record.class.primary_key
72
- foreign_key_column_names.each { |key| hash.delete key }
73
- end
74
-
75
- def reject_timestamps!(hash)
76
- timestamp_column_names.each { |key| hash.delete key }
77
- end
78
-
79
- def reject_unsaved_changes!(hash)
80
- record.changes_to_save.each do |key, (original_value, _)|
81
- hash[key] = original_value
82
- end
83
- end
84
-
85
- def add_descendants!(hash)
86
- hash[DESCENDANTS_KEY] ||= {}
87
-
88
- loaded_has_many_relations_by_name.each do |name, relation|
89
- descendants = relation.map do |descendant|
90
- descendant.instance_variable_set(:@_uid_depth, prepack_database_options.current_depth + 1)
91
- UniversalID::Encoder.encode descendant, prepack_options
92
- ensure
93
- prepack_database_options.decrement_current_depth!
94
- descendant.remove_instance_variable :@_uid_depth
95
- end
96
- hash[DESCENDANTS_KEY][name] = descendants
97
- end
98
-
99
- prepack_database_options.increment_current_depth!
100
- end
101
-
102
- # active record helpers ....................................................................................
103
-
104
- def timestamp_column_names
105
- record.class.all_timestamp_attributes_in_model
106
- end
107
-
108
- def foreign_key_column_names
109
- record.class.reflections
110
- .each_with_object([]) do |(name, reflection), memo|
111
- memo << reflection.foreign_key if reflection.macro == :belongs_to
112
- end
113
- end
114
-
115
- def associations
116
- record.class.reflect_on_all_associations
117
- end
118
-
119
- def has_many_associations
120
- associations.select { |a| HAS_MANY_ASSOCIATIONS.include? a.class }
121
- end
122
-
123
- def loaded_has_many_relations_by_name
124
- has_many_associations.each_with_object({}) do |association, memo|
125
- relation = record.public_send(association.name)
126
- next unless relation.loaded?
127
- memo[association.name] = relation
128
- end
129
- end
130
- end
@@ -1,50 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class UniversalID::Contrib::ActiveRecordBaseUnpacker
4
- class << self
5
- def unpack_with(unpacker)
6
- class_name = unpacker.read
7
- attributes = unpacker.read || {}
8
- create_instance class_name, attributes
9
- end
10
-
11
- private
12
-
13
- def create_instance(class_name, attributes)
14
- klass = Object.const_get(class_name) if Object.const_defined?(class_name)
15
- return nil unless klass
16
-
17
- record = if attributes[klass.primary_key]
18
- klass.find_by(klass.primary_key => attributes[klass.primary_key])
19
- else
20
- klass.new
21
- end
22
-
23
- assign_attributes record, attributes
24
- assign_descendants record, attributes
25
-
26
- record
27
- end
28
-
29
- def assign_attributes(record, attributes)
30
- attributes.each do |key, value|
31
- record.public_send "#{key}=", value if record.respond_to? "#{key}="
32
- end
33
- end
34
-
35
- def assign_descendants(record, attributes)
36
- descendants = attributes[UniversalID::Contrib::ActiveRecordBasePacker::DESCENDANTS_KEY] || {}
37
- descendants.each do |name, list|
38
- next unless record.respond_to?(name) && record.respond_to?("#{name}=")
39
-
40
- models = list.map { |encoded| UniversalID::Encoder.decode encoded }
41
- models.compact!
42
- next unless models.any?
43
-
44
- # NOTE: ActiveRecord is smart enough to not re-create or re-add
45
- # existing records for has_many associations
46
- record.public_send "#{name}=", models
47
- end
48
- end
49
- end
50
- end
@@ -1,16 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # TODO: Revisit ActiveRecord::Relation serialization strategy,
4
- # and attempt to optimize without falling back to Marshal.dump/load
5
- UniversalID::MessagePackFactory.register(
6
- type: ActiveRecord::Relation,
7
- recreate_pool: false,
8
- packer: ->(obj, packer) do
9
- # NOTE: packing a relation will reset the loaded state and internal cache of the relation
10
- # this ensures minimal payload size
11
- obj = obj.dup # clear internal cached state (loaded results, etc.)
12
- obj.reset # dup should clear any internal caching, but we call reset just in case
13
- packer.write Marshal.dump(obj)
14
- end,
15
- unpacker: ->(unpacker) { Marshal.load unpacker.read }
16
- )
@@ -1,4 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "active_record/base_message_pack_type"
4
- require_relative "active_record/relation_message_pack_type"
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- UniversalID::MessagePackFactory.register(
4
- type: ActiveSupport::TimeWithZone,
5
- packer: ->(obj, packer) do
6
- packer.write obj.iso8601(9)
7
- packer.write obj.zone
8
- end,
9
- unpacker: ->(unpacker) do
10
- time = Time.parse(unpacker.read)
11
- zone = unpacker.read
12
- ActiveSupport::TimeWithZone.new time, ActiveSupport::TimeZone[zone]
13
- end
14
- )
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "active_support/time_with_zone_message_pack_type"
@@ -1,24 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class UniversalID::Contrib::GlobalIDModel
4
- include GlobalID::Identification
5
-
6
- def self.find(value)
7
- new value
8
- end
9
-
10
- attr_reader :id, :uid
11
-
12
- def initialize(universal_id)
13
- @uid = case universal_id
14
- when URI::UID then universal_id
15
- when String
16
- case universal_id
17
- when /\A#{URI::UID::SCHEME}/o then URI::UID.parse(universal_id)
18
- else URI::UID.parse(URI::UID.build_string(universal_id, self))
19
- end
20
- end
21
-
22
- @id = @uid&.payload
23
- end
24
- end
@@ -1,36 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UniversalID::Contrib::GlobalIDUIDExtension
4
- extend Forwardable
5
-
6
- def self.included(mixer)
7
- mixer.extend ClassMethods
8
- end
9
-
10
- # Adds all GlobalID::Identification methods
11
- def_delegators(:to_global_id_model, *GlobalID::Identification.instance_methods(false))
12
-
13
- # Returns a UniversalID::Contrib::GlobalIDModel instance
14
- # which implements the GlobalID::Identification interface/protocol
15
- def to_global_id_model
16
- UniversalID::Contrib::GlobalIDModel.new self
17
- end
18
-
19
- module ClassMethods
20
- def from_global_id_record(gid_record)
21
- gid_record&.find&.uid
22
- end
23
-
24
- def from_global_id(gid, options = {})
25
- from_global_id_record GlobalID.parse(gid, options)
26
- end
27
-
28
- alias_method :from_gid, :from_global_id
29
-
30
- def from_signed_global_id(sgid, options = {})
31
- from_global_id_record SignedGlobalID.parse(sgid, options)
32
- end
33
-
34
- alias_method :from_sgid, :from_signed_global_id
35
- end
36
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module UniversalID::Contrib::GlobalID; end
4
-
5
- require_relative "global_id_model"
6
- require_relative "global_id_uid_extension"
7
-
8
- URI::UID.include UniversalID::Contrib::GlobalIDUIDExtension
9
-
10
- UniversalID::MessagePackFactory.register(
11
- type: GlobalID,
12
- recreate_pool: false,
13
- packer: ->(obj, packer) { packer.write obj.to_param },
14
- unpacker: ->(unpacker) { GlobalID.parse unpacker.read }
15
- )
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "global_id/message_pack_type"
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative "active_record" if defined? ActiveRecord
4
- require_relative "active_support" if defined? ActiveSupport
5
- require_relative "global_id" if defined? GlobalID
6
- require_relative "signed_global_id" if defined? SignedGlobalID
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- UniversalID::MessagePackFactory.register(
4
- type: SignedGlobalID,
5
- recreate_pool: false,
6
- packer: ->(obj, packer) { packer.write obj.to_param },
7
- unpacker: ->(unpacker) { SignedGlobalID.parse unpacker.read }
8
- )