universalid 0.1.0 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +297 -73
- data/{contrib → lib/universal_id/contrib}/active_record/base_unpacker.rb +1 -3
- data/lib/universal_id/contrib/active_record.rb +4 -0
- data/lib/universal_id/contrib/active_support.rb +3 -0
- data/{contrib → lib/universal_id/contrib}/global_id/global_id_model.rb +1 -1
- data/lib/universal_id/contrib/global_id.rb +3 -0
- data/lib/universal_id/contrib/rails.rb +6 -0
- data/lib/universal_id/contrib/signed_global_id.rb +3 -0
- data/lib/universal_id/message_pack_factory.rb +20 -6
- data/lib/universal_id/message_pack_types/ruby/composites/module.rb +11 -0
- data/lib/universal_id/message_pack_types/ruby/composites/struct.rb +7 -7
- data/lib/universal_id/message_pack_types/ruby/scalars/complex.rb +1 -1
- data/lib/universal_id/message_pack_types/ruby/scalars/date.rb +1 -1
- data/lib/universal_id/message_pack_types/ruby/scalars/date_time.rb +1 -1
- data/lib/universal_id/message_pack_types/ruby/scalars/range.rb +1 -1
- data/lib/universal_id/message_pack_types/ruby/scalars/rational.rb +1 -1
- data/lib/universal_id/message_pack_types/ruby/scalars/regexp.rb +1 -1
- data/lib/universal_id/message_pack_types.rb +18 -19
- data/lib/universal_id/prepacker.rb +0 -3
- data/lib/universal_id/refinements.rb +0 -1
- data/lib/universal_id/version.rb +1 -1
- data/lib/universal_id.rb +3 -0
- data/lib/uri/uid.rb +57 -10
- metadata +18 -19
- data/contrib/active_record.rb +0 -8
- data/contrib/active_support.rb +0 -7
- data/contrib/global_id.rb +0 -7
- data/contrib/signed_global_id.rb +0 -7
- data/contrib/tags +0 -75
- data/lib/universal_id/contrib.rb +0 -14
- data/lib/universal_id/refinements/kernel_refinement.rb +0 -19
- /data/{contrib → lib/universal_id/contrib}/active_record/base_message_pack_type.rb +0 -0
- /data/{contrib → lib/universal_id/contrib}/active_record/base_packer.rb +0 -0
- /data/{contrib → lib/universal_id/contrib}/active_record/relation_message_pack_type.rb +0 -0
- /data/{contrib → lib/universal_id/contrib}/active_support/time_with_zone_message_pack_type.rb +0 -0
- /data/{contrib → lib/universal_id/contrib}/global_id/global_id_uid_extension.rb +0 -0
- /data/{contrib → lib/universal_id/contrib}/global_id/message_pack_type.rb +0 -0
- /data/{contrib → lib/universal_id/contrib}/signed_global_id/message_pack_type.rb +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: da76bb6c2a7189ce9dfdd3c51e823bd4953d4e808d87f19bf3454071b6b12b38
|
4
|
+
data.tar.gz: 9e5e859338c65f59f6a2db08c7c518591b234ff2351a3e23ecfa34044d6443a3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eaa7ecb09b580b5aa197f3ae806027ea7a403b141617631f4036da0aaf1acd4d6af77a9a0776f45f5d8de192a81445a8d6ca358c6fd3b0bfce0edff31466754e
|
7
|
+
data.tar.gz: e43c45212acf57c0cadfea74b18eeeb2f241efd2b9eced81af3e0013aaa76f605d671122fd8c9b2969a513fde62c1a27427e6823c2aa6b6259c7c41ca540f617
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
<h1 align="center">Universal ID</h1>
|
3
3
|
<p align="center">
|
4
4
|
<a href="http://blog.codinghorror.com/the-best-code-is-no-code-at-all/">
|
5
|
-
<img alt="Lines of Code" src="https://img.shields.io/badge/loc-
|
5
|
+
<img alt="Lines of Code" src="https://img.shields.io/badge/loc-750-47d299.svg" />
|
6
6
|
</a>
|
7
7
|
<a href="https://codeclimate.com/github/hopsoft/universalid/maintainability">
|
8
8
|
<img src="https://api.codeclimate.com/v1/badges/567624cbe733fafc2330/maintainability" />
|
@@ -33,7 +33,7 @@
|
|
33
33
|
<img alt="Twitter Follow" src="https://img.shields.io/twitter/url?label=%40hopsoft&style=social&url=https%3A%2F%2Ftwitter.com%2Fhopsoft">
|
34
34
|
</a>
|
35
35
|
</p>
|
36
|
-
<h2 align="center">URL-Safe Portability for Ruby
|
36
|
+
<h2 align="center">URL-Safe Portability for any Ruby Object</h2>
|
37
37
|
</p>
|
38
38
|
|
39
39
|
**Universal ID introduces a paradigm shift in Ruby development with powerful recursive serialization.**
|
@@ -42,43 +42,151 @@ This innovative library transforms any Ruby object into a URL-safe string, enabl
|
|
42
42
|
It leverages both [MessagePack](https://msgpack.org/) and [Brotli](https://github.com/google/brotli) _(a combo built for speed and best-in-class data compression)_.
|
43
43
|
MessagePack + Brotli is up to 30% faster and within 2-5% compression rates compared to Protobuf. <a title="Source" href="https://g.co/bard/share/e5bdb17aee91">↗</a>
|
44
44
|
|
45
|
-
## Example Use Cases
|
46
|
-
|
47
|
-
- **State Preservation in Web Apps**: Maintain the state of a user's session in web applications without storing data server-side
|
48
|
-
- **API Data Transfer**: Serialize complex data structures into a URI format for easy and efficient transfer via RESTful APIs
|
49
|
-
- **Bookmarkable Configurations**: Allow users to bookmark configurations of a web application by embedding the state in the URL
|
50
|
-
- **Deep Linking in Web Apps**: Create deep links that carry complex state information, allowing users to return to a specific state within an application
|
51
|
-
- **Debugging Tools**: Serialize objects and their state for logging purposes, aiding in debugging and error tracking
|
52
|
-
- **Shareable Reports and Views**: Encode the state of reports or customized views in web applications, making them shareable
|
53
|
-
- **Inter-Service Communication**: Facilitate communication between different services by passing complex objects in a standardized, URL-safe format
|
54
|
-
- **Client-Side Storage Optimization**: Reduce the need for client-side storage by keeping serialized state in URLs or Cookies
|
55
|
-
- **Versioning Serialized Objects**: Enable versioning of serialized objects in URLs, allowing users to access different states or versions of data
|
56
|
-
- **Data Export/Import**: Simplify the export and import process of complex objects between different environments or systems by using URI-encoded data
|
57
|
-
|
58
|
-
This is just a fraction of what's possible with Universal ID. It's an invaluable tool for a range of development needs. API design, data management, user experience, and more. **Endless possibilities!**
|
59
|
-
|
60
45
|
<!-- Tocer[start]: Auto-generated, don't remove. -->
|
61
46
|
|
62
47
|
## Table of Contents
|
63
48
|
|
49
|
+
- [Example Use Cases](#example-use-cases)
|
64
50
|
- [Supported Data Types](#supported-data-types)
|
65
51
|
- [Scalars](#scalars)
|
66
52
|
- [Composites](#composites)
|
67
|
-
- [
|
68
|
-
|
69
|
-
- [Custom Datatypes](#custom-datatypes)
|
53
|
+
- [Custom Types](#custom-types)
|
54
|
+
- [Contributed Types](#contributed-types)
|
70
55
|
- [Settings and Prepack Options](#settings-and-prepack-options)
|
71
56
|
- [Advanced ActiveRecord](#advanced-activerecord)
|
72
57
|
- [ActiveRecord::Relation Support](#activerecordrelation-support)
|
73
58
|
- [SignedGlobalID](#signedglobalid)
|
59
|
+
- [Fingerprinting (Implicit Versioning)](#fingerprinting-implicit-versioning)
|
74
60
|
- [Performance and Benchmarks](#performance-and-benchmarks)
|
75
61
|
- [Sponsors](#sponsors)
|
76
62
|
- [License](#license)
|
77
63
|
|
78
64
|
<!-- Tocer[finish]: Auto-generated, don't remove. -->
|
79
65
|
|
80
|
-
|
66
|
+
## Example Use Cases
|
67
|
+
|
68
|
+
Universal ID's powerful serialization capabilities unlock a myriad of possibilities across various domains.
|
69
|
+
Here are a few possibilities.
|
70
|
+
|
71
|
+
- **State Management for Web Applications**:
|
72
|
+
Facilitate seamless user experiences in web applications by preserving and transferring UI states, even across different sessions.
|
73
|
+
|
74
|
+
- **Data Serialization for Distributed Systems**:
|
75
|
+
Enable efficient communication in distributed systems by serializing complex data structures for network transmission.
|
76
|
+
|
77
|
+
- **Configuration Settings for Software Applications**:
|
78
|
+
Store and manage configuration settings for software applications, allowing easy transfer and versioning of settings across installations.
|
79
|
+
|
80
|
+
- **Session Continuity in Cloud Services**:
|
81
|
+
Ensure continuity of user sessions in cloud-based applications, enabling users to pick up their work exactly where they left off, regardless of the device or location.
|
82
|
+
|
83
|
+
- **Audit Logging for Complex Transactions**:
|
84
|
+
Record detailed states of complex transactions in audit logs, providing a comprehensive and reversible record of actions for compliance and analysis.
|
85
|
+
|
86
|
+
- **Machine-to-Machine Communication**:
|
87
|
+
Standardize data formats for machine-to-machine communication, facilitating interoperability and data exchange in IoT and other automated systems.
|
88
|
+
|
89
|
+
These use cases demonstrate the versatility and power of Universal ID in various application and business scenarios, offering solutions that enhance efficiency, user experience, and system reliability.
|
90
|
+
|
91
|
+
<details>
|
92
|
+
<summary><b>See More Use Cases</b>... ▾</summary>
|
93
|
+
<p></p>
|
94
|
+
|
95
|
+
Harnessing the capabilities of this advanced low-level tool in your libraries and applications might initially seem daunting.
|
96
|
+
To assist you in unlocking its full potential, here are some additional suggestions to help you get started.
|
97
|
+
|
98
|
+
- **API Response Caching**
|
99
|
+
Cache complex API responses as serialized strings, allowing for efficient storage and quick retrieval.
|
100
|
+
|
101
|
+
- **Asset Management in Enterprises**
|
102
|
+
Serialize asset information, including status and location, for efficient tracking and management.
|
103
|
+
|
104
|
+
- **Audit Logging for Financial Transactions**
|
105
|
+
Serialize transaction states for audit trails in financial applications, providing detailed and reversible records for compliance.
|
106
|
+
|
107
|
+
- **Automated Testing of Web Applications**
|
108
|
+
Serialize application states to reproduce and test various scenarios automatically.
|
109
|
+
|
110
|
+
- **Backup and Restore of Application States**
|
111
|
+
Create snapshots of application states that can be backed up and later restored.
|
112
|
+
|
113
|
+
- **Configuration Management in DevOps**
|
114
|
+
Serialize configuration settings for software deployments, enabling easy versioning and rollback.
|
115
|
+
|
116
|
+
- **Content Management Systems (CMS)**
|
117
|
+
Serialize page or post states in CMS, enabling advanced versioning and preview functionalities.
|
118
|
+
|
119
|
+
- **Customer Support Tools**
|
120
|
+
Serialize user issues and their context, helping support teams to quickly understand and resolve customer problems.
|
121
|
+
|
122
|
+
- **Data Migration Between Databases**
|
123
|
+
Serialize entire database records for easy transfer between different database systems or formats.
|
124
|
+
|
125
|
+
- **Educational Platforms**
|
126
|
+
Serialize user progress and states in educational platforms, allowing students to pause and resume their learning activities.
|
127
|
+
|
128
|
+
- **E-commerce Cart Persistence**
|
129
|
+
Serialize shopping cart contents, enabling users to return to a filled cart even after their session expires.
|
130
|
+
|
131
|
+
- **Energy Management Systems**
|
132
|
+
Serialize energy usage data from various sensors for analysis and monitoring.
|
133
|
+
|
134
|
+
- **Environmental Monitoring Systems**
|
135
|
+
Serialize sensor data from environmental monitoring systems for analysis and historical record keeping.
|
136
|
+
|
137
|
+
- **Event Sourcing in Applications**
|
138
|
+
Use serialized states for event sourcing, maintaining an immutable log of state changes over time.
|
139
|
+
|
140
|
+
- **Gaming State Preservation**
|
141
|
+
Store game states as serialized strings, allowing players to resume games exactly where they left off.
|
142
|
+
|
143
|
+
- **Healthcare Data Exchange**
|
144
|
+
Securely transfer patient data between different healthcare systems while maintaining the integrity of complex data structures.
|
145
|
+
|
146
|
+
- **IoT Device State Management**
|
147
|
+
Serialize the state of IoT devices for efficient transmission over networks, aiding in remote monitoring and control.
|
148
|
+
|
149
|
+
- **Legal Document Management**
|
150
|
+
Serialize versions of legal documents, maintaining a trail of edits and changes for auditing.
|
151
|
+
|
152
|
+
- **Machine Learning Data Preparation**
|
153
|
+
Serialize complex data structures used in machine learning pipelines for efficient processing.
|
154
|
+
|
155
|
+
- **Microservice Communication**
|
156
|
+
Serialize complex objects for inter-service communication, ensuring efficient data transfer and reducing the need for complex parsing logic.
|
157
|
+
|
158
|
+
- **Real Estate Portfolio Management**
|
159
|
+
Serialize complex property data for portfolio management and analysis.
|
160
|
+
|
161
|
+
- **Real-time Collaboration Tools**
|
162
|
+
Serialize document or application states for real-time collaboration tools, ensuring consistency across different user sessions.
|
163
|
+
|
164
|
+
- **Research Data Management**
|
165
|
+
Serialize research data and experimental setups for ease of sharing and replication of experiments.
|
166
|
+
|
167
|
+
- **Retail Inventory Management**
|
168
|
+
Serialize inventory data, including details of products, for efficient management and tracking.
|
169
|
+
|
170
|
+
- **Session Continuity Across Devices**
|
171
|
+
Store user session data as a serialized string, enabling users to resume their session on a different device without loss of context.
|
172
|
+
|
173
|
+
- **State Management for Single Page Applications (SPAs)**
|
174
|
+
Serialize UI states into URL-safe strings, enabling bookmarking or sharing of specific application states.
|
81
175
|
|
176
|
+
- **Supply Chain Logistics**
|
177
|
+
Serialize complex logistics and shipment data, aiding in efficient tracking and management.
|
178
|
+
|
179
|
+
- **Telecommunication Network Management**
|
180
|
+
Serialize configurations and states of network devices for efficient management and troubleshooting.
|
181
|
+
|
182
|
+
- **Travel Itinerary Planning**
|
183
|
+
Serialize travel plans and itineraries, allowing users to save and share their travel details easily.
|
184
|
+
|
185
|
+
- **Version Control of Design Files**
|
186
|
+
Serialize design artifacts for version control in graphic design and CAD applications.
|
187
|
+
</details>
|
188
|
+
|
189
|
+
> :rocket: **Ready to Dive In?**: All the code examples below can be tested on your local machine. Simply clone the repo and run `bin/console` to begin exploring. Don't forget to execute `bundle` first to ensure all dependencies are up to date. Happy coding!
|
82
190
|
|
83
191
|
## Supported Data Types
|
84
192
|
|
@@ -93,7 +201,6 @@ Universal ID supports most Ruby primitives.
|
|
93
201
|
- `FalseClass`
|
94
202
|
- `Float`
|
95
203
|
- `Integer`
|
96
|
-
- `NilClass`
|
97
204
|
- `Range`
|
98
205
|
- `Rational`
|
99
206
|
- `Regexp`
|
@@ -216,56 +323,7 @@ Composite support is where things start to get interesting. All of the composite
|
|
216
323
|
```
|
217
324
|
</details>
|
218
325
|
|
219
|
-
###
|
220
|
-
|
221
|
-
> :information_source: **Broad Compatibility**: Universal ID has built-in support for ActiveRecord, yet it maintains independence from Rails-specific dependencies. This versatile design enables integration into **any Ruby project**.
|
222
|
-
|
223
|
-
#### Why Universal ID with ActiveRecord?
|
224
|
-
|
225
|
-
While ActiveRecord already supports GlobalID, a robust library for serializing individual ActiveRecord models, Universal ID extends this functionality to cover a wider range of use cases. Here are a few reasons you may want to consider Universal ID.
|
226
|
-
|
227
|
-
- **Support for New Records**: Unlike GlobalID, Universal ID can serialize models that haven't been saved to the database yet
|
228
|
-
- **Capturing Unsaved Changes**: It can serialize ActiveRecord models with unsaved changes, ensuring that even transient states are captured
|
229
|
-
- **Association Handling**: Universal ID goes beyond single models. It can serialize associated records, including those with unsaved changes, creating a comprehensive snapshot of complex object states
|
230
|
-
- **Cloning Existing Records**: Need to make a copy of a record, including its associations? Universal ID handles this effortlessly, making it ideal for duplicating complex datasets
|
231
|
-
- **Granular Data Control**: With Universal ID, you gain explicit control over the serialization process. You can precisely choose which columns to include or exclude, allowing for tailored, optimized payloads that fit your specific needs
|
232
|
-
- **Efficient Query Serialization**: Universal ID extends its capabilities to ActiveRecord relations, enabling the serialization of complex queries and scopes. This feature allows for seamless sharing of query logic between processes, ensuring consistency and reducing redundancy in data handling tasks.
|
233
|
-
|
234
|
-
In summary, while GlobalID excels in its specific use case, Universal ID offers extended capabilities, particularly useful in scenarios involving unsaved records, complex associations, and data cloning.
|
235
|
-
|
236
|
-
<details>
|
237
|
-
<summary><b>How to Convert Records to UIDs</b>... ▾</summary>
|
238
|
-
<p></p>
|
239
|
-
|
240
|
-
```ruby
|
241
|
-
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
242
|
-
|
243
|
-
ActiveRecord::Schema.define do
|
244
|
-
create_table :campaigns do |t|
|
245
|
-
t.column :name, :string
|
246
|
-
t.timestamps
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
class Campaign < ApplicationRecord
|
251
|
-
end
|
252
|
-
|
253
|
-
# ---
|
254
|
-
|
255
|
-
campaign = Campaign.create(name: "Marketing Campaign")
|
256
|
-
|
257
|
-
uri = URI::UID.build(campaign).to_s
|
258
|
-
#=> "uid://universal-id/CwiAxw4EqENhbXBhaWdugaJpZAMD"
|
259
|
-
|
260
|
-
uid = URI::UID.parse(uri)
|
261
|
-
#=> #<URI::UID uid://universal-id/CwiAxw4EqENhbXBhaWdugaJpZAMD>
|
262
|
-
|
263
|
-
URI::UID.parse(uri).decode
|
264
|
-
##<Campaign:0x000000011cc67da8 id: 1, name: "Marketing Campaign", ...>
|
265
|
-
```
|
266
|
-
</details>
|
267
|
-
|
268
|
-
### Custom Datatypes
|
326
|
+
### Custom Types
|
269
327
|
|
270
328
|
Universal ID is **extensible** so you can register your own datatypes with specialized serialization rules.
|
271
329
|
It couldn't be simpler. Just convert the required data to a Ruby scalar or composite value.
|
@@ -316,6 +374,104 @@ It couldn't be simpler. Just convert the required data to a Ruby scalar or compo
|
|
316
374
|
```
|
317
375
|
</details>
|
318
376
|
|
377
|
+
### Contributed Types
|
378
|
+
|
379
|
+
Universal ID is designed to be highly extensible, allowing for third-party contributions to enhance its capabilities.
|
380
|
+
These contributions can introduce support for additional data types, further broadening the scope of Universal ID’s utility.
|
381
|
+
The following are some notable contrib extensions:
|
382
|
+
|
383
|
+
- **ActiveRecord::Base**:
|
384
|
+
Integrates Universal ID with ActiveRecord base models, enabling intelligent serialization of database records.
|
385
|
+
|
386
|
+
- **ActiveRecord::Relation**:
|
387
|
+
Supports the serialization of ActiveRecord relations, making it possible to encode complex query structures.
|
388
|
+
|
389
|
+
- **ActiveSupport::TimeWithZone**:
|
390
|
+
Adds the ability to serialize ActiveSupport's TimeWithZone objects.
|
391
|
+
|
392
|
+
- **GlobalID**:
|
393
|
+
Extends support to include GlobalIDs.
|
394
|
+
|
395
|
+
- **SignedGlobalID**:
|
396
|
+
Extends support to include SignedGlobalIDs.
|
397
|
+
|
398
|
+
**Requiring Contributed Types**
|
399
|
+
|
400
|
+
To utilize the contributed types, you must explicitly require them in your application.
|
401
|
+
This ensures the extensions are loaded and available for use.
|
402
|
+
Here is an example illustrating how to include contributed types:
|
403
|
+
|
404
|
+
```ruby
|
405
|
+
# load contrib types
|
406
|
+
require "universal_id/contrib/active_record"
|
407
|
+
require "universal_id/contrib/active_support"
|
408
|
+
require "universal_id/contrib/global_id"
|
409
|
+
require "universal_id/contrib/signed_global_id"
|
410
|
+
|
411
|
+
# or simply
|
412
|
+
require "universal_id/contrib/rails"
|
413
|
+
```
|
414
|
+
|
415
|
+
> :bulb: **Implicit Contribs**: Whenever the `Rails` constant is defined, the related contribs are auto-loaded.
|
416
|
+
|
417
|
+
> :bulb: **Broad Compatibility**: Universal ID has built-in support for ActiveRecord, yet it maintains independence from Rails-specific dependencies. This versatile design enables integration into **any Ruby project**.
|
418
|
+
|
419
|
+
**Why Universal ID with ActiveRecord?**
|
420
|
+
|
421
|
+
While ActiveRecord already supports GlobalID, a robust library for serializing individual ActiveRecord models, Universal ID extends this functionality to cover a wider range of use cases. Here are a few reasons you may want to consider Universal ID.
|
422
|
+
|
423
|
+
- **Support for New Records**:
|
424
|
+
Unlike GlobalID, Universal ID can serialize models that haven't been saved to the database yet.
|
425
|
+
|
426
|
+
- **Capturing Unsaved Changes**:
|
427
|
+
It can serialize ActiveRecord models with unsaved changes, ensuring that even transient states are captured.
|
428
|
+
|
429
|
+
- **Association Handling**:
|
430
|
+
Universal ID goes beyond single models. It can serialize associated records, including those with unsaved changes, creating a comprehensive snapshot of complex object states.
|
431
|
+
|
432
|
+
- **Cloning Existing Records**:
|
433
|
+
Need to make a copy of a record, including its associations? Universal ID handles this effortlessly, making it ideal for duplicating complex datasets.
|
434
|
+
|
435
|
+
- **Granular Data Control**:
|
436
|
+
With Universal ID, you gain explicit control over the serialization process. You can precisely choose which columns to include or exclude, allowing for tailored, optimized payloads that fit your specific needs.
|
437
|
+
|
438
|
+
- **Efficient Query Serialization**:
|
439
|
+
Universal ID extends its capabilities to ActiveRecord relations, enabling the serialization of complex queries and scopes. This feature allows for seamless sharing of query logic between processes, ensuring consistency and reducing redundancy in data handling tasks.
|
440
|
+
|
441
|
+
In summary, while GlobalID excels in its specific use case, Universal ID offers extended capabilities, particularly useful in scenarios involving unsaved records, complex associations, and data cloning.
|
442
|
+
|
443
|
+
<details>
|
444
|
+
<summary><b>How to Convert Records to UIDs</b>... ▾</summary>
|
445
|
+
<p></p>
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
|
449
|
+
|
450
|
+
ActiveRecord::Schema.define do
|
451
|
+
create_table :campaigns do |t|
|
452
|
+
t.column :name, :string
|
453
|
+
t.timestamps
|
454
|
+
end
|
455
|
+
end
|
456
|
+
|
457
|
+
class Campaign < ApplicationRecord
|
458
|
+
end
|
459
|
+
|
460
|
+
# ---
|
461
|
+
|
462
|
+
campaign = Campaign.create(name: "Marketing Campaign")
|
463
|
+
|
464
|
+
uri = URI::UID.build(campaign).to_s
|
465
|
+
#=> "uid://universal-id/CwiAxw4EqENhbXBhaWdugaJpZAMD"
|
466
|
+
|
467
|
+
uid = URI::UID.parse(uri)
|
468
|
+
#=> #<URI::UID uid://universal-id/CwiAxw4EqENhbXBhaWdugaJpZAMD>
|
469
|
+
|
470
|
+
URI::UID.parse(uri).decode
|
471
|
+
##<Campaign:0x000000011cc67da8 id: 1, name: "Marketing Campaign", ...>
|
472
|
+
```
|
473
|
+
</details>
|
474
|
+
|
319
475
|
## Settings and Prepack Options
|
320
476
|
|
321
477
|
Universal ID supports a small but powerful set of configuration options for transforming objects before being
|
@@ -446,7 +602,7 @@ It's also possible to register frequently used options as reusable settings to f
|
|
446
602
|
```
|
447
603
|
|
448
604
|
```ruby
|
449
|
-
UniversalID::Settings.register :unsaved,
|
605
|
+
UniversalID::Settings.register :unsaved, File.expand_path("app/config/unsaved.yml", __dir__)
|
450
606
|
URI::UID.build @record, UniversalID::Settings[:small_record]
|
451
607
|
```
|
452
608
|
</details>
|
@@ -828,6 +984,74 @@ simply convert your UniversalID to a SignedGlobalID to add these features to any
|
|
828
984
|
```
|
829
985
|
</details>
|
830
986
|
|
987
|
+
## Fingerprinting (Implicit Versioning)
|
988
|
+
|
989
|
+
Fingerprinting adds an extra layer of intelligence to the serialization process.
|
990
|
+
UIDs automatically include a "fingerprint" for each serialized object based on the target object's class and
|
991
|
+
its modification time _(mtime)_.
|
992
|
+
|
993
|
+
Fingerprints are comprised of the following components:
|
994
|
+
|
995
|
+
1. `Class (Class)` - The encoded object's class
|
996
|
+
2. `Timestamp (Time)` - The mtime (UTC) of the file that defined the object's class
|
997
|
+
|
998
|
+
> :bulb: **Modification Timestamp**: The `mtime` is detected and captured the moment a UID is created.
|
999
|
+
|
1000
|
+
Fingerprints allow developers to manage different versions of serialized data effectively...**without the need for custom versioning**.
|
1001
|
+
Whenever the class definition changes, the mtime updates, resulting in a different fingerprint.
|
1002
|
+
This is especially useful in scenarios where the data format evolves over time, such as in long-lived applications.
|
1003
|
+
|
1004
|
+
<details>
|
1005
|
+
<summary><b>How to Use Fingerprinting</b>... ▾</summary>
|
1006
|
+
<p></p>
|
1007
|
+
|
1008
|
+
1. Build a UID using a custom handler _(optional Ruby block)_. This allows you to take control of the encoding process.
|
1009
|
+
|
1010
|
+
```ruby
|
1011
|
+
# NOTE: The campaign model instance was setup earlier in the "Model Instances" section above
|
1012
|
+
campaign.save!
|
1013
|
+
|
1014
|
+
# the uid build target (campaign in this case)
|
1015
|
+
# |
|
1016
|
+
# | encoding options (whatever was passed to URI::UID.build or {})
|
1017
|
+
# | |
|
1018
|
+
uid = URI::UID.build(campaign) do |record, options|
|
1019
|
+
data = { id: record.id, demo: true }
|
1020
|
+
URI::UID.encode data, options.merge(include: %w[id demo]) # block returns the encoded payload
|
1021
|
+
end
|
1022
|
+
```
|
1023
|
+
|
1024
|
+
2. Decode the UID using a custom handler _(optional Ruby block)_. This allows you to take control of the decoding process.
|
1025
|
+
|
1026
|
+
```ruby
|
1027
|
+
# fingerprint components
|
1028
|
+
# ____|______
|
1029
|
+
# the decoded payload from above | |
|
1030
|
+
# | | |
|
1031
|
+
decoded = URI::UID.parse(uid.to_s).decode do |data, klass, timestamp|
|
1032
|
+
record = klass.find_by(id: data[:id])
|
1033
|
+
record.instance_variable_set(:@demo, data[:demo])
|
1034
|
+
|
1035
|
+
case Time.parse(timestamp)
|
1036
|
+
when 3.months.ago..Time.now
|
1037
|
+
# current data format
|
1038
|
+
# return the record as-is
|
1039
|
+
record
|
1040
|
+
when 1.year.ago..3.months.ago
|
1041
|
+
# outdated data format
|
1042
|
+
# apply an ETL process to bring the outdated data current
|
1043
|
+
# then return the modified record
|
1044
|
+
record
|
1045
|
+
end
|
1046
|
+
end
|
1047
|
+
```
|
1048
|
+
</details>
|
1049
|
+
|
1050
|
+
Fingerprinting allows for seamless handling of different data versions and formats,
|
1051
|
+
so you can maintain consistency and reliability in applications dealing with serialized data over time.
|
1052
|
+
|
1053
|
+
> :bulb: **Optional Usage**: While fingerpint creation is automatic and implicit, using it is optional... ready whenever you want more control.
|
1054
|
+
|
831
1055
|
## Performance and Benchmarks
|
832
1056
|
|
833
1057
|
<details>
|
@@ -1,8 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class UniversalID::Contrib::ActiveRecordBaseUnpacker
|
4
|
-
using UniversalID::Refinements::KernelRefinement
|
5
|
-
|
6
4
|
class << self
|
7
5
|
def unpack_with(unpacker)
|
8
6
|
class_name = unpacker.read
|
@@ -13,7 +11,7 @@ class UniversalID::Contrib::ActiveRecordBaseUnpacker
|
|
13
11
|
private
|
14
12
|
|
15
13
|
def create_instance(class_name, attributes)
|
16
|
-
klass =
|
14
|
+
klass = Object.const_get(class_name) if Object.const_defined?(class_name)
|
17
15
|
return nil unless klass
|
18
16
|
|
19
17
|
record = if attributes[klass.primary_key]
|
@@ -15,7 +15,7 @@ class UniversalID::Contrib::GlobalIDModel
|
|
15
15
|
when String
|
16
16
|
case universal_id
|
17
17
|
when /\A#{URI::UID::SCHEME}/o then URI::UID.parse(universal_id)
|
18
|
-
else URI::UID.parse(URI::UID.build_string(universal_id))
|
18
|
+
else URI::UID.parse(URI::UID.build_string(universal_id, self))
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -0,0 +1,6 @@
|
|
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
|
@@ -11,16 +11,30 @@ UniversalID::MessagePackFactory = MessagePack::Factory.new.tap do |factory|
|
|
11
11
|
@msgpack_pool = UniversalID::MessagePackFactory.pool([Etc.nprocessors.to_i, 1].max)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
id
|
14
|
+
def register_scalar(type:, recreate_pool: true, **options)
|
15
|
+
register id: next_type_id(order: :asc), type: type, **options
|
16
|
+
end
|
17
|
+
|
18
|
+
def register(type:, id: nil, recreate_pool: true, **options)
|
16
19
|
options[:recursive] = true unless options.key?(:recursive)
|
17
|
-
register_type(id, type, options)
|
20
|
+
register_type(id || next_type_id(order: :desc), type, options)
|
18
21
|
create_msgpack_pool if recreate_pool
|
19
22
|
end
|
20
23
|
|
21
|
-
def next_type_id
|
22
|
-
|
23
|
-
|
24
|
+
def next_type_id(order:)
|
25
|
+
range = 0..127
|
26
|
+
|
27
|
+
case order
|
28
|
+
when :asc
|
29
|
+
id = range.first
|
30
|
+
id += 1 while type_registered?(id)
|
31
|
+
when :desc
|
32
|
+
id = range.last
|
33
|
+
id -= 1 while type_registered?(id)
|
34
|
+
end
|
35
|
+
|
36
|
+
id = nil unless range.cover?(id)
|
37
|
+
id
|
24
38
|
end
|
25
39
|
end
|
26
40
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
UniversalID::MessagePackFactory.register(
|
4
|
+
type: Module,
|
5
|
+
recreate_pool: false,
|
6
|
+
packer: ->(obj, packer) { packer.write obj.name },
|
7
|
+
unpacker: ->(unpacker) do
|
8
|
+
name = unpacker.read
|
9
|
+
Object.const_defined?(name) ? Object.const_get(name) : nil
|
10
|
+
end
|
11
|
+
)
|
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
using UniversalID::Refinements::KernelRefinement
|
4
|
-
|
5
3
|
UniversalID::MessagePackFactory.register(
|
6
4
|
type: Struct,
|
7
5
|
recreate_pool: false,
|
@@ -13,11 +11,13 @@ UniversalID::MessagePackFactory.register(
|
|
13
11
|
unpacker: ->(unpacker) do
|
14
12
|
class_name = unpacker.read
|
15
13
|
hash = unpacker.read
|
16
|
-
klass =
|
14
|
+
klass = Object.const_get(class_name) if Object.const_defined?(class_name)
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
16
|
+
if klass
|
17
|
+
# shenanigans to support ::Ruby 3.0.X and 3.1.X
|
18
|
+
RUBY_VERSION.start_with?("3.0", "3.1") ?
|
19
|
+
klass.new.tap { |struct| hash.each { |key, val| struct[key] = hash[key] } } :
|
20
|
+
klass.new(**hash)
|
21
|
+
end
|
22
22
|
end
|
23
23
|
)
|
@@ -1,26 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# IMPORTANT: More specific types should be registered before more general types
|
6
|
-
# because MessagePack will use the first registered type that matches
|
7
|
-
# MessagePack scans registered type in linear order and first match wins
|
3
|
+
# NOTE: MessagePack scans registered type in linear order and first match wins
|
8
4
|
|
9
|
-
|
5
|
+
# scalars
|
6
|
+
require_relative "message_pack_types/ruby/scalars/complex"
|
7
|
+
require_relative "message_pack_types/ruby/scalars/rational"
|
8
|
+
require_relative "message_pack_types/ruby/scalars/date_time"
|
9
|
+
require_relative "message_pack_types/ruby/scalars/date"
|
10
|
+
require_relative "message_pack_types/ruby/scalars/range"
|
11
|
+
require_relative "message_pack_types/ruby/scalars/regexp"
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
message_pack_types/ruby/scalars/complex.rb
|
17
|
-
message_pack_types/ruby/scalars/rational.rb
|
18
|
-
message_pack_types/ruby/scalars/date_time.rb
|
19
|
-
message_pack_types/ruby/scalars/date.rb
|
20
|
-
message_pack_types/ruby/scalars/range.rb
|
21
|
-
message_pack_types/ruby/scalars/regexp.rb
|
22
|
-
]
|
13
|
+
# composites
|
14
|
+
require_relative "message_pack_types/ruby/composites/module"
|
15
|
+
require_relative "message_pack_types/ruby/composites/open_struct"
|
16
|
+
require_relative "message_pack_types/ruby/composites/struct"
|
17
|
+
require_relative "message_pack_types/ruby/composites/set"
|
23
18
|
|
24
|
-
|
19
|
+
# uid
|
20
|
+
require_relative "message_pack_types/uri/uid/type"
|
21
|
+
|
22
|
+
# contribs
|
23
|
+
require_relative "contrib/rails" if defined? Rails
|
25
24
|
|
26
25
|
UniversalID::MessagePackFactory.create_msgpack_pool
|
@@ -1,9 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "refinements"
|
4
|
-
|
5
3
|
class UniversalID::Prepacker
|
6
|
-
using UniversalID::Refinements::KernelRefinement
|
7
4
|
using UniversalID::Refinements::ArrayRefinement
|
8
5
|
using UniversalID::Refinements::HashRefinement
|
9
6
|
using UniversalID::Refinements::SetRefinement
|
data/lib/universal_id/version.rb
CHANGED
data/lib/universal_id.rb
CHANGED
@@ -6,6 +6,7 @@ require "ostruct"
|
|
6
6
|
require "uri"
|
7
7
|
|
8
8
|
require_relative "universal_id/version"
|
9
|
+
require_relative "universal_id/refinements"
|
9
10
|
require_relative "universal_id/settings"
|
10
11
|
require_relative "universal_id/encoder"
|
11
12
|
require_relative "uri/uid"
|
@@ -16,6 +17,8 @@ require_relative "universal_id/message_pack_factory"
|
|
16
17
|
UniversalID::Settings.instance # initialize settings
|
17
18
|
|
18
19
|
module UniversalID
|
20
|
+
module Contrib; end
|
21
|
+
|
19
22
|
class << self
|
20
23
|
attr_writer :logger
|
21
24
|
|
data/lib/uri/uid.rb
CHANGED
@@ -4,24 +4,40 @@ unless defined?(::URI::UID) || ::URI.scheme_list.include?("UID")
|
|
4
4
|
|
5
5
|
module URI
|
6
6
|
class UID < ::URI::Generic
|
7
|
-
|
8
|
-
|
7
|
+
VERSION = UniversalID::VERSION
|
9
8
|
SCHEME = "uid"
|
10
9
|
HOST = "universal-id"
|
11
10
|
|
12
11
|
class << self
|
12
|
+
def encoder
|
13
|
+
UniversalID::Encoder
|
14
|
+
end
|
15
|
+
|
16
|
+
def fingerprint(object)
|
17
|
+
encode fingerprint_components(object)
|
18
|
+
end
|
19
|
+
|
13
20
|
def parse(value)
|
14
21
|
components = ::URI.split(value.to_s)
|
15
22
|
new(*components)
|
16
23
|
end
|
17
24
|
|
18
|
-
def build_string(payload)
|
19
|
-
"#{SCHEME}://#{HOST}/#{payload}"
|
25
|
+
def build_string(payload, object = nil)
|
26
|
+
"#{SCHEME}://#{HOST}/#{payload}##{fingerprint(object)}"
|
20
27
|
end
|
21
28
|
|
22
|
-
def build(object, options = {})
|
23
|
-
path = "/#{
|
24
|
-
parse "#{SCHEME}://#{HOST}#{path}"
|
29
|
+
def build(object, options = {}, &block)
|
30
|
+
path = "/#{encode(object, options, &block)}"
|
31
|
+
parse "#{SCHEME}://#{HOST}#{path}##{fingerprint(object)}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def encode(object, options = {})
|
35
|
+
return yield(object, options) if block_given?
|
36
|
+
encoder.encode object, options
|
37
|
+
end
|
38
|
+
|
39
|
+
def decode(...)
|
40
|
+
encoder.decode(...)
|
25
41
|
end
|
26
42
|
|
27
43
|
# Creates a new URI::UID with the given URI components.
|
@@ -53,15 +69,33 @@ unless defined?(::URI::UID) || ::URI.scheme_list.include?("UID")
|
|
53
69
|
end
|
54
70
|
end
|
55
71
|
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def fingerprint_components(object)
|
76
|
+
klass = object.is_a?(Class) ? object : object.class
|
77
|
+
tokens = [klass]
|
78
|
+
|
79
|
+
begin
|
80
|
+
path = const_source_location(klass.name).first.to_s
|
81
|
+
tokens << ::File.mtime(path).utc if ::File.exist?(path)
|
82
|
+
rescue => e
|
83
|
+
UniversalID.logger&.warn "URI::UID#fingerprint: Unable to determine the source location for #{klass.name}!\n#{e.message}}"
|
84
|
+
end
|
85
|
+
|
86
|
+
tokens
|
87
|
+
end
|
56
88
|
end
|
57
89
|
|
90
|
+
alias_method :fingerprint, :fragment
|
91
|
+
|
58
92
|
def payload(truncate: false)
|
59
93
|
(truncate && path.length > 80) ? "#{path[1..77]}..." : path[1..]
|
60
94
|
end
|
61
95
|
|
62
96
|
def valid?
|
63
97
|
case self
|
64
|
-
in scheme: SCHEME, host: HOST, path: p if p.size >= 8 then return true
|
98
|
+
in scheme: SCHEME, host: HOST, path: p, fragment: _ if p.size >= 8 then return true
|
65
99
|
else false
|
66
100
|
end
|
67
101
|
end
|
@@ -71,16 +105,29 @@ unless defined?(::URI::UID) || ::URI.scheme_list.include?("UID")
|
|
71
105
|
end
|
72
106
|
|
73
107
|
def decode
|
74
|
-
|
108
|
+
return nil unless valid?
|
109
|
+
return yield(decode_payload, *decode_fingerprint) if block_given?
|
110
|
+
|
111
|
+
decode_payload
|
75
112
|
end
|
76
113
|
|
77
114
|
def deconstruct_keys(_keys)
|
78
|
-
{scheme: scheme, host: host, path: path}
|
115
|
+
{scheme: scheme, host: host, path: path, fragment: fragment}
|
79
116
|
end
|
80
117
|
|
81
118
|
def inspect
|
82
119
|
"#<URI::UID scheme=#{scheme}, host=#{host}, payload=#{payload truncate: true}>"
|
83
120
|
end
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def decode_payload
|
125
|
+
self.class.decode payload
|
126
|
+
end
|
127
|
+
|
128
|
+
def decode_fingerprint
|
129
|
+
self.class.decode fingerprint
|
130
|
+
end
|
84
131
|
end
|
85
132
|
|
86
133
|
# Register the URI scheme
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: universalid
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
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-
|
11
|
+
date: 2023-11-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: brotli
|
@@ -263,25 +263,25 @@ files:
|
|
263
263
|
- Rakefile
|
264
264
|
- config/default.yml
|
265
265
|
- config/example.yml
|
266
|
-
- contrib/active_record.rb
|
267
|
-
- contrib/active_record/base_message_pack_type.rb
|
268
|
-
- contrib/active_record/base_packer.rb
|
269
|
-
- contrib/active_record/base_unpacker.rb
|
270
|
-
- contrib/active_record/relation_message_pack_type.rb
|
271
|
-
- contrib/active_support.rb
|
272
|
-
- contrib/active_support/time_with_zone_message_pack_type.rb
|
273
|
-
- contrib/global_id.rb
|
274
|
-
- contrib/global_id/global_id_model.rb
|
275
|
-
- contrib/global_id/global_id_uid_extension.rb
|
276
|
-
- contrib/global_id/message_pack_type.rb
|
277
|
-
- contrib/signed_global_id.rb
|
278
|
-
- contrib/signed_global_id/message_pack_type.rb
|
279
|
-
- contrib/tags
|
280
266
|
- lib/universal_id.rb
|
281
|
-
- lib/universal_id/contrib.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
|
282
281
|
- lib/universal_id/encoder.rb
|
283
282
|
- lib/universal_id/message_pack_factory.rb
|
284
283
|
- lib/universal_id/message_pack_types.rb
|
284
|
+
- lib/universal_id/message_pack_types/ruby/composites/module.rb
|
285
285
|
- lib/universal_id/message_pack_types/ruby/composites/open_struct.rb
|
286
286
|
- lib/universal_id/message_pack_types/ruby/composites/set.rb
|
287
287
|
- lib/universal_id/message_pack_types/ruby/composites/struct.rb
|
@@ -298,7 +298,6 @@ files:
|
|
298
298
|
- lib/universal_id/refinements.rb
|
299
299
|
- lib/universal_id/refinements/array_refinement.rb
|
300
300
|
- lib/universal_id/refinements/hash_refinement.rb
|
301
|
-
- lib/universal_id/refinements/kernel_refinement.rb
|
302
301
|
- lib/universal_id/refinements/open_struct_refinement.rb
|
303
302
|
- lib/universal_id/refinements/set_refinement.rb
|
304
303
|
- lib/universal_id/settings.rb
|
@@ -327,7 +326,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
327
326
|
- !ruby/object:Gem::Version
|
328
327
|
version: '0'
|
329
328
|
requirements: []
|
330
|
-
rubygems_version: 3.
|
329
|
+
rubygems_version: 3.4.15
|
331
330
|
signing_key:
|
332
331
|
specification_version: 4
|
333
332
|
summary: URL-Safe String Serialization for any Ruby Object
|
data/contrib/active_record.rb
DELETED
data/contrib/active_support.rb
DELETED
data/contrib/global_id.rb
DELETED
data/contrib/signed_global_id.rb
DELETED
data/contrib/tags
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
!_TAG_EXTRA_DESCRIPTION anonymous /Include tags for non-named objects like lambda/
|
2
|
-
!_TAG_EXTRA_DESCRIPTION fileScope /Include tags of file scope/
|
3
|
-
!_TAG_EXTRA_DESCRIPTION pseudo /Include pseudo tags/
|
4
|
-
!_TAG_EXTRA_DESCRIPTION subparser /Include tags generated by subparsers/
|
5
|
-
!_TAG_FIELD_DESCRIPTION epoch /the last modified time of the input file (only for F\/file kind tag)/
|
6
|
-
!_TAG_FIELD_DESCRIPTION file /File-restricted scoping/
|
7
|
-
!_TAG_FIELD_DESCRIPTION input /input file/
|
8
|
-
!_TAG_FIELD_DESCRIPTION name /tag name/
|
9
|
-
!_TAG_FIELD_DESCRIPTION pattern /pattern/
|
10
|
-
!_TAG_FIELD_DESCRIPTION typeref /Type and name of a variable or typedef/
|
11
|
-
!_TAG_FIELD_DESCRIPTION!Ruby mixin /how the class or module is mixed in (mixin:HOW:MODULE)/
|
12
|
-
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
13
|
-
!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/
|
14
|
-
!_TAG_KIND_DESCRIPTION!Ruby A,accessor /accessors/
|
15
|
-
!_TAG_KIND_DESCRIPTION!Ruby C,constant /constants/
|
16
|
-
!_TAG_KIND_DESCRIPTION!Ruby L,library /libraries/
|
17
|
-
!_TAG_KIND_DESCRIPTION!Ruby S,singletonMethod /singleton methods/
|
18
|
-
!_TAG_KIND_DESCRIPTION!Ruby a,alias /aliases/
|
19
|
-
!_TAG_KIND_DESCRIPTION!Ruby c,class /classes/
|
20
|
-
!_TAG_KIND_DESCRIPTION!Ruby f,method /methods/
|
21
|
-
!_TAG_KIND_DESCRIPTION!Ruby m,module /modules/
|
22
|
-
!_TAG_OUTPUT_EXCMD mixed /number, pattern, mixed, or combineV2/
|
23
|
-
!_TAG_OUTPUT_FILESEP slash /slash or backslash/
|
24
|
-
!_TAG_OUTPUT_MODE u-ctags /u-ctags or e-ctags/
|
25
|
-
!_TAG_OUTPUT_VERSION 0.0 /current.age/
|
26
|
-
!_TAG_PARSER_VERSION!Ruby 0.0 /current.age/
|
27
|
-
!_TAG_PATTERN_LENGTH_LIMIT 96 /0 for no limit/
|
28
|
-
!_TAG_PROC_CWD /Users/nathan/work/hopsoft/universalid/contrib/ //
|
29
|
-
!_TAG_PROGRAM_AUTHOR Universal Ctags Team //
|
30
|
-
!_TAG_PROGRAM_NAME Universal Ctags /Derived from Exuberant Ctags/
|
31
|
-
!_TAG_PROGRAM_URL https://ctags.io/ /official site/
|
32
|
-
!_TAG_PROGRAM_VERSION 6.0.0 //
|
33
|
-
!_TAG_ROLE_DESCRIPTION!Ruby!library loaded /loaded by "load" method/
|
34
|
-
!_TAG_ROLE_DESCRIPTION!Ruby!library required /loaded by "require" method/
|
35
|
-
!_TAG_ROLE_DESCRIPTION!Ruby!library requiredRel /loaded by "require_relative" method/
|
36
|
-
ActiveRecordPacker active_record/active_record_packer.rb /^class UniversalID::Contrib::ActiveRecordPacker$/;" c module:UniversalID.Contrib
|
37
|
-
ActiveRecordUnpacker active_record/active_record_unpacker.rb /^class UniversalID::Contrib::ActiveRecordUnpacker$/;" c module:UniversalID.Contrib
|
38
|
-
ClassMethods global_id/global_id_uid_extension.rb /^ module ClassMethods$/;" m module:GlobalIDUIDExtension
|
39
|
-
DESCENDANTS_KEY active_record/active_record_packer.rb /^ DESCENDANTS_KEY = "uid:descendants"$/;" C class:ActiveRecordPacker
|
40
|
-
GlobalID global_id/message_pack_type.rb /^module UniversalID::Contrib::GlobalID; end$/;" m module:UniversalID.Contrib
|
41
|
-
GlobalIDModel global_id/global_id_model.rb /^class UniversalID::Contrib::GlobalIDModel$/;" c module:UniversalID.Contrib mixin:include:GlobalID.Identification
|
42
|
-
GlobalIDUIDExtension global_id/global_id_uid_extension.rb /^module UniversalID::Contrib::GlobalIDUIDExtension$/;" m module:UniversalID.Contrib mixin:extend:Forwardable
|
43
|
-
HAS_MANY_ASSOCIATIONS active_record/active_record_packer.rb /^ HAS_MANY_ASSOCIATIONS = [$/;" C class:ActiveRecordPacker
|
44
|
-
add_descendants! active_record/active_record_packer.rb /^ def add_descendants!(hash)$/;" f class:ActiveRecordPacker
|
45
|
-
assign_attributes active_record/active_record_unpacker.rb /^ def assign_attributes(record, attributes)$/;" S class:ActiveRecordUnpacker
|
46
|
-
assign_descendants active_record/active_record_unpacker.rb /^ def assign_descendants(record, attributes)$/;" S class:ActiveRecordUnpacker
|
47
|
-
associations active_record/active_record_packer.rb /^ def associations$/;" f class:ActiveRecordPacker
|
48
|
-
create_instance active_record/active_record_unpacker.rb /^ def create_instance(class_name, attributes)$/;" S class:ActiveRecordUnpacker
|
49
|
-
find global_id/global_id_model.rb /^ def self.find(value)$/;" S class:GlobalIDModel
|
50
|
-
foreign_key_column_names active_record/active_record_packer.rb /^ def foreign_key_column_names$/;" f class:ActiveRecordPacker
|
51
|
-
from_gid global_id/global_id_uid_extension.rb /^ alias_method :from_gid, :from_global_id$/;" a module:GlobalIDUIDExtension.ClassMethods
|
52
|
-
from_global_id global_id/global_id_uid_extension.rb /^ def from_global_id(gid, options = {})$/;" f module:GlobalIDUIDExtension.ClassMethods
|
53
|
-
from_global_id_record global_id/global_id_uid_extension.rb /^ def from_global_id_record(gid_record)$/;" f module:GlobalIDUIDExtension.ClassMethods
|
54
|
-
from_sgid global_id/global_id_uid_extension.rb /^ alias_method :from_sgid, :from_signed_global_id$/;" a module:GlobalIDUIDExtension.ClassMethods
|
55
|
-
from_signed_global_id global_id/global_id_uid_extension.rb /^ def from_signed_global_id(sgid, options = {})$/;" f module:GlobalIDUIDExtension.ClassMethods
|
56
|
-
has_many_associations active_record/active_record_packer.rb /^ def has_many_associations$/;" f class:ActiveRecordPacker
|
57
|
-
id global_id/global_id_model.rb /^ attr_reader :id, :uid$/;" A class:GlobalIDModel
|
58
|
-
id_only? active_record/active_record_packer.rb /^ def id_only?(prepack_database_options)$/;" f class:ActiveRecordPacker
|
59
|
-
include_descendants? active_record/active_record_packer.rb /^ def include_descendants?$/;" f class:ActiveRecordPacker
|
60
|
-
included global_id/global_id_uid_extension.rb /^ def self.included(mixer)$/;" S module:GlobalIDUIDExtension
|
61
|
-
initialize active_record/active_record_packer.rb /^ def initialize(record)$/;" f class:ActiveRecordPacker
|
62
|
-
initialize global_id/global_id_model.rb /^ def initialize(universal_id)$/;" f class:GlobalIDModel
|
63
|
-
loaded_has_many_relations_by_name active_record/active_record_packer.rb /^ def loaded_has_many_relations_by_name$/;" f class:ActiveRecordPacker
|
64
|
-
pack_with active_record/active_record_packer.rb /^ def pack_with(packer)$/;" f class:ActiveRecordPacker
|
65
|
-
packable_attributes active_record/active_record_packer.rb /^ def packable_attributes$/;" f class:ActiveRecordPacker
|
66
|
-
prepack_database_options active_record/active_record_packer.rb /^ def prepack_database_options$/;" f class:ActiveRecordPacker
|
67
|
-
prepack_options active_record/active_record_packer.rb /^ def prepack_options$/;" f class:ActiveRecordPacker
|
68
|
-
record active_record/active_record_packer.rb /^ attr_reader :record$/;" A class:ActiveRecordPacker
|
69
|
-
reject_keys! active_record/active_record_packer.rb /^ def reject_keys!(hash)$/;" f class:ActiveRecordPacker
|
70
|
-
reject_timestamps! active_record/active_record_packer.rb /^ def reject_timestamps!(hash)$/;" f class:ActiveRecordPacker
|
71
|
-
reject_unsaved_changes! active_record/active_record_packer.rb /^ def reject_unsaved_changes!(hash)$/;" f class:ActiveRecordPacker
|
72
|
-
timestamp_column_names active_record/active_record_packer.rb /^ def timestamp_column_names$/;" f class:ActiveRecordPacker
|
73
|
-
to_global_id_model global_id/global_id_uid_extension.rb /^ def to_global_id_model$/;" f module:GlobalIDUIDExtension
|
74
|
-
uid global_id/global_id_model.rb /^ attr_reader :id, :uid$/;" A class:GlobalIDModel
|
75
|
-
unpack_with active_record/active_record_unpacker.rb /^ def unpack_with(unpacker)$/;" S class:ActiveRecordUnpacker
|
data/lib/universal_id/contrib.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module UniversalID::Contrib; end
|
4
|
-
|
5
|
-
# A list of all MessagePack types in the preferred registration order
|
6
|
-
#
|
7
|
-
# IMPORTANT: More specific types should be registered before more general types
|
8
|
-
# because MessagePack will use the first registered type that matches
|
9
|
-
# MessagePack scans registered type in linear order and first match wins
|
10
|
-
|
11
|
-
require_relative "../../contrib/signed_global_id"
|
12
|
-
require_relative "../../contrib/global_id"
|
13
|
-
require_relative "../../contrib/active_support"
|
14
|
-
require_relative "../../contrib/active_record"
|
@@ -1,19 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module UniversalID::Refinements::KernelRefinement
|
4
|
-
refine Kernel do
|
5
|
-
# Finds a constant by name, starting at the root namespace (i.e. ::Object)
|
6
|
-
def const_find(name)
|
7
|
-
return nil unless name.is_a?(String)
|
8
|
-
names = name.split("::")
|
9
|
-
constant = Object
|
10
|
-
|
11
|
-
while names.any?
|
12
|
-
value = names.shift
|
13
|
-
constant = constant.const_get(value) if constant.const_defined?(value)
|
14
|
-
end
|
15
|
-
|
16
|
-
(constant.name == name) ? constant : nil
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
File without changes
|
File without changes
|
File without changes
|
/data/{contrib → lib/universal_id/contrib}/active_support/time_with_zone_message_pack_type.rb
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|