auto_increment 1.1.1 → 1.2.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: a36a39a264726b9982a4d095c35fea157c26f5c7
4
- data.tar.gz: e9b05d63b7f60324d93d629ebeb6918570587c9a
3
+ metadata.gz: af472f5d68643f3e99904a990f327d9846d19e33
4
+ data.tar.gz: 380099f99c07728694985db36741aea2c42c3727
5
5
  SHA512:
6
- metadata.gz: c570534697d6be0655f3f5c2e1206438fdee3324474e60bd9420c819225b68767694c34eaea809a41460a8b8130257a525ed5a651fb9437a832f26253d577849
7
- data.tar.gz: fd281c2cf3c6f083aa3eb9f7851b7d30e4e4d7f2e2b05b27038bce56f748b14b4b9a3c1a38ea4692408787e4225661758a582b92b905f5ad90fa629a0eeefe1b
6
+ metadata.gz: 54c9892f0e7d2570879a979aa7f108ab0965171564328e0cb5eda8cb0cb75116ea27e2bca2a64c2d5741c0e1ca7b7983e9625cec9fd1b7199064aaf91388ebb4
7
+ data.tar.gz: 018cc0922a78a5398880e7f36bc0c0e70a14746b98d937c62b62694c692e6576feb572147cfa42477114da24064705227110aeb9c52212acd2159a1698317ec0
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source 'http://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in auto_increment.gemspec
4
4
  gemspec
data/Guardfile CHANGED
@@ -1,5 +1,5 @@
1
1
  guard :rspec, cmd: 'bundle exec rspec' do
2
2
  watch(%r{^spec/.+_spec\.rb$})
3
3
  watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
- watch('spec/spec_helper.rb') { "spec" }
5
- end
4
+ watch('spec/spec_helper.rb') { 'spec' }
5
+ end
data/README.md CHANGED
@@ -17,7 +17,7 @@ To use the gem version, put the following gem requirement in your `Gemfile`:
17
17
 
18
18
  ## Usage
19
19
 
20
- To work with a auto increment column you used to do sometihng like this in your model:
20
+ To work with a auto increment column you used to do something like this in your model:
21
21
 
22
22
  before_create :set_code
23
23
  def set_code
@@ -29,7 +29,7 @@ Looks fine, but not when you need to do it over and over again. In fact auto_inc
29
29
 
30
30
  All you need to do is this:
31
31
 
32
- auto_increment
32
+ auto_increment :code
33
33
 
34
34
  And your code field will be incremented
35
35
 
@@ -38,17 +38,19 @@ And your code field will be incremented
38
38
 
39
39
  So you have a different column or need a scope. auto_increment provides options. You can use it like this:
40
40
 
41
- auto_increment column: :letter, scope: [:account_id, :job_id], initial: 'C', force: true
41
+ auto_increment :letter, scope: [:account_id, :job_id], initial: 'C', force: true, lock: false
42
+
43
+ First argument is the column that will be incremented. Can be integer or string.
42
44
 
43
- * column: the column that will be incremented. Can be integer os string (default: code)
44
45
  * scope: you can define columns that will be scoped and you can use as many as you want (default: nil)
45
46
  * initial: initial value of column (default: 1)
46
47
  * force: you can set a value before create and auto_increment will not change that, but if you do want this, set force to true (default: false)
48
+ * lock: you can set a lock on the max query. (default: false)
47
49
 
48
50
 
49
51
  ## Compatibility
50
52
 
51
- Tested with Rails 4.0.13 in Ruby 2.0.0
53
+ Tested with Rails 4.2.2 in Ruby 2.0.0
52
54
 
53
55
  ## License
54
56
 
@@ -1,37 +1,36 @@
1
1
  # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "auto_increment/version"
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
+ require 'auto_increment/version'
4
4
 
