uuids 4.0.1 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +4 -2
- data/README.rdoc +15 -23
- data/app/queries/by_uuid.rb +2 -1
- data/lib/uuids/base/belongs_to.rb +123 -0
- data/lib/uuids/base/has_uuids.rb +19 -0
- data/lib/uuids/base.rb +29 -10
- data/lib/uuids/version.rb +1 -1
- data/spec/dummy/app/models/state.rb +6 -0
- data/spec/dummy/db/migrate/20141215182349_create_states.rb +8 -0
- data/spec/dummy/db/migrate/{20141017081115_create_cities.rb → 20151215182355_create_cities.rb} +1 -1
- data/spec/dummy/db/schema.rb +7 -1
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/lib/uuids/base_spec.rb +65 -0
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 016e522c63a1b3f96e575a5e3cc46ebf45d4b7f8
|
4
|
+
data.tar.gz: a23f8b1dc1bbc0e4588294ca6537526bec02d8cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1265400e53725494f22c2a31b4c90de117a8caa5bc16e415aedf3732ddaac2d4ef403268f65a7ff1544f9c65421b5d9b6586abc51ffc3f95c56edceeb58457f5
|
7
|
+
data.tar.gz: e635c00cf24e8c160723d7c9c2716014ec4199f0abfb90966f45685fdcdabcf010a42e7cab3bce6edb662b20821cbf33ab47d0f8ec61c0531b2618584ff82399
|
data/.rubocop.yml
CHANGED
@@ -29,6 +29,9 @@ Style/Documentation:
|
|
29
29
|
- 'db/**/*'
|
30
30
|
- 'lib/uuids/version.rb'
|
31
31
|
|
32
|
+
Style/EmptyLinesAroundBlockBody:
|
33
|
+
Enabled: false
|
34
|
+
|
32
35
|
Style/EmptyLinesAroundClassBody:
|
33
36
|
Enabled: false
|
34
37
|
|
@@ -39,8 +42,7 @@ Style/EmptyLinesAroundModuleBody:
|
|
39
42
|
Enabled: false
|
40
43
|
|
41
44
|
Style/EmptyLineBetweenDefs:
|
42
|
-
|
43
|
-
- 'spec/**/*'
|
45
|
+
Enabled: false
|
44
46
|
|
45
47
|
Style/PredicateName:
|
46
48
|
Enabled: false
|
data/README.rdoc
CHANGED
@@ -60,24 +60,18 @@ Or install it yourself as:
|
|
60
60
|
|
61
61
|
$ gem install uuids
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
After installation you should copy and run uuid's db migration into your module.
|
66
|
-
|
67
|
-
When you install the module to a final application, the migration should be
|
68
|
-
installed to `db/migrate` path directly.
|
63
|
+
Then run the command in the root of a <b>end-up application</b>:
|
69
64
|
|
70
65
|
$ uuids install
|
71
66
|
|
72
|
-
|
73
|
-
|
74
|
-
your gem in a proper environment.
|
75
|
-
|
76
|
-
In this case the migration should be installed to a dummy app in a
|
77
|
-
`spec/dummy/db/migrate` folder. Do it with the `-d` key:
|
67
|
+
Use the <tt>-d</tt> key when installing the gem into a <b>module</b> that is not
|
68
|
+
an end-up application (Rails engine etc.):
|
78
69
|
|
79
70
|
$ uuids install -d
|
80
71
|
|
72
|
+
(this will copy the gem's migrations to the host's dummy folder:
|
73
|
+
+spec/dummy/db/migrate+).
|
74
|
+
|
81
75
|
== Usage
|
82
76
|
|
83
77
|
=== Adding UUIDs to models
|
@@ -86,6 +80,7 @@ Add the assotiation to your AR model with a `has_uuids` helper:
|
|
86
80
|
|
87
81
|
class City < ActiveRecord::Base
|
88
82
|
include Uuids::Base
|
83
|
+
|
89
84
|
has_uuids
|
90
85
|
end
|
91
86
|
|
@@ -113,9 +108,6 @@ all object's UUIDs to another record in advance.
|
|
113
108
|
|
114
109
|
=== Referring model by UUID
|
115
110
|
|
116
|
-
Instead of <tt>ActiveRecord::Associations</tt> +belongs_to+, +has_one+ and
|
117
|
-
+has_many+, you should define custom methods explicitly.
|
118
|
-
|
119
111
|
# db/migrate/*_create_streets.rb
|
120
112
|
class CreateStreetsTable < ActiveRecord::Migration
|
121
113
|
def change
|
@@ -128,17 +120,17 @@ Instead of <tt>ActiveRecord::Associations</tt> +belongs_to+, +has_one+ and
|
|
128
120
|
|
129
121
|
# app/models/street.rb
|
130
122
|
class Street < ActiveRecord::Base
|
123
|
+
include Uuids::Base
|
131
124
|
|
132
|
-
|
125
|
+
belongs_by_uuid_to :city, class: City
|
126
|
+
end
|
133
127
|
|
134
|
-
|
135
|
-
@city ||= City.by_uuid(city_uuid)
|
136
|
-
end
|
128
|
+
This will add both getter and setter for the attribute:
|
137
129
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
130
|
+
street = Street.new name: "Damrak", city: City.new name: "Amsterdam"
|
131
|
+
street.city
|
132
|
+
# => #<City @name="Amsterdam" ... >
|
133
|
+
street.city_uuid == street.city.uuid # => true
|
142
134
|
|
143
135
|
=== Adding uuid
|
144
136
|
|
data/app/queries/by_uuid.rb
CHANGED
@@ -0,0 +1,123 @@
|
|
1
|
+
module Uuids
|
2
|
+
module Base
|
3
|
+
|
4
|
+
# @api hide
|
5
|
+
# Adds getter and setter for the model attribute referred by uuid.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# BelongsTo.add City, :state, State
|
9
|
+
# city = City.new
|
10
|
+
# city.respond_to? :state # => true
|
11
|
+
# city.respond_to? :state= # => true
|
12
|
+
class BelongsTo < Struct.new(:klass, :name, :model)
|
13
|
+
|
14
|
+
# @api hide
|
15
|
+
# @!attribute klass
|
16
|
+
# The model to add the attribute to.
|
17
|
+
# @return [ActiveRecord::Base] The model class.
|
18
|
+
|
19
|
+
# @api hide
|
20
|
+
# @!attribute name
|
21
|
+
# The name of the attribute to be added.
|
22
|
+
# @return [String, Symbol] The name.
|
23
|
+
|
24
|
+
# @api hide
|
25
|
+
# @!attribute model
|
26
|
+
# The model to be referred by uuid.
|
27
|
+
# @return [ActiveRecord::Base] The model class to be referred to.
|
28
|
+
|
29
|
+
# @api hide
|
30
|
+
# @!attribute [r] class_name
|
31
|
+
# The name of the {#klass} constant.
|
32
|
+
# @return [String] The {#klass} name.
|
33
|
+
def class_name
|
34
|
+
@class_name ||= klass.name
|
35
|
+
end
|
36
|
+
|
37
|
+
# @api hide
|
38
|
+
# @!attribute [r] model_name
|
39
|
+
# The name of the {#model} constant.
|
40
|
+
# @return [String] The {#model} name.
|
41
|
+
def model_name
|
42
|
+
@model_name ||= model.name
|
43
|
+
end
|
44
|
+
|
45
|
+
# @api hide
|
46
|
+
# @!attribute [r] model_name
|
47
|
+
# The name of the {#klass} db table column to store reference to the
|
48
|
+
# attribute by uuid.
|
49
|
+
# @return [String] The name of the column.
|
50
|
+
def column_name
|
51
|
+
@column_name ||= "#{ name }_uuid"
|
52
|
+
end
|
53
|
+
|
54
|
+
# @api hide
|
55
|
+
# Constructs the object and adds the attribute.
|
56
|
+
# @example (see Uuids::Base::BelongsTo)
|
57
|
+
# @params [ActiveRecord::Base] klass The model to add attribute to.
|
58
|
+
# Should have a corresponding column for reference by uuid.
|
59
|
+
# @params [String, Symbol] name The name of the attribute to be added.
|
60
|
+
# @params [ActiveRecord::Base] model The model to be referred by uuid.
|
61
|
+
# Should include the <tt>Uuids::Base</tt> module.
|
62
|
+
# @raise (see Uuids::Base::BelongsTo#add)
|
63
|
+
def self.add(*args)
|
64
|
+
new(*args).add
|
65
|
+
end
|
66
|
+
|
67
|
+
# @api hide
|
68
|
+
# Adds the attribute's getter and setter.
|
69
|
+
# @raise [TypeError] if the {#model} doesn't include
|
70
|
+
# the <tt>Uuids::Base</tt> module.
|
71
|
+
# @raise [NotImplementedError] if the {#klass} doesn't have the
|
72
|
+
# correspondint {#column_name} column.
|
73
|
+
def add
|
74
|
+
check_model
|
75
|
+
check_column
|
76
|
+
add_getter
|
77
|
+
add_setter
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def check_model
|
83
|
+
return if model.ancestors.include? Uuids::Base
|
84
|
+
fail TypeError
|
85
|
+
.new "#{ model_name } class doesn't include the Uuids::Base module"
|
86
|
+
end
|
87
|
+
|
88
|
+
def check_column
|
89
|
+
return if klass.attribute_names.include? column_name
|
90
|
+
fail NotImplementedError
|
91
|
+
.new "#{ class_name }##{ column_name } attribute isn't implemented"
|
92
|
+
end
|
93
|
+
|
94
|
+
def add_getter
|
95
|
+
klass.class_eval getter
|
96
|
+
end
|
97
|
+
|
98
|
+
def add_setter
|
99
|
+
klass.class_eval setter
|
100
|
+
end
|
101
|
+
|
102
|
+
def getter
|
103
|
+
"def #{ name };
|
104
|
+
uuid = read_attribute :#{ column_name };
|
105
|
+
return @#{ name } = nil unless uuid;
|
106
|
+
if Array(@#{ name }.try(:uuids)).map(&:value).include? uuid;
|
107
|
+
@#{ name };
|
108
|
+
else;
|
109
|
+
@#{ name } = #{ model_name }.by_uuid(uuid).includes(:uuids).first;
|
110
|
+
end;
|
111
|
+
end"
|
112
|
+
end
|
113
|
+
|
114
|
+
def setter
|
115
|
+
"def #{ name }=(value);
|
116
|
+
fail TypeError unless value.nil? || value.is_a?(#{ model_name });
|
117
|
+
write_attribute :#{ column_name }, value.try(:uuid);
|
118
|
+
#{ name };
|
119
|
+
end"
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
data/lib/uuids/base/has_uuids.rb
CHANGED
@@ -1,13 +1,16 @@
|
|
1
1
|
module Uuids
|
2
2
|
module Base
|
3
3
|
|
4
|
+
# @api hide
|
4
5
|
# Defines methods to be added by the +has_uuids+ class helper.
|
5
6
|
module HasUuids
|
6
7
|
extend ActiveSupport::Concern
|
7
8
|
|
9
|
+
# @api hide
|
8
10
|
# Model scopes.
|
9
11
|
module ClassMethods
|
10
12
|
|
13
|
+
# @api hide
|
11
14
|
# Selects records by uuid(s).
|
12
15
|
#
|
13
16
|
# @example Selects records by a list of uuids
|
@@ -32,8 +35,22 @@ module Uuids
|
|
32
35
|
def by_uuid(*values)
|
33
36
|
Queries::ByUuid.select(self, *values)
|
34
37
|
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# @api hide
|
42
|
+
# Associates uuids to the current model.
|
43
|
+
def has_many_uuids
|
44
|
+
has_many(
|
45
|
+
:uuids,
|
46
|
+
class_name: "Uuids::Models::Uuid",
|
47
|
+
as: :record,
|
48
|
+
validate: false
|
49
|
+
)
|
50
|
+
end
|
35
51
|
end
|
36
52
|
|
53
|
+
# @api hide
|
37
54
|
# Returns the first UUID (sorted as a string) for the record.
|
38
55
|
#
|
39
56
|
# @example
|
@@ -46,6 +63,7 @@ module Uuids
|
|
46
63
|
uuids.map(&:value).sort.first
|
47
64
|
end
|
48
65
|
|
66
|
+
# @api hide
|
49
67
|
# Assigns a new uuid to the record.
|
50
68
|
#
|
51
69
|
# @example
|
@@ -58,6 +76,7 @@ module Uuids
|
|
58
76
|
uuids.new value: value
|
59
77
|
end
|
60
78
|
|
79
|
+
# @api hide
|
61
80
|
# Assigns a list of new uuids to the record.
|
62
81
|
#
|
63
82
|
# @example
|
data/lib/uuids/base.rb
CHANGED
@@ -21,6 +21,8 @@ module Uuids
|
|
21
21
|
#
|
22
22
|
# @example
|
23
23
|
# class City < ActiveRecord::Base
|
24
|
+
# include Uuids::Base
|
25
|
+
#
|
24
26
|
# has_uuids
|
25
27
|
# end
|
26
28
|
#
|
@@ -43,21 +45,38 @@ module Uuids
|
|
43
45
|
# # => true
|
44
46
|
def has_uuids
|
45
47
|
include Uuids::Base::HasUuids
|
46
|
-
|
48
|
+
has_many_uuids
|
47
49
|
after_initialize :add_default_uuid
|
48
50
|
before_destroy :prevent_destruction
|
49
51
|
validates :uuids, presence: true, on: :update
|
50
52
|
end
|
51
53
|
|
52
|
-
#
|
53
|
-
#
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
54
|
+
# The helper defines both the getter and setter for object, associated
|
55
|
+
# by uuid.
|
56
|
+
#
|
57
|
+
# @example
|
58
|
+
# class City < ActiveRecord::Base
|
59
|
+
# include Uuids::Base
|
60
|
+
#
|
61
|
+
# belongs_by_uuid_to :state, class: State
|
62
|
+
# end
|
63
|
+
#
|
64
|
+
# city = City.new
|
65
|
+
# city.state_uuid = "12345678-90ab-cdef-1234-567890abcdef"
|
66
|
+
#
|
67
|
+
# city.state.class # => State
|
68
|
+
# city.state.uuid # => "12345678-90ab-cdef-1234-567890abcdef"
|
69
|
+
#
|
70
|
+
# city.state = State.new uuid: "fedcba98-7654-3210-fedc-ba9876543210"
|
71
|
+
# city.state.uuid # => "fedcba98-7654-3210-fedc-ba9876543210"
|
72
|
+
#
|
73
|
+
# @param [String, Symbol] name The name of the attribute.
|
74
|
+
# @param [Hash] options The options for the association.
|
75
|
+
# @option options [Class] :class The model of the attribute.
|
76
|
+
# @option options [String] :class_name The name of the attribute's model.
|
77
|
+
def belongs_by_uuid_to(name, options = {})
|
78
|
+
class_name = options[:class] || options[:class_name].constantize
|
79
|
+
BelongsTo.add self, name, class_name
|
61
80
|
end
|
62
81
|
end
|
63
82
|
|
data/lib/uuids/version.rb
CHANGED
data/spec/dummy/db/schema.rb
CHANGED
@@ -11,9 +11,10 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
14
|
+
ActiveRecord::Schema.define(version: 20151215182355) do
|
15
15
|
|
16
16
|
create_table "cities", force: true do |t|
|
17
|
+
t.string "state_uuid", limit: 36
|
17
18
|
t.datetime "created_at"
|
18
19
|
t.datetime "updated_at"
|
19
20
|
end
|
@@ -23,6 +24,11 @@ ActiveRecord::Schema.define(version: 20141017081115) do
|
|
23
24
|
t.datetime "updated_at"
|
24
25
|
end
|
25
26
|
|
27
|
+
create_table "states", force: true do |t|
|
28
|
+
t.datetime "created_at"
|
29
|
+
t.datetime "updated_at"
|
30
|
+
end
|
31
|
+
|
26
32
|
create_table "uuids_uuids", force: true do |t|
|
27
33
|
t.string "value", limit: 36, null: false
|
28
34
|
t.integer "record_id", null: false
|
data/spec/dummy/db/test.sqlite3
CHANGED
Binary file
|
data/spec/lib/uuids/base_spec.rb
CHANGED
@@ -81,5 +81,70 @@ module Uuids
|
|
81
81
|
expect { subject.destroy! }.not_to raise_error
|
82
82
|
end
|
83
83
|
end
|
84
|
+
|
85
|
+
describe ".belongs_by_uuid_to" do
|
86
|
+
|
87
|
+
context "when a model doesn't include Uuids::Base" do
|
88
|
+
|
89
|
+
it "raises TypeError" do
|
90
|
+
expect { City.send :belongs_by_uuid_to, :state, class: Record }
|
91
|
+
.to raise_error { TypeError }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context "when a class doesn't have column for uuids" do
|
96
|
+
|
97
|
+
it "raises NotImplementedError" do
|
98
|
+
expect { City.send :belongs_by_uuid_to, :country, class: State }
|
99
|
+
.to raise_error { NotImplementedError }
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
context "with valid arguments" do
|
104
|
+
|
105
|
+
before { City.send :belongs_by_uuid_to, :state, class: State }
|
106
|
+
subject { City.new }
|
107
|
+
|
108
|
+
let!(:uuid) { "01234567-89ab-cdef-0123-456789abcdef" }
|
109
|
+
let!(:state) { State.create uuid: uuid }
|
110
|
+
|
111
|
+
it "defines the getter" do
|
112
|
+
expect(subject).to respond_to :state
|
113
|
+
expect(subject.method(:state).arity).to eq 0
|
114
|
+
end
|
115
|
+
|
116
|
+
it "defines the setter" do
|
117
|
+
expect(subject).to respond_to :state=
|
118
|
+
expect(subject.method(:state=).arity).to eq 1
|
119
|
+
end
|
120
|
+
|
121
|
+
it "sets the object" do
|
122
|
+
expect { subject.state = state }
|
123
|
+
.to change { subject.state }.to state
|
124
|
+
end
|
125
|
+
|
126
|
+
it "sets the object uuid" do
|
127
|
+
expect { subject.state = state }
|
128
|
+
.to change { subject.state_uuid }.to state.uuid
|
129
|
+
end
|
130
|
+
|
131
|
+
it "resets the object" do
|
132
|
+
subject.state = state
|
133
|
+
expect { subject.state = nil }
|
134
|
+
.to change { subject.state }.to nil
|
135
|
+
end
|
136
|
+
|
137
|
+
it "resets the object uuid" do
|
138
|
+
subject.state = state
|
139
|
+
expect { subject.state = nil }
|
140
|
+
.to change { subject.state_uuid }.to nil
|
141
|
+
end
|
142
|
+
|
143
|
+
it "sets the object by uuid" do
|
144
|
+
expect { subject.state_uuid = state.uuid }
|
145
|
+
.to change { subject.state }.to state
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
84
149
|
end
|
85
150
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: uuids
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.0
|
4
|
+
version: 4.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Kozin
|
@@ -218,19 +218,22 @@ files:
|
|
218
218
|
- db/migrate/20141016112506_create_uuids_uuids.rb
|
219
219
|
- lib/uuids.rb
|
220
220
|
- lib/uuids/base.rb
|
221
|
+
- lib/uuids/base/belongs_to.rb
|
221
222
|
- lib/uuids/base/has_uuids.rb
|
222
223
|
- lib/uuids/version.rb
|
223
224
|
- spec/bin/uuids_spec.rb
|
224
225
|
- spec/dummy/Rakefile
|
225
226
|
- spec/dummy/app/models/city.rb
|
226
227
|
- spec/dummy/app/models/record.rb
|
228
|
+
- spec/dummy/app/models/state.rb
|
227
229
|
- spec/dummy/config/database.yml
|
228
230
|
- spec/dummy/config/environment.rb
|
229
231
|
- spec/dummy/config/initializers/application.rb
|
230
232
|
- spec/dummy/config/initializers/dummy.rb
|
231
233
|
- spec/dummy/config/initializers/seed_loader.rb
|
232
234
|
- spec/dummy/db/migrate/20141016113016_create_records.rb
|
233
|
-
- spec/dummy/db/migrate/
|
235
|
+
- spec/dummy/db/migrate/20141215182349_create_states.rb
|
236
|
+
- spec/dummy/db/migrate/20151215182355_create_cities.rb
|
234
237
|
- spec/dummy/db/schema.rb
|
235
238
|
- spec/dummy/db/test.sqlite3
|
236
239
|
- spec/dummy/lib/dummy.rb
|
@@ -288,10 +291,12 @@ test_files:
|
|
288
291
|
- spec/dummy/config/initializers/seed_loader.rb
|
289
292
|
- spec/dummy/config/initializers/application.rb
|
290
293
|
- spec/dummy/config/initializers/dummy.rb
|
291
|
-
- spec/dummy/db/migrate/
|
294
|
+
- spec/dummy/db/migrate/20141215182349_create_states.rb
|
292
295
|
- spec/dummy/db/migrate/20141016113016_create_records.rb
|
296
|
+
- spec/dummy/db/migrate/20151215182355_create_cities.rb
|
293
297
|
- spec/dummy/db/test.sqlite3
|
294
298
|
- spec/dummy/db/schema.rb
|
299
|
+
- spec/dummy/app/models/state.rb
|
295
300
|
- spec/dummy/app/models/record.rb
|
296
301
|
- spec/dummy/app/models/city.rb
|
297
302
|
- spec/dummy/lib/dummy.rb
|