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