5
- Gem::Specification.new do |spec|
6
- spec.name = "auto_increment"
7
- spec.version = AutoIncrement::VERSION
8
- spec.licenses = %w(MIT)
9
- spec.platform = Gem::Platform::RUBY
10
- spec.authors = ["Felipe Diesel"]
11
- spec.email = ["felipediesel@gmail.com"]
12
- spec.homepage = "http://github.com/felipediesel/auto_increment"
13
- spec.summary = %q{Auto increment a string or integer field}
14
- spec.description = %q{Automaticaly increments a string or integer field in ActiveRecord.}
5
+ Gem::Specification.new do |s|
6
+ s.name = 'auto_increment'
7
+ s.version = AutoIncrement::VERSION.dup
8
+ s.licenses = 'MIT'
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ['Felipe Diesel']
11
+ s.email = ['felipediesel@gmail.com']
12
+ s.homepage = 'http://github.com/felipediesel/auto_increment'
13
+ s.summary = 'Auto increment a string or integer field'
14
+ s.description = 'Automaticaly increments a string or integer field ' \
15
+ 'in ActiveRecord.'
15
16
 
16
- spec.rubyforge_project = "auto_increment"
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.require_paths = ['lib']
17
20
 
18
- spec.files = `git ls-files`.split("\n")
19
- spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
- spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
- spec.require_paths = ["lib"]
21
+ s.add_dependency 'activerecord', '~> 4.0'
22
+ s.add_dependency 'activesupport', '~> 4.0'
22
23
 
23
- spec.add_dependency "activerecord", "~> 4.0"
24
- spec.add_dependency "activesupport", "~> 4.0"
24
+ s.add_development_dependency 'bundler', '~> 1.3'
25
+ s.add_development_dependency 'rake', '~> 0'
25
26
 
26
- spec.add_development_dependency "bundler", "~> 1.3"
27
- spec.add_development_dependency "rake"
27
+ s.add_development_dependency 'rspec', '~> 3.3'
28
+ s.add_development_dependency 'rspec-nc', '~> 0.2'
29
+ s.add_development_dependency 'guard', '~> 2.12'
30
+ s.add_development_dependency 'guard-rspec', '~> 4.5'
31
+ s.add_development_dependency 'fuubar', '~> 2'
32
+ s.add_development_dependency 'coveralls', '~> 0'
33
+ s.add_development_dependency 'database_cleaner', '~> 1.4'
28
34
 
29
- spec.add_development_dependency "rspec"
30
- spec.add_development_dependency "rspec-nc"
31
- spec.add_development_dependency "guard"
32
- spec.add_development_dependency "guard-rspec"
33
- spec.add_development_dependency "fuubar"
34
- spec.add_development_dependency "coveralls"
35
-
36
- spec.add_development_dependency 'sqlite3'
35
+ s.add_development_dependency 'sqlite3', '~> 1.3'
37
36
  end
@@ -1,13 +1,14 @@
1
- require "date"
2
- require "i18n"
3
- require "active_record"
4
- require "active_support"
5
- require "active_support/time_with_zone"
6
- require "auto_increment/version"
1
+ require 'date'
2
+ require 'i18n'
3
+ require 'active_record'
4
+ require 'active_support'
5
+ require 'active_support/time_with_zone'
6
+ require 'auto_increment/version'
7
7
 
8
+ # +AutoIncrement+
8
9
  module AutoIncrement
9
- autoload :Incrementor, "auto_increment/incrementor"
10
- autoload :ActiveRecord , "auto_increment/active_record"
10
+ autoload :Incrementor, 'auto_increment/incrementor'
11
+ autoload :ActiveRecord, 'auto_increment/active_record'
11
12
  end
12
13
 
13
14
  ActiveRecord::Base.send :include, AutoIncrement::ActiveRecord
@@ -1,10 +1,12 @@
1
+ # +AutoIncrement+
1
2
  module AutoIncrement
3
+ # +AutoIncrement::ActiveRecord+
2
4
  module ActiveRecord
3
5
  extend ActiveSupport::Concern
4
-
6
+ # +AutoIncrement::ActiveRecord::ClassMethods+
5
7
  module ClassMethods
6
- def auto_increment(options = {})
7
- before_create Incrementor.new(options)
8
+ def auto_increment(column = nil, options = {})
9
+ before_create Incrementor.new(column, options)
8
10
  end
