rescue_unique_constraint 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f0e3cb076ff7875dceb8444be36ef82080bcd05c
4
+ data.tar.gz: 353306cab3df3aa689c7c74f4208c30d28c05c91
5
+ SHA512:
6
+ metadata.gz: 230a6f59b281782ace42043b97ccee346739b4db72bc42091a24017636491af825bbc1f2cc9aac05a2928193b69ae8dbe674c25598b9a84037ede76e4f1b206d
7
+ data.tar.gz: e6326eb248afb2684f3a58f9246c56152a58478a497fda051fc491a948afde9fa4b46d38ae149610cd733636b3e0de39c7e59b26403bc5e5f7a6f5ae23c245d0
data/.gitignore ADDED
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rescue_unique_constraint.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2015 Reverb.com, LLC
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
data/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # RescueUniqueConstraint
2
+
3
+ Rails doesn't do a great job of rescuing ActiveRecord::RecordNotUnique
4
+ violations resulting from a duplicate entry on a unique constraint.
5
+
6
+ This gem automatically rescues the error and instead adds a validation error
7
+ on the field in question, making it behave as if you had a normal uniqueness
8
+ validation.
9
+
10
+ Note that if you have only a unique constraint and no uniquness validation, it
11
+ is possible for your object to validate but then fail to save.
12
+
13
+ See Usage for more info.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ gem 'rescue_unique_constraint'
20
+
21
+ And then execute:
22
+
23
+ $ bundle
24
+
25
+ Or install it yourself as:
26
+
27
+ $ gem install rescue_unique_constraint
28
+
29
+ ## Usage
30
+
31
+ Assuming you've added unique index:
32
+
33
+ class AddIndexToThing < ActiveRecord::Migration
34
+ disable_ddl_transaction!
35
+
36
+ def change
37
+ add_index :things, :somefield, unique: true, algorithm: :concurrently, name: "my_unique_index"
38
+ end
39
+ end
40
+
41
+ Before:
42
+
43
+ class Thing < ActiveRecord::Base
44
+ end
45
+
46
+ thing = Thing.create(somefield: "foo")
47
+ dupe = Thing.create(somefield: "foo")
48
+ => raises ActiveRecord::RecordNotUnique
49
+
50
+ Note that if you have `validates :uniqueness` in your model, it will prevent
51
+ the RecordNotUnique from being raised in _some_ cases, but not all, as race
52
+ conditions between multiple processes will still cause duplicate entries to
53
+ enter your database.
54
+
55
+ After:
56
+
57
+ class Thing < ActiveRecord::Base
58
+ rescue_unique_constraint index: "my_unique_index", field: "somefield"
59
+ end
60
+
61
+ thing = Thing.create(somefield: "foo")
62
+ dupe = Thing.create(somefield: "foo")
63
+ => false
64
+ thing.errors[:somefield] == "somefield has already been taken"
65
+ => true
66
+
67
+ ## Testing
68
+
69
+ You'll need a database that supports unique constraints.
70
+ This gem has been tested with PostgreSQL and SQLite only.
71
+
72
+ ## Contributing
73
+
74
+ 1. Fork it ( https://github.com/[my-github-username]/rescue_unique_constraint/fork )
75
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
76
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
77
+ 4. Push to the branch (`git push origin my-new-feature`)
78
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,34 @@
1
+ require "rescue_unique_constraint/version"
2
+ require 'active_record'
3
+
4
+ module RescueUniqueConstraint
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+ def rescue_unique_constraint(index:, field:)
11
+ define_method(:create_or_update_with_rescue) do
12
+ begin
13
+ create_or_update_without_rescue
14
+ rescue ActiveRecord::RecordNotUnique => e
15
+ case e.message
16
+ when /#{index}/ # Postgres
17
+ errors.add(field, :taken)
18
+ when /UNIQUE.*#{field}/ # SQLite
19
+ errors.add(field, :taken)
20
+ else
21
+ # This should not happen; we want to know if we forgot to handle some unique constraint
22
+ raise e
23
+ end
24
+ false
25
+ end
26
+ end
27
+
28
+ alias_method :create_or_update_without_rescue, :create_or_update
29
+ alias_method :create_or_update, :create_or_update_with_rescue
30
+ end
31
+ end
32
+ end
33
+
34
+ ActiveRecord::Base.include(RescueUniqueConstraint)
@@ -0,0 +1,3 @@
1
+ module RescueUniqueConstraint
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rescue_unique_constraint/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rescue_unique_constraint"
8
+ spec.version = RescueUniqueConstraint::VERSION
9
+ spec.authors = ["Tam Dang", "Yan Pritzker"]
10
+ spec.email = ["tam.dang@reverb.com","yan@reverb.com"]
11
+ spec.summary = %q{Turns ActiveRecord::RecordNotUnique errors into ActiveRecord errors}
12
+ spec.description = %q{Rescues unique constraint violations and turns them into ActiveRecord errors}
13
+ spec.homepage = "https://github.com/reverbdotcom/rescue_unique_contraint"
14
+ spec.license = "Apache 2.0"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "activerecord", "~> 4.1"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.6"
24
+ spec.add_development_dependency "rake", "~> 10.5"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "sqlite3", "~> 1.3"
27
+ end
@@ -0,0 +1,27 @@
1
+ require 'active_record'
2
+ require 'rescue_unique_constraint'
3
+
4
+ describe RescueUniqueConstraint do
5
+ before do
6
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
7
+ ActiveRecord::Schema.verbose = false
8
+ ActiveRecord::Schema.define(:version => 1) do
9
+ create_table :things do |t|
10
+ t.string :name
11
+ end
12
+
13
+ add_index :things, :name, unique: true, name: "idx_things_on_name_unique"
14
+ end
15
+ end
16
+
17
+ class Thing < ActiveRecord::Base
18
+ rescue_unique_constraint index: "idx_things_on_name_unique", field: "name"
19
+ end
20
+
21
+ it "rescues unique constraint violations as activerecord errors" do
22
+ thing = Thing.create(name: "foo")
23
+ dupe = Thing.new(name: "foo")
24
+ expect(dupe.save).to eql false
25
+ expect(dupe.errors[:name].first).to match /taken/
26
+ end
27
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rescue_unique_constraint
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Tam Dang
8
+ - Yan Pritzker
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-01-14 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '4.1'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '4.1'
28
+ - !ruby/object:Gem::Dependency
29
+ name: bundler
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '1.6'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '1.6'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rake
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '10.5'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '10.5'
56
+ - !ruby/object:Gem::Dependency
57
+ name: rspec
58
+ requirement: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - "~>"
61
+ - !ruby/object:Gem::Version
62
+ version: '3.0'
63
+ type: :development
64
+ prerelease: false
65
+ version_requirements: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - "~>"
68
+ - !ruby/object:Gem::Version
69
+ version: '3.0'
70
+ - !ruby/object:Gem::Dependency
71
+ name: sqlite3
72
+ requirement: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '1.3'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - "~>"
82
+ - !ruby/object:Gem::Version
83
+ version: '1.3'
84
+ description: Rescues unique constraint violations and turns them into ActiveRecord
85
+ errors
86
+ email:
87
+ - tam.dang@reverb.com
88
+ - yan@reverb.com
89
+ executables: []
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - Gemfile
95
+ - LICENSE.txt
96
+ - README.md
97
+ - Rakefile
98
+ - lib/rescue_unique_constraint.rb
99
+ - lib/rescue_unique_constraint/version.rb
100
+ - rescue_unique_constraint.gemspec
101
+ - spec/rescue_unique_constraint_spec.rb
102
+ homepage: https://github.com/reverbdotcom/rescue_unique_contraint
103
+ licenses:
104
+ - Apache 2.0
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.4.8
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Turns ActiveRecord::RecordNotUnique errors into ActiveRecord errors
126
+ test_files:
127
+ - spec/rescue_unique_constraint_spec.rb