sequenced 1.0.0 → 1.2.0
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.
- data/CHANGELOG.md +13 -0
- data/README.md +11 -5
- data/lib/sequenced.rb +0 -1
- data/lib/sequenced/acts_as_sequenced.rb +38 -12
- data/lib/sequenced/version.rb +1 -1
- data/sequenced.gemspec +1 -1
- data/test/dummy/app/models/email.rb +4 -0
- data/test/dummy/db/migrate/20130411225444_create_emails.rb +12 -0
- data/test/sequenced_test.rb +11 -3
- metadata +72 -63
- data/lib/sequenced/exceptions.rb +0 -4
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
1.2.0 (April 11, 2013)
|
2
|
+
----------------------
|
3
|
+
|
4
|
+
* Accept an array of symbols for the scope attribute to scope by multiple
|
5
|
+
columns.
|
6
|
+
|
7
|
+
1.1.0 (July 5, 2012)
|
8
|
+
--------------------
|
9
|
+
|
10
|
+
* Raise ArgumentError instead of Sequenced::InvalidAttributeError
|
11
|
+
* Remove custom exceptions
|
12
|
+
* Stop calling it a "plugin"
|
13
|
+
|
1
14
|
1.0.0 (March 7, 2012)
|
2
15
|
---------------------
|
3
16
|
|
data/README.md
CHANGED
@@ -1,13 +1,11 @@
|
|
1
1
|
# Sequenced
|
2
2
|
|
3
|
-
Sequenced is a simple
|
3
|
+
Sequenced is a simple gem that generates scoped sequential IDs for
|
4
4
|
ActiveRecord models. This gem provides an `acts_as_sequenced` macro that
|
5
|
-
automatically assigns a unique, sequential ID to each record.
|
5
|
+
automatically assigns a unique, sequential ID to each record. The sequential ID is
|
6
6
|
not a replacement for the database primary key, but rather adds another way to
|
7
7
|
retrieve the object without exposing the primary key.
|
8
8
|
|
9
|
-
Extracted from the [GuideKit](https://guidekit.com) codebase.
|
10
|
-
|
11
9
|
## Purpose
|
12
10
|
|
13
11
|
It's generally a bad practice to expose your primary keys to the world
|
@@ -58,7 +56,15 @@ end
|
|
58
56
|
```
|
59
57
|
|
60
58
|
The `:scope` option can be any attribute, but will typically be the foreign
|
61
|
-
key of an associated parent object.
|
59
|
+
key of an associated parent object. You can even scope by multiple columns
|
60
|
+
for polymorphic relationships:
|
61
|
+
|
62
|
+
```ruby
|
63
|
+
class Answer < ActiveRecord::Base
|
64
|
+
belongs_to :questionable, :polymorphic => true
|
65
|
+
acts_as_sequenced :scope => [:questionable_id, :questionable_type]
|
66
|
+
end
|
67
|
+
```
|
62
68
|
|
63
69
|
## Configuration
|
64
70
|
|
data/lib/sequenced.rb
CHANGED
@@ -51,7 +51,7 @@ module Sequenced
|
|
51
51
|
# defined.
|
52
52
|
#
|
53
53
|
# Returns nothing.
|
54
|
-
# Raises
|
54
|
+
# Raises ArgumentError if
|
55
55
|
# 1) The specified scope method is undefined,
|
56
56
|
# 2) The specified scope method returns nil, or
|
57
57
|
# 3) The sequential ID column is undefined.
|
@@ -60,39 +60,60 @@ module Sequenced
|
|
60
60
|
column = self.class.sequenced_options[:column]
|
61
61
|
|
62
62
|
if scope.present?
|
63
|
-
if
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
if scope.is_a?(Array)
|
64
|
+
scope.each { |s| verify_scope_method(s) }
|
65
|
+
else
|
66
|
+
verify_scope_method(scope)
|
67
67
|
end
|
68
68
|
end
|
69
69
|
|
70
70
|
unless self.respond_to?(column)
|
71
|
-
raise
|
71
|
+
raise ArgumentError, "Column method ##{column.to_s} is undefined"
|
72
72
|
end
|
73
73
|
|
74
74
|
# Fetch the next ID unless it is already defined
|
75
75
|
self.send(:"#{column}=", next_sequential_id) until sequential_id_is_unique?
|
76
76
|
end
|
77
77
|
|
78
|
+
# Internal: Verify that the given scope method is defined and does not
|
79
|
+
# return nil unexpectedly.
|
80
|
+
#
|
81
|
+
# scope - A Symbol representing the scope method.
|
82
|
+
#
|
83
|
+
# Returns nothing.
|
84
|
+
# Raises an ArgumentError if
|
85
|
+
# 1) The specified scope method is undefined, or
|
86
|
+
# 2) The specified scope method returns nil
|
87
|
+
def verify_scope_method(scope)
|
88
|
+
if !self.respond_to?(scope)
|
89
|
+
raise ArgumentError, "Scope method ##{scope.to_s} is undefined"
|
90
|
+
elsif self.send(scope).nil?
|
91
|
+
raise ArgumentError, "Scope method ##{scope.to_s} returned nil unexpectedly"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
78
95
|
# Internal: Obtain the next sequential ID
|
79
96
|
#
|
80
97
|
# Returns Integer.
|
81
|
-
# Raises
|
82
|
-
# an Integer.
|
98
|
+
# Raises ArgumentError if the last sequential ID is not an Integer.
|
83
99
|
def next_sequential_id
|
84
100
|
scope = self.class.sequenced_options[:scope]
|
85
101
|
column = self.class.sequenced_options[:column]
|
86
102
|
start_at = self.class.sequenced_options[:start_at]
|
87
103
|
|
88
104
|
q = self.class.unscoped.where("#{column.to_s} IS NOT NULL").order("#{column.to_s} DESC")
|
89
|
-
|
105
|
+
|
106
|
+
if scope.is_a?(Symbol)
|
107
|
+
q = q.where(scope => self.send(scope))
|
108
|
+
elsif scope.is_a?(Array)
|
109
|
+
scope.each { |s| q = q.where(s => self.send(s)) }
|
110
|
+
end
|
90
111
|
|
91
112
|
return start_at unless last_record = q.first
|
92
113
|
last_id = last_record.send(column)
|
93
114
|
|
94
115
|
unless last_id.is_a?(Integer)
|
95
|
-
raise
|
116
|
+
raise ArgumentError, "The sequential ID column must contain Integer values"
|
96
117
|
end
|
97
118
|
|
98
119
|
last_id + 1 > start_at ? last_id + 1 : start_at
|
@@ -107,9 +128,14 @@ module Sequenced
|
|
107
128
|
return false unless self.send(column).is_a?(Integer)
|
108
129
|
|
109
130
|
q = self.class.unscoped.where(column => self.send(column))
|
110
|
-
q = q.where(scope => self.send(scope)) if scope.is_a?(Symbol)
|
111
|
-
q = q.where("NOT id = ?", self.id) if self.persisted?
|
112
131
|
|
132
|
+
if scope.is_a?(Symbol)
|
133
|
+
q = q.where(scope => self.send(scope))
|
134
|
+
elsif scope.is_a?(Array)
|
135
|
+
scope.each { |s| q = q.where(s => self.send(s)) }
|
136
|
+
end
|
137
|
+
|
138
|
+
q = q.where("NOT id = ?", self.id) if self.persisted?
|
113
139
|
q.count > 0 ? false : true
|
114
140
|
end
|
115
141
|
end
|
data/lib/sequenced/version.rb
CHANGED
data/sequenced.gemspec
CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.email = ["derrickreimer@gmail.com"]
|
9
9
|
s.homepage = "https://github.com/djreimer/sequenced"
|
10
10
|
s.summary = "Generate scoped sequential IDs for ActiveRecord models"
|
11
|
-
s.description = "Sequenced is a
|
11
|
+
s.description = "Sequenced is a gem that generates scoped sequential IDs for ActiveRecord models."
|
12
12
|
|
13
13
|
s.files = `git ls-files`.split("\n")
|
14
14
|
s.test_files = Dir["test/**/*"]
|
data/test/sequenced_test.rb
CHANGED
@@ -8,6 +8,7 @@ require 'test_helper'
|
|
8
8
|
# Order - :scope => :non_existent_column
|
9
9
|
# User - :scope => :account_id, :column => :custom_sequential_id
|
10
10
|
# Address - :scope => :account_id ('sequential_id' does not exist)
|
11
|
+
# Email - :scope => [:emailable_id, :emailable_type]
|
11
12
|
# Subscription - no options
|
12
13
|
|
13
14
|
class SequencedTest < ActiveSupport::TestCase
|
@@ -49,12 +50,12 @@ class SequencedTest < ActiveSupport::TestCase
|
|
49
50
|
test "undefined scope method" do
|
50
51
|
account = Account.create
|
51
52
|
order = account.orders.build
|
52
|
-
assert_raises(
|
53
|
+
assert_raises(ArgumentError) { order.save }
|
53
54
|
end
|
54
55
|
|
55
56
|
test "scope method returns nil" do
|
56
57
|
answer = Answer.new
|
57
|
-
assert_raises(
|
58
|
+
assert_raises(ArgumentError) { answer.save }
|
58
59
|
end
|
59
60
|
|
60
61
|
test "custom sequential id column" do
|
@@ -77,7 +78,7 @@ class SequencedTest < ActiveSupport::TestCase
|
|
77
78
|
test "undefined sequential id column" do
|
78
79
|
account = Account.create
|
79
80
|
address = account.addresses.build
|
80
|
-
assert_raises(
|
81
|
+
assert_raises(ArgumentError) { address.save }
|
81
82
|
end
|
82
83
|
|
83
84
|
test "manually setting sequential id" do
|
@@ -97,4 +98,11 @@ class SequencedTest < ActiveSupport::TestCase
|
|
97
98
|
comment = question.comments.create
|
98
99
|
assert_equal 4, comment.sequential_id
|
99
100
|
end
|
101
|
+
|
102
|
+
test "multi-column scopes" do
|
103
|
+
Email.create(:emailable_id => 1, :emailable_type => "User", :sequential_id => 2)
|
104
|
+
Email.create(:emailable_id => 1, :emailable_type => "Question", :sequential_id => 3)
|
105
|
+
email = Email.create(:emailable_id => 1, :emailable_type => "User")
|
106
|
+
assert_equal 3, email.sequential_id
|
107
|
+
end
|
100
108
|
end
|
metadata
CHANGED
@@ -1,72 +1,88 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequenced
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.0
|
4
5
|
prerelease:
|
5
|
-
version: 1.0.0
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Derrick Reimer
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
dependencies:
|
16
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2013-04-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
17
15
|
name: activesupport
|
18
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
18
|
+
requirements:
|
21
19
|
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
24
22
|
type: :runtime
|
25
23
|
prerelease: false
|
26
|
-
version_requirements:
|
27
|
-
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '3.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
28
31
|
name: activerecord
|
29
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
30
33
|
none: false
|
31
|
-
requirements:
|
34
|
+
requirements:
|
32
35
|
- - ~>
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '3.0'
|
35
38
|
type: :runtime
|
36
39
|
prerelease: false
|
37
|
-
version_requirements:
|
38
|
-
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '3.0'
|
46
|
+
- !ruby/object:Gem::Dependency
|
39
47
|
name: rails
|
40
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
41
49
|
none: false
|
42
|
-
requirements:
|
50
|
+
requirements:
|
43
51
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version:
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '3.1'
|
46
54
|
type: :development
|
47
55
|
prerelease: false
|
48
|
-
version_requirements:
|
49
|
-
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.1'
|
62
|
+
- !ruby/object:Gem::Dependency
|
50
63
|
name: sqlite3
|
51
|
-
requirement:
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
52
65
|
none: false
|
53
|
-
requirements:
|
54
|
-
- -
|
55
|
-
- !ruby/object:Gem::Version
|
56
|
-
version:
|
66
|
+
requirements:
|
67
|
+
- - ! '>='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
57
70
|
type: :development
|
58
71
|
prerelease: false
|
59
|
-
version_requirements:
|
60
|
-
|
61
|
-
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - ! '>='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: '0'
|
78
|
+
description: Sequenced is a gem that generates scoped sequential IDs for ActiveRecord
|
79
|
+
models.
|
80
|
+
email:
|
62
81
|
- derrickreimer@gmail.com
|
63
82
|
executables: []
|
64
|
-
|
65
83
|
extensions: []
|
66
|
-
|
67
84
|
extra_rdoc_files: []
|
68
|
-
|
69
|
-
files:
|
85
|
+
files:
|
70
86
|
- .gitignore
|
71
87
|
- CHANGELOG.md
|
72
88
|
- Gemfile
|
@@ -76,7 +92,6 @@ files:
|
|
76
92
|
- TODO.md
|
77
93
|
- lib/sequenced.rb
|
78
94
|
- lib/sequenced/acts_as_sequenced.rb
|
79
|
-
- lib/sequenced/exceptions.rb
|
80
95
|
- lib/sequenced/version.rb
|
81
96
|
- sequenced.gemspec
|
82
97
|
- test/dummy/README.rdoc
|
@@ -91,6 +106,7 @@ files:
|
|
91
106
|
- test/dummy/app/models/address.rb
|
92
107
|
- test/dummy/app/models/answer.rb
|
93
108
|
- test/dummy/app/models/comment.rb
|
109
|
+
- test/dummy/app/models/email.rb
|
94
110
|
- test/dummy/app/models/invoice.rb
|
95
111
|
- test/dummy/app/models/order.rb
|
96
112
|
- test/dummy/app/models/question.rb
|
@@ -122,6 +138,7 @@ files:
|
|
122
138
|
- test/dummy/db/migrate/20120219175744_create_users.rb
|
123
139
|
- test/dummy/db/migrate/20120219232323_create_addresses.rb
|
124
140
|
- test/dummy/db/migrate/20120220000804_create_comments.rb
|
141
|
+
- test/dummy/db/migrate/20130411225444_create_emails.rb
|
125
142
|
- test/dummy/db/schema.rb
|
126
143
|
- test/dummy/lib/assets/.gitkeep
|
127
144
|
- test/dummy/log/.gitkeep
|
@@ -136,41 +153,31 @@ files:
|
|
136
153
|
- test/dummy/db/test.sqlite3
|
137
154
|
- test/dummy/log/development.log
|
138
155
|
- test/dummy/log/test.log
|
139
|
-
has_rdoc: true
|
140
156
|
homepage: https://github.com/djreimer/sequenced
|
141
157
|
licenses: []
|
142
|
-
|
143
158
|
post_install_message:
|
144
159
|
rdoc_options: []
|
145
|
-
|
146
|
-
require_paths:
|
160
|
+
require_paths:
|
147
161
|
- lib
|
148
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
162
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
149
163
|
none: false
|
150
|
-
requirements:
|
151
|
-
- -
|
152
|
-
- !ruby/object:Gem::Version
|
153
|
-
|
154
|
-
|
155
|
-
- 0
|
156
|
-
version: "0"
|
157
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
164
|
+
requirements:
|
165
|
+
- - ! '>='
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
169
|
none: false
|
159
|
-
requirements:
|
160
|
-
- -
|
161
|
-
- !ruby/object:Gem::Version
|
162
|
-
|
163
|
-
segments:
|
164
|
-
- 0
|
165
|
-
version: "0"
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
166
174
|
requirements: []
|
167
|
-
|
168
175
|
rubyforge_project:
|
169
|
-
rubygems_version: 1.
|
176
|
+
rubygems_version: 1.8.23
|
170
177
|
signing_key:
|
171
178
|
specification_version: 3
|
172
179
|
summary: Generate scoped sequential IDs for ActiveRecord models
|
173
|
-
test_files:
|
180
|
+
test_files:
|
174
181
|
- test/dummy/app/assets/javascripts/application.js
|
175
182
|
- test/dummy/app/assets/stylesheets/application.css
|
176
183
|
- test/dummy/app/controllers/application_controller.rb
|
@@ -179,6 +186,7 @@ test_files:
|
|
179
186
|
- test/dummy/app/models/address.rb
|
180
187
|
- test/dummy/app/models/answer.rb
|
181
188
|
- test/dummy/app/models/comment.rb
|
189
|
+
- test/dummy/app/models/email.rb
|
182
190
|
- test/dummy/app/models/invoice.rb
|
183
191
|
- test/dummy/app/models/order.rb
|
184
192
|
- test/dummy/app/models/question.rb
|
@@ -211,6 +219,7 @@ test_files:
|
|
211
219
|
- test/dummy/db/migrate/20120219175744_create_users.rb
|
212
220
|
- test/dummy/db/migrate/20120219232323_create_addresses.rb
|
213
221
|
- test/dummy/db/migrate/20120220000804_create_comments.rb
|
222
|
+
- test/dummy/db/migrate/20130411225444_create_emails.rb
|
214
223
|
- test/dummy/db/schema.rb
|
215
224
|
- test/dummy/db/test.sqlite3
|
216
225
|
- test/dummy/log/development.log
|
data/lib/sequenced/exceptions.rb
DELETED