9
11
  end
10
12
  end
@@ -1,8 +1,16 @@
1
+ # +AutoIncrement+
1
2
  module AutoIncrement
3
+ # +AutoIncrement::Incrementor+
2
4
  class Incrementor
3
- def initialize(options = {})
4
- @options = options.reverse_merge column: :code, scope: nil, initial: 1, force: false
5
- @options[:scope] = [ @options[:scope] ] unless @options[:scope].is_a? Array
5
+ def initialize(column = nil, options = {})
6
+ if column.is_a? Hash
7
+ options = column
8
+ column = nil
9
+ end
10
+
11
+ @column = column || options[:column] || :code
12
+ @options = options.reverse_merge scope: nil, initial: 1, force: false
13
+ @options[:scope] = [@options[:scope]] unless @options[:scope].is_a? Array
6
14
  end
7
15
 
8
16
  def before_create(record)
@@ -13,16 +21,16 @@ module AutoIncrement
13
21
  private
14
22
 
15
23
  def can_write?
16
- @record.send(@options[:column]).blank? or @options[:force]
24
+ @record.send(@column).blank? || @options[:force]
17
25
  end
18
26
 
19
27
  def write
20
- @record.send :write_attribute, @options[:column], increment
28
+ @record.send :write_attribute, @column, increment
21
29
  end
22
30
 
23
31
  def build_scopes(query)
24
32
  @options[:scope].each do |scope|
25
- if scope.present? and @record.respond_to?(scope)
33
+ if scope.present? && @record.respond_to?(scope)
26
34
  query = query.where(scope => @record.send(scope))
27
35
  end
28
36
  end
@@ -32,18 +40,29 @@ module AutoIncrement
32
40
 
33
41
  def maximum
34
42
  query = build_scopes @record.class
43
+ query.lock if lock?
35
44
 
36
- if @options[:initial].class == String
37
- query.select("#{@options[:column]} max").order("LENGTH(#{@options[:column]}) DESC, #{@options[:column]} DESC").first.try :max
45
+ if string?
46
+ query.select("#{@column} max")
47
+ .order("LENGTH(#{@column}) DESC, #{@column} DESC")
48
+ .first.try :max
38
49
  else
39
- query.maximum @options[:column]
50
+ query.maximum @column
40
51
  end
41
52
  end
42
53
 
54
+ def lock?
55
+ @options[:lock] == true
56
+ end
57
+
43
58
  def increment
44
59
  max = maximum
45
60
 
46
61
  max.blank? ? @options[:initial] : max.next
47
62
  end
63
+
64
+ def string?
65
+ @options[:initial].class == String
66
+ end
48
67
  end
49
- end
68
+ end
@@ -1,3 +1,4 @@
1
+ # +AutoIncrement::VERSION+
1
2
  module AutoIncrement
2
- VERSION = "1.1.1"
3
+ VERSION = '1.2.0'
3
4
  end
Binary file
@@ -16,15 +16,41 @@ describe AutoIncrement do
16
16
  it { expect(@user_account1.letter_code).to eq 'A' }
17
17
  end
18
18
 
19
- describe "do not increment outside scope" do
19
+ describe 'do not increment outside scope' do
20
20
  it { expect(@user_account2.letter_code).to eq 'A' }
21
21
  end
22
22
 
23
- describe "not set column if is already set" do
23
+ describe 'not set column if is already set' do
24
24
  it { expect(@account2.code).to eq 50 }
25
25
  end
26
26
 
27
- describe "set column if option force is used" do
27
+ describe 'set column if option force is used' do
28
28
  it { expect(@user_account1.letter_code).to eq 'A' }
29
29
  end
