uuids 0.2.0 → 1.0.0.pre.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +6 -3
- data/README.rdoc +64 -73
- data/lib/tasks/uuids_tasks.rake +6 -7
- data/lib/uuids/base.rb +46 -10
- data/lib/uuids/version.rb +1 -1
- data/spec/dummy/app/models/city.rb +5 -0
- data/spec/dummy/db/migrate/20141017081115_create_cities.rb +8 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/test.log +7932 -0
- data/spec/lib/uuids/base_spec.rb +44 -26
- data/spec/support/initializers/coveralls.rb +1 -1
- metadata +8 -8
- data/spec/dummy/app/models/item.rb +0 -4
- data/spec/dummy/db/migrate/20141017081115_create_items.rb +0 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 716ef7b1e74c7adf9fd9d29302aa0ad0b2ba6c74
|
4
|
+
data.tar.gz: 6086c3c5ece7db6730ef17aa814373789ea03189
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bc6c1947993bddd20aae7128f7be6987032bb7018e073a48c841a69ba4208ffdb20b854c2dec71d583a6f95b76ca2b35e944b7567e1050a2210a7946e8cf04af
|
7
|
+
data.tar.gz: 9a663e80d1b08d164eeb9a3ecab76fb5bf3d1051cecb579360bbae7333bf710fa87169d477f829133761012d4694c0665d5bbe555389dec0d9cacc57e3f8e43a
|
data/.rubocop.yml
CHANGED
@@ -11,6 +11,10 @@ Lint/RescueException:
|
|
11
11
|
Exclude:
|
12
12
|
- 'spec/**/*'
|
13
13
|
|
14
|
+
Metrics/MethodLength:
|
15
|
+
Exclude:
|
16
|
+
- 'db/**/*'
|
17
|
+
|
14
18
|
Style/AccessorMethodName:
|
15
19
|
Exclude:
|
16
20
|
- 'spec/**/*'
|
@@ -31,9 +35,8 @@ Style/EmptyLineBetweenDefs:
|
|
31
35
|
Exclude:
|
32
36
|
- 'spec/**/*'
|
33
37
|
|
34
|
-
|
35
|
-
|
36
|
-
- 'db/**/*'
|
38
|
+
Style/PredicateName:
|
39
|
+
Enabled: false
|
37
40
|
|
38
41
|
Style/RaiseArgs:
|
39
42
|
EnforcedStyle: compact
|
data/README.rdoc
CHANGED
@@ -9,53 +9,44 @@
|
|
9
9
|
|
10
10
|
== About
|
11
11
|
|
12
|
-
|
12
|
+
The gem adds addressing ActiveRecord objects by {UUID}[http://en.wikipedia.org/wiki/Universally_Unique_Identifier]s following the {RFC4122}[http://www.ietf.org/rfc/rfc4122.txt]
|
13
|
+
standard.
|
13
14
|
|
14
|
-
It
|
15
|
-
identified by many uuids.
|
16
|
-
|
17
|
-
The gem is a {mountable Rails engine}[http://guides.rubyonrails.org/engines.html#generating-an-engine].
|
18
|
-
|
19
|
-
The gem provides:
|
15
|
+
It provides:
|
20
16
|
|
21
17
|
<tt>Uuids::Uuid</tt>:: A model of UUIDs associated with various records.
|
22
|
-
<tt>Uuids::Base</tt>:: A module
|
18
|
+
<tt>Uuids::Base</tt>:: A module provides ActiveRecord class helpers +has_uuids+ and +has_many+ (with <tt>uuid: true</tt> option).
|
19
|
+
|
20
|
+
The gem is a {mountable Rails engine}[http://guides.rubyonrails.org/engines.html#generating-an-engine].
|
23
21
|
|
24
22
|
=== Pattern
|
25
23
|
|
26
|
-
This model allows
|
24
|
+
This model allows adressing records by some UUID (not the ID).
|
25
|
+
It is expected any UUID is assigned to one record, but a record can be
|
26
|
+
identified by many UUIDs.
|
27
27
|
|
28
28
|
If necessary any referred record can be merged with another one.
|
29
|
-
|
30
|
-
valid
|
31
|
-
|
32
|
-
A uuid should be neither deleted, no changed. It can only be reassigned to
|
33
|
-
another resource. The records can be deleted
|
29
|
+
All you need is to reassign all UUIDs to merged record and outer associations
|
30
|
+
remains valid.
|
34
31
|
|
35
|
-
|
36
|
-
|
32
|
+
A **UUID** should be neither deleted, no changed. It can only be reassigned to
|
33
|
+
another resource. On ther other hand, the outer record should be merged to
|
34
|
+
another one (reassign UUIDs) to prevent existance of UUIDs assigned to nothing.
|
37
35
|
|
38
36
|
=== Example
|
39
37
|
|
40
38
|
Suppose you have models referred to cities. One day you discover
|
41
|
-
a duplication among cities: the "New York" and the "NEW YORK".
|
39
|
+
a duplication among two cities: the "New York" and the "NEW YORK".
|
42
40
|
|
43
41
|
You should:
|
44
42
|
|
45
|
-
* reassign both
|
43
|
+
* reassign both UUIDs to "New York";
|
46
44
|
* safely remove the "NEW YORK" record.
|
47
45
|
|
48
46
|
You needn't track all records that refer to "NEW YORK". All those references
|
49
|
-
will authomatically lead to merged record via old
|
50
|
-
|
51
|
-
=== Standards
|
47
|
+
will authomatically lead to merged record via old UUID.
|
52
48
|
|
53
|
-
|
54
|
-
{RFC4122}[http://www.ietf.org/rfc/rfc4122.txt] standard. The generation uses the
|
55
|
-
+sequrerandom+ Ruby library.
|
56
|
-
|
57
|
-
This allows keeping all uuids in one model and referring to any record whatever
|
58
|
-
type it has.
|
49
|
+
Now the model of cities should **know nothing about outer models** that use it.
|
59
50
|
|
60
51
|
=== Translations
|
61
52
|
|
@@ -76,90 +67,101 @@ Or install it yourself as:
|
|
76
67
|
|
77
68
|
$ gem install uuids
|
78
69
|
|
70
|
+
== Initialization
|
71
|
+
|
72
|
+
To initialize the module you need to copy and run uuid's db migrations.
|
73
|
+
|
79
74
|
=== Rails application
|
80
75
|
|
81
76
|
Run from a command line in application root:
|
82
77
|
|
83
78
|
$ rake uuids:install
|
84
79
|
|
85
|
-
This will copy gem migrations to a `db/migrate` folder and run it.
|
86
|
-
|
87
80
|
=== Rails mountable engine
|
88
81
|
|
89
82
|
Run from a command line in application root:
|
90
83
|
|
91
84
|
$ rake app:uuids:install
|
92
85
|
|
93
|
-
This will copy gem migrations to a `spec/dummy/db/migrate` folder and run it.
|
94
|
-
|
95
86
|
== Usage
|
96
87
|
|
88
|
+
=== Adding UUIDs identifiers
|
89
|
+
|
97
90
|
Add the assotiation to your AR model:
|
98
91
|
|
99
|
-
class
|
92
|
+
class City < ActiveRecord::Base
|
93
|
+
include Uuids::Base
|
94
|
+
has_uuids
|
95
|
+
end
|
100
96
|
|
101
|
-
|
102
|
-
has_many :uuids, class_name: "Uuids::Uuid", as: :record, validate: false
|
97
|
+
This will add methods:
|
103
98
|
|
104
|
-
|
105
|
-
|
99
|
+
+#uuids+:: List of <tt>Uuids::Uuid</tt> objects referred to the record.
|
100
|
+
+#uuid+:: main UUID for the record - a value of the first +uuids+ object.
|
101
|
+
<tt>.by_uuid</tt>:: A scope for unique records by UUID: <tt>City.by_uuid</tt>
|
106
102
|
|
107
|
-
|
108
|
-
|
103
|
+
The first uuid is added by default. It can also be set manually:
|
104
|
+
|
105
|
+
# UUID is generated by default
|
106
|
+
city = City.new
|
107
|
+
city.save!
|
109
108
|
|
110
|
-
|
111
|
-
|
112
|
-
|
109
|
+
# UUID is assigned manually
|
110
|
+
city = City.new
|
111
|
+
city.uuids.new value: "6d9456a9-8f54-4ff7-ba0d-9854f1954417"
|
112
|
+
city.save
|
113
113
|
|
114
|
-
|
114
|
+
The destruction of object is forbidden if it has a +uuid+. You should reassign
|
115
|
+
all object's UUIDs to another object in advance.
|
115
116
|
|
116
|
-
|
117
|
-
include Uuids::Base
|
118
|
-
end
|
117
|
+
=== Referring model by UUID [TODO]
|
119
118
|
|
120
|
-
|
119
|
+
Instead of <tt>ActiveRecord::Associations</tt> +belongs_to+, +has_one+ and
|
120
|
+
+has_many+, you should define custom methods by <tt>ActiveRecord::Relation</tt>
|
121
|
+
explicitly.
|
121
122
|
|
122
|
-
class
|
123
|
+
class CreateStreetsTable < ActiveRecord::Migration
|
123
124
|
def change
|
124
|
-
create_table :
|
125
|
-
t.string :
|
125
|
+
create_table :streets do |t|
|
126
|
+
t.string :city_uuid, limit: 36
|
126
127
|
end
|
127
|
-
add_index :
|
128
|
+
add_index :streets_table, :city_uuid
|
128
129
|
end
|
129
130
|
end
|
130
131
|
|
131
|
-
class
|
132
|
+
class Street < ActiveRecord::Base
|
132
133
|
|
133
|
-
|
134
|
-
|
135
|
-
|
134
|
+
scope :by_city, ->(city) { City.by_uuid(city.uuid) }
|
135
|
+
|
136
|
+
def city
|
137
|
+
@city ||= City.by_uuid(city_uuid)
|
136
138
|
end
|
137
139
|
|
138
|
-
def
|
139
|
-
|
140
|
+
def city=(city)
|
141
|
+
read_attribute :city_uuid, city.uuid
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
143
145
|
== Uninstallation
|
144
146
|
|
147
|
+
To uninstall the module you need to:
|
148
|
+
|
149
|
+
* rollback and remove uuid's migration;
|
150
|
+
* remove all lines containing <tt>include Uuids::Base</tt>, +has_uuids+ and <tt>by_uuid: true</tt> from any model;
|
151
|
+
* remove the gem dependencies from application's +Gemfile+ and gemspec.
|
152
|
+
|
145
153
|
=== Rails app
|
146
154
|
|
147
155
|
Run from a command line in application root:
|
148
156
|
|
149
157
|
$ rake uuids:uninstall
|
150
158
|
|
151
|
-
This will rollback and remove migration from `db/migrate` folder and then
|
152
|
-
remove the gem dependencies from application's +Gemfile+ and gemspec.
|
153
|
-
|
154
159
|
=== Rails mountable engine
|
155
160
|
|
156
161
|
Run from a command line in engine root:
|
157
162
|
|
158
163
|
$ rake app:uuids:uninstall
|
159
164
|
|
160
|
-
This will rollback and remove migration from `spec/dummy/db/migrate` folder and
|
161
|
-
then remove the gem dependencies from engine's +Gemfile+ and gemspec.
|
162
|
-
|
163
165
|
== Contributing
|
164
166
|
|
165
167
|
1. Fork it ( https://github.com/nepalez/uuids/fork )
|
@@ -168,17 +170,6 @@ then remove the gem dependencies from engine's +Gemfile+ and gemspec.
|
|
168
170
|
4. Push to the branch (`git push origin my-new-feature`)
|
169
171
|
5. Create a new Pull Request
|
170
172
|
|
171
|
-
== TODO
|
172
|
-
|
173
|
-
Redefine AR::Base class methods +has_one+ and +has_many+ to allow reference
|
174
|
-
by uuid:
|
175
|
-
|
176
|
-
class MyModel < ActiveRecord::Base
|
177
|
-
include Uuids::Associations
|
178
|
-
|
179
|
-
has_one :another_model, uuid: true
|
180
|
-
end
|
181
|
-
|
182
173
|
== License
|
183
174
|
|
184
175
|
The plugin is distributed under {MIT license}[https://github.com/nepalez/uuids/blob/master/LICENSE.rdoc]
|
data/lib/tasks/uuids_tasks.rake
CHANGED
@@ -14,18 +14,17 @@ namespace :uuids do
|
|
14
14
|
|
15
15
|
def remove_gem
|
16
16
|
say "Removing the 'uuids' gem" do
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
GEMFILE = /gem\s+["|']uuids["|']/
|
18
|
+
GEMSPEC = /_dependency\s+["|']uuids["|']/
|
19
|
+
remove_from_file "Gemfile", GEMFILE
|
20
|
+
Dir["*.gemspec"].each { |file| remove_from_file file, GEMSPEC }
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
def remove_from_file(name, regex)
|
25
25
|
say_with_time name do
|
26
|
-
temp = File.read(name).split("\n")
|
27
|
-
|
28
|
-
File.write(name, temp)
|
26
|
+
temp = File.read(name).split("\n").reject { |line| line[regex] }.join "\n"
|
27
|
+
File.write name, temp
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
data/lib/uuids/base.rb
CHANGED
@@ -2,25 +2,61 @@ module Uuids
|
|
2
2
|
|
3
3
|
# Creates required `#uuids` attribute of the ActiveRecord model.
|
4
4
|
module Base
|
5
|
+
extend ActiveSupport::Concern
|
5
6
|
|
7
|
+
# Prevents the module usage outside an ActiveRecord model.
|
8
|
+
#
|
9
|
+
# class Text < String
|
10
|
+
# include Uuids::Base
|
11
|
+
# end
|
12
|
+
# # => raises a TypeError
|
13
|
+
#
|
6
14
|
def self.included(klass)
|
7
|
-
|
15
|
+
unless klass.ancestors.include? ActiveRecord::Base
|
16
|
+
fail TypeError.new("#{ klass.name } isn't an ActiveRecord model.")
|
17
|
+
end
|
18
|
+
end
|
8
19
|
|
9
|
-
|
20
|
+
# Methods added to the ActiveRecord model.
|
21
|
+
module ClassMethods
|
10
22
|
|
11
|
-
|
12
|
-
klass.before_destroy :prevent_destruction
|
23
|
+
private
|
13
24
|
|
14
|
-
|
15
|
-
|
25
|
+
# Declares:
|
26
|
+
#
|
27
|
+
# * +uuids+ association attribute;
|
28
|
+
# * +uuid+ method (string);
|
29
|
+
# * <tt>uuid</tt> relation scope.
|
30
|
+
#
|
31
|
+
def has_uuids
|
32
|
+
define_uuids
|
33
|
+
define_uuid_getter
|
34
|
+
define_scope
|
35
|
+
end
|
16
36
|
|
17
|
-
|
37
|
+
# Defines the +uuids+ association attribute;
|
38
|
+
def define_uuids
|
39
|
+
has_many :uuids, class_name: "Uuids::Uuid", as: :record, validate: false
|
40
|
+
before_create :add_default_uuid
|
41
|
+
before_destroy :prevent_destruction
|
42
|
+
validates :uuids, presence: true, on: :update
|
43
|
+
end
|
18
44
|
|
19
|
-
|
20
|
-
|
21
|
-
|
45
|
+
# Defines the +uuid+ method
|
46
|
+
def define_uuid_getter
|
47
|
+
class_eval "def uuid; uuids.first.try(:value); end"
|
48
|
+
end
|
49
|
+
|
50
|
+
# Defines the <tt>uuid</tt> relation scope.
|
51
|
+
def define_scope
|
52
|
+
scope :by_uuid, ->(value) {
|
53
|
+
joins(:uuids).where(uuids_uuids: { value: value }).uniq
|
54
|
+
}
|
55
|
+
end
|
22
56
|
end
|
23
57
|
|
58
|
+
private
|
59
|
+
|
24
60
|
# Creates the uuids by default preventing a record from being ureferrable
|
25
61
|
def add_default_uuid
|
26
62
|
uuids.present? || uuids.new
|
data/lib/uuids/version.rb
CHANGED
data/spec/dummy/db/schema.rb
CHANGED
data/spec/dummy/db/test.sqlite3
CHANGED
Binary file
|