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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1ce0188d48ab948a1a9d6e01b9bce6783d7d05f4
4
- data.tar.gz: 55040c5ebc0e3824e2e81c5eb05806544dea305e
3
+ metadata.gz: 016e522c63a1b3f96e575a5e3cc46ebf45d4b7f8
4
+ data.tar.gz: a23f8b1dc1bbc0e4588294ca6537526bec02d8cf
5
5
  SHA512:
6
- metadata.gz: 0980d73961b09197aa7e419de79d880fcee3966b552eb1d7e31fad42aab546973479bac2a6321ebc71242150934378cc4a42b5041d709a6e7c807a355cabb1f3
7
- data.tar.gz: c1eb2d45b66ebfdde301d6c4c31b2dc357a53447fc02754395ed88fea18caeb4f4c12ea67ca916e78b4032e3de9006bf9c63fb172f9ac7a098422ec23a12ab9b
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
- Exclude:
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
- == Initialization
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
- When you install the module to another gem as a part of its environment,
73
- the migration isn't a part of your project. It only needed for testing
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
- scope :by_city, ->(city) { City.by_uuid(city.uuid) }
125
+ belongs_by_uuid_to :city, class: City
126
+ end
133
127
 
134
- def city
135
- @city ||= City.by_uuid(city_uuid)
136
- end
128
+ This will add both getter and setter for the attribute:
137
129
 
138
- def city=(city)
139
- write_attribute :city_uuid, city.uuid
140
- end
141
- end
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
 
@@ -41,7 +41,8 @@ module Uuids
41
41
  end
42
42
 
43
43
  # @api hide
44
- # Runs and returns the query.
44
+ # Runs and returns the query
45
+ # @return [ActiveRecord::Relation] The updated scope.
45
46
  def select
46
47
  values.any? ? by_uuid : model.all
47
48
  end
@@ -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
@@ -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
- add_association
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
- # @api hide
53
- # Associates uuids to the current model.
54
- def add_association
55
- has_many(
56
- :uuids,
57
- class_name: "Uuids::Models::Uuid",
58
- as: :record,
59
- validate: false
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
@@ -1,5 +1,5 @@
1
1
  module Uuids
2
2
 
3
3
  # Current release.
4
- VERSION = "4.0.1"
4
+ VERSION = "4.1.0"
5
5
  end
@@ -0,0 +1,6 @@
1
+ require "uuids"
2
+
3
+ class State < ActiveRecord::Base
4
+ include Uuids::Base
5
+ has_uuids
6
+ end
@@ -0,0 +1,8 @@
1
+ class CreateStates < ActiveRecord::Migration
2
+ def change
3
+ create_table :states do |t|
4
+
5
+ t.timestamps
6
+ end
7
+ end
8
+ end
@@ -1,7 +1,7 @@
1
1
  class CreateCities < ActiveRecord::Migration
2
2
  def change
3
3
  create_table :cities do |t|
4
-
4
+ t.string :state_uuid, limit: 36
5
5
  t.timestamps
6
6
  end
7
7
  end
@@ -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: 20141017081115) do
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
Binary file
@@ -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.1
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/20141017081115_create_cities.rb
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/20141017081115_create_cities.rb
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