30
+
31
+ describe 'locks query for increment' do
32
+ before :all do
33
+ threads = []
34
+ lock = Mutex.new
35
+ @account = Account.create name: 'Another Account', code: 50
36
+ @accounts = []
37
+ 5.times do |_t|
38
+ threads << Thread.new do
39
+ lock.synchronize do
40
+ 5.times do |_thr|
41
+ @accounts << (@account.users.create name: 'Daniel')
42
+ end
43
+ end
44
+ end
45
+ end
46
+ threads.each(&:join)
47
+ end
48
+
49
+ let(:account_last_letter_code) do
50
+ @accounts.sort_by(&:letter_code).last.letter_code
51
+ end
52
+
53
+ it { expect(@accounts.size).to eq 25 }
54
+ it { expect(account_last_letter_code).to eq 'Y' }
55
+ end
30
56
  end
@@ -2,24 +2,30 @@ require 'spec_helper'
2
2
 
3
3
  describe AutoIncrement::Incrementor do
4
4
  {
5
- nil => 1, 0 => 1, 1 => 2, 'A' => 'B', 'Z' => 'AA', 'AA' => 'AB', 'AAAAA' => 'AAAAB'
5
+ nil => 1,
6
+ 0 => 1,
7
+ 1 => 2,
8
+ 'A' => 'B',
9
+ 'Z' => 'AA',
10
+ 'AA' => 'AB',
11
+ 'AAAAA' => 'AAAAB'
6
12
  }.each do |previous_value, next_value|
7
13
  describe "increment value for #{previous_value}" do
8
- it {
14
+ it do
9
15
  allow(subject).to receive(:maximum) { previous_value }
10
16
  expect(subject.send(:increment)).to eq next_value
11
- }
17
+ end
12
18
  end
13
19
  end
14
20
 
15
- describe "initial value of string" do
16
- subject {
21
+ describe 'initial value of string' do
22
+ subject do
17
23
  AutoIncrement::Incrementor.new initial: 'A'
18
- }
24
+ end
19
25
 
20
- it {
26
+ it do
21
27
  allow(subject).to receive(:maximum) { nil }
22
28
  expect(subject.send(:increment)).to eq 'A'
23
- }
29
+ end
24
30
  end
25
31
  end
@@ -1,5 +1,6 @@
1
+ # Spec +Account+
1
2
  class Account < ActiveRecord::Base
2
- auto_increment
3
+ auto_increment :code
3
4
 
4
5
  has_many :users
5
- end
6
+ end
@@ -1,5 +1,7 @@
1
+ # + Spec +User+
1
2
  class User < ActiveRecord::Base
2
- auto_increment column: :letter_code, scope: :account_id, initial: 'A', force: true
3
+ auto_increment :letter_code, scope: :account_id, initial: 'A', force: true,
4
+ lock: true
3
5
 
4
6
  belongs_to :account
5
7
  end
@@ -3,7 +3,11 @@ Coveralls.wear!
3
3
 
4
4
  require 'pry'
5
5
  require 'auto_increment'
6
+ require 'database_cleaner'
6
7
 
7
- ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:"
8
+ ActiveRecord::Base.establish_connection adapter: 'sqlite3',
9
+ database: 'spec/db/sync.db',
10
+ timeout: 5000
8
11
 
9
- require 'support/active_record'
12
+ # require 'support/active_record'
13
+ require 'support/database_cleaner'
@@ -1,8 +1,10 @@
1
+ # +ActiveRecord+ migration for Accounts
1
2
  ActiveRecord::Migration.create_table :accounts do |t|
2
3
  t.string :name
3
- t.date :code
4
+ t.integer :code
4
5
  end
5
6
 
7
+ # +ActiveRecord+ migration for Users
6
8
  ActiveRecord::Migration.create_table :users do |t|
7
9
  t.string :name
8
10
  t.integer :account_id
@@ -0,0 +1,12 @@
1
+ RSpec.configure do |config|
2
+ config.before(:suite) do
3
+ DatabaseCleaner.strategy = :transaction
4
+ DatabaseCleaner.clean_with(:truncation)
5
+ end
6
+
7
+ config.around(:each) do |example|
8
+ DatabaseCleaner.cleaning do
9
+ example.run
10
+ end
11
+ end
12
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: auto_increment
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felipe Diesel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-05-05 00:00:00.000000000 Z
11
+ date: 2015-06-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -56,114 +56,128 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - '>='
59
+ - - ~>
60
60
  - !ruby/object:Gem::Version
