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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5e74d457a60d98ff3a145f6a6a1833f2075983af
4
- data.tar.gz: 6ff0c0939c243ef4648edb145a5d6f5b3b9cab3b
3
+ metadata.gz: 716ef7b1e74c7adf9fd9d29302aa0ad0b2ba6c74
4
+ data.tar.gz: 6086c3c5ece7db6730ef17aa814373789ea03189
5
5
  SHA512:
6
- metadata.gz: 8d4b2414ae87ce041c34248cb76c4e382072d2e20f5e1b54c86a884b5cb488bc703acf02220a8012fb8f3bb080dac55801a779147c67cd73567375ee182016fa
7
- data.tar.gz: 168e82b3e79766a35e814ccb6660f35d4a82d277a8a9a23030936099faa4aa4c631a748beceadb5f72766dd1293b2c50662f2f9b4729106634faf645aabd8499
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
- Metrics/MethodLength:
35
- Exclude:
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
- Defines a model +Uuid+ to store {UUIDs}[http://en.wikipedia.org/wiki/Universally_Unique_Identifier] assigned to various AR records.
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 is expected any uuid is assigned to one record, but a record can be
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 to be included to AR model to provide required +#uuids+ attribute.
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 refering records by some uuid (not the id).
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
- If you reassign all their uuids to merged record then any references remains
30
- valid without tracking and changing them before merge.
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
- * by merging to another ones;
36
- * by explicitly marking as deleted without physical removal.
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 uuids to "New York";
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 uuid.
50
-
51
- === Standards
47
+ will authomatically lead to merged record via old UUID.
52
48
 
53
- The Uuid is generated authomatically following the
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 YourModel < ActiveRecord::Base
92
+ class City < ActiveRecord::Base
93
+ include Uuids::Base
94
+ has_uuids
95
+ end
100
96
 
101
- # declares the association
102
- has_many :uuids, class_name: "Uuids::Uuid", as: :record, validate: false
97
+ This will add methods:
103
98
 
104
- # auto-generates uuid by default
105
- before_create -> { uuids.present? || uuids.new }
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
- # prevents the record from being unreferable
108
- validates :uuids, presence: true, on: :update
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
- # prevents a record destruction before its uuids reassigned to another one
111
- before_destroy -> { uuids.blank? }
112
- end
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
- Instead of above you can simply include the Uuids::Base module:
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
- class YourModel < ActiveRecord::Base
117
- include Uuids::Base
118
- end
117
+ === Referring model by UUID [TODO]
119
118
 
120
- Now you can refer to your model via uuid:
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 CreateAnotherModelTable < ActiveRecord::Migration
123
+ class CreateStreetsTable < ActiveRecord::Migration
123
124
  def change
124
- create_table :another_models do |t|
125
- t.string :your_model_uuid, limit: 36
125
+ create_table :streets do |t|
126
+ t.string :city_uuid, limit: 36
126
127
  end
127
- add_index :another_models, :your_model_uuid
128
+ add_index :streets_table, :city_uuid
128
129
  end
129
130
  end
130
131
 
131
- class AnotherModel < ActiveRecord::Base
132
+ class Street < ActiveRecord::Base
132
133
 
133
- def your_model
134
- @your_model ||= YourModel.join(:uuids)
135
- .where(uuids_uuids: { value: your_model_uuid }).first
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 your_model=(record)
139
- @your_model_uuid ||= Uuids::Uuid.find_by_record(record).try(:value)
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]
@@ -14,18 +14,17 @@ namespace :uuids do
14
14
 
15
15
  def remove_gem
16
16
  say "Removing the 'uuids' gem" do
17
- remove_from_file "Gemfile", /gem\s+["|']uuids["|']/
18
- Dir["*.gemspec"].each do |gemspec|
19
- remove_from_file gemspec, /_dependency\s+["|']uuids["|']/
20
- end
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
- .reject { |line| line[regex] }.join("\n")
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
- fail unless klass.ancestors.include? ActiveRecord::Base
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
- klass.has_many :uuids, uuids_params
20
+ # Methods added to the ActiveRecord model.
21
+ module ClassMethods
10
22
 
11
- klass.before_create :add_default_uuid
12
- klass.before_destroy :prevent_destruction
23
+ private
13
24
 
14
- klass.validates :uuids, presence: true, on: :update
15
- end
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
- private
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
- # Parameters for uuid associations
20
- def self.uuids_params
21
- { class_name: "Uuids::Uuid", as: :record, validate: false }
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
@@ -2,5 +2,5 @@
2
2
  module Uuids
3
3
 
4
4
  # Current release.
5
- VERSION = "0.2.0"
5
+ VERSION = "1.0.0-rc1"
6
6
  end
@@ -0,0 +1,5 @@
1
+ require "uuids"
2
+
3
+ class City < ActiveRecord::Base
4
+ include Uuids::Base
5
+ end
@@ -0,0 +1,8 @@
1
+ class CreateCities < ActiveRecord::Migration
2
+ def change
3
+ create_table :cities do |t|
4
+
5
+ t.timestamps
6
+ end
7
+ end
8
+ end
@@ -13,7 +13,7 @@
13
13
 
14
14
  ActiveRecord::Schema.define(version: 20141017081115) do
15
15
 
16
- create_table "items", force: true do |t|
16
+ create_table "cities", force: true do |t|
17
17
  t.datetime "created_at"
18
18
  t.datetime "updated_at"
19
19
  end
Binary file