uuids 0.2.0 → 1.0.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|