61
61
  version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - '>='
66
+ - - ~>
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ~>
74
74
  - !ruby/object:Gem::Version
75
- version: '0'
75
+ version: '3.3'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ~>
81
81
  - !ruby/object:Gem::Version
82
- version: '0'
82
+ version: '3.3'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rspec-nc
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ~>
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: '0.2'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ~>
95
95
  - !ruby/object:Gem::Version
96
- version: '0'
96
+ version: '0.2'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: guard
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ~>
102
102
  - !ruby/object:Gem::Version
103
- version: '0'
103
+ version: '2.12'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ~>
109
109
  - !ruby/object:Gem::Version
110
- version: '0'
110
+ version: '2.12'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: guard-rspec
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - '>='
115
+ - - ~>
116
116
  - !ruby/object:Gem::Version
117
- version: '0'
117
+ version: '4.5'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - '>='
122
+ - - ~>
123
123
  - !ruby/object:Gem::Version
124
- version: '0'
124
+ version: '4.5'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: fuubar
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ~>
130
130
  - !ruby/object:Gem::Version
131
- version: '0'
131
+ version: '2'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ~>
137
137
  - !ruby/object:Gem::Version
138
- version: '0'
138
+ version: '2'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: coveralls
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - '>='
143
+ - - ~>
144
144
  - !ruby/object:Gem::Version
145
145
  version: '0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - '>='
150
+ - - ~>
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: database_cleaner
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ~>
158
+ - !ruby/object:Gem::Version
159
+ version: '1.4'
160
+ type: :development
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ~>
165
+ - !ruby/object:Gem::Version
166
+ version: '1.4'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: sqlite3
155
169
  requirement: !ruby/object:Gem::Requirement
156
170
  requirements:
157
- - - '>='
171
+ - - ~>
158
172
  - !ruby/object:Gem::Version
159
- version: '0'
173
+ version: '1.3'
160
174
  type: :development
161
175
  prerelease: false
162
176
  version_requirements: !ruby/object:Gem::Requirement
163
177
  requirements:
164
- - - '>='
178
+ - - ~>
165
179
  - !ruby/object:Gem::Version
166
- version: '0'
180
+ version: '1.3'
167
181
  description: Automaticaly increments a string or integer field in ActiveRecord.
168
182
  email:
169
183
  - felipediesel@gmail.com
@@ -185,12 +199,14 @@ files:
185
199
  - lib/auto_increment/active_record.rb
186
200
  - lib/auto_increment/incrementor.rb
187
201
  - lib/auto_increment/version.rb
202
+ - spec/db/sync.db
188
203
  - spec/lib/active_record_spec.rb
189
204
  - spec/lib/incrementor_spec.rb
190
205
  - spec/models/account.rb
191
206
  - spec/models/user.rb
192
207
  - spec/spec_helper.rb
193
208
  - spec/support/active_record.rb
209
+ - spec/support/database_cleaner.rb
194
210
  homepage: http://github.com/felipediesel/auto_increment
195
211
  licenses:
196
212
  - MIT
@@ -210,16 +226,18 @@ required_rubygems_version: !ruby/object:Gem::Requirement
210
226
  - !ruby/object:Gem::Version
211
227
  version: '0'
212
228
  requirements: []
213
- rubyforge_project: auto_increment
229
+ rubyforge_project:
214
230
  rubygems_version: 2.4.6
215
231
  signing_key:
216
232
  specification_version: 4
217
233
  summary: Auto increment a string or integer field
218
234
  test_files:
235
+ - spec/db/sync.db
219
236
  - spec/lib/active_record_spec.rb
220
237
  - spec/lib/incrementor_spec.rb
221
238
  - spec/models/account.rb
222
239
  - spec/models/user.rb
223
240
  - spec/spec_helper.rb
224
241
  - spec/support/active_record.rb
242
+ - spec/support/database_cleaner.rb
225
243
  has_rdoc: