activerecord-rescue_from_duplicate 0.1.2 → 0.1.3
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 +5 -5
- data/.travis.yml +11 -17
- data/README.md +15 -0
- data/Rakefile +0 -10
- data/activerecord-rescue_from_duplicate.gemspec +10 -10
- data/docker-compose.yml +18 -0
- data/lib/rescue_from_duplicate/active_record/extension.rb +1 -1
- data/lib/rescue_from_duplicate/active_record/version.rb +1 -1
- data/spec/rescue_from_duplicate_spec.rb +14 -18
- data/spec/rescuer_spec.rb +4 -8
- data/spec/spec_helper.rb +0 -2
- data/spec/support/model.rb +45 -43
- data/spec/validator_spec.rb +10 -13
- metadata +10 -14
- data/gemfiles/Gemfile.ar-3.2 +0 -10
- data/gemfiles/Gemfile.ar-4.0 +0 -10
- data/gemfiles/Gemfile.ar-4.1 +0 -10
- data/gemfiles/Gemfile.ar-4.2 +0 -10
- data/gemfiles/Gemfile.ar-edge +0 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 57e38eb0a3e8bc47bc4c1e7e299c4ca6b30a4ffa14d9982db17d88086f3dc0ae
|
4
|
+
data.tar.gz: d963ba4a9a08bd3c6ba193bff5ca84f57074e3e0f68afd7a43ff6c02b02accb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e703b89e8bcb6a4b722ca14fda626f837fe49cfca11cd1ced6023b2d54b0fde559e26e87e808ae5918ab9c180e27142ada04be181c1690122a16774906bee28f
|
7
|
+
data.tar.gz: 3c87f3a1f4f8c5e3233a2a603075bf62f9c0e49dcf6f9257c0e8b98de4bf16c5078b9c718537dd6aea0de704712381d833b7a3b1e544c87eed3a57103426524f
|
data/.travis.yml
CHANGED
@@ -1,22 +1,16 @@
|
|
1
1
|
sudo: false
|
2
2
|
rvm:
|
3
|
-
- 2.
|
4
|
-
- 2.2
|
5
|
-
- 2.3.1
|
6
|
-
gemfile:
|
7
|
-
- gemfiles/Gemfile.ar-3.2
|
8
|
-
- gemfiles/Gemfile.ar-4.0
|
9
|
-
- gemfiles/Gemfile.ar-4.1
|
10
|
-
- gemfiles/Gemfile.ar-4.2
|
11
|
-
- gemfiles/Gemfile.ar-edge
|
12
|
-
|
13
|
-
before_script:
|
14
|
-
- mysql -e 'create database rescue_from_duplicate;'
|
15
|
-
- psql -c 'create database rescue_from_duplicate;' -U postgres
|
3
|
+
- 2.5.0
|
16
4
|
|
17
5
|
env:
|
18
|
-
-
|
6
|
+
- DOCKER_COMPOSE_VERSION=1.20.1
|
7
|
+
|
8
|
+
before_script:
|
9
|
+
- docker-compose --version
|
10
|
+
- docker-compose pull
|
11
|
+
- docker-compose build
|
12
|
+
- docker-compose up --no-start
|
13
|
+
- docker-compose start
|
14
|
+
- sleep 30 # Wait for databases to come online
|
15
|
+
- docker ps
|
19
16
|
|
20
|
-
matrix:
|
21
|
-
allow_failures:
|
22
|
-
- gemfile: gemfiles/Gemfile.ar-edge
|
data/README.md
CHANGED
@@ -69,6 +69,21 @@ And then execute:
|
|
69
69
|
Or install it yourself as:
|
70
70
|
|
71
71
|
$ gem install activerecord-rescue_from_duplicate
|
72
|
+
|
73
|
+
## Development Setup
|
74
|
+
|
75
|
+
Install:
|
76
|
+
|
77
|
+
- Have Docker installed
|
78
|
+
- Clone the repo
|
79
|
+
- `docker-compose up -d`
|
80
|
+
|
81
|
+
Run tests:
|
82
|
+
|
83
|
+
```
|
84
|
+
rspec
|
85
|
+
```
|
86
|
+
|
72
87
|
|
73
88
|
## Contributing
|
74
89
|
|
data/Rakefile
CHANGED
@@ -5,13 +5,3 @@ RSpec::Core::RakeTask.new(:spec)
|
|
5
5
|
|
6
6
|
task :default => :spec
|
7
7
|
|
8
|
-
namespace :spec do
|
9
|
-
task :all do
|
10
|
-
Dir[File.expand_path('../gemfiles/*.lock', __FILE__)].each { |f| File.delete(f) }
|
11
|
-
Dir[File.expand_path('../gemfiles/*', __FILE__)].each do |gemfile|
|
12
|
-
env = {'BUNDLE_GEMFILE' => gemfile, 'MYSQL' => '1'}
|
13
|
-
system(env, 'bundle install')
|
14
|
-
system(env, 'bundle exec rspec')
|
15
|
-
end
|
16
|
-
end
|
17
|
-
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
|
-
lib = File.expand_path(
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
3
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
-
require
|
4
|
+
require "rescue_from_duplicate/active_record/version"
|
5
5
|
|
6
6
|
Gem::Specification.new do |spec|
|
7
7
|
spec.name = "activerecord-rescue_from_duplicate"
|
@@ -18,14 +18,14 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency
|
21
|
+
spec.add_dependency "activerecord", ">= 5.2"
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler"
|
23
|
+
spec.add_development_dependency "bundler"
|
24
24
|
spec.add_development_dependency "rake"
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
30
|
-
spec.add_development_dependency
|
25
|
+
spec.add_development_dependency "simplecov"
|
26
|
+
spec.add_development_dependency "sqlite3"
|
27
|
+
spec.add_development_dependency "mysql2"
|
28
|
+
spec.add_development_dependency "rspec"
|
29
|
+
spec.add_development_dependency "pg"
|
30
|
+
spec.add_development_dependency "pry"
|
31
31
|
end
|
data/docker-compose.yml
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
mysql:
|
2
|
+
image: mysql:5.7
|
3
|
+
environment:
|
4
|
+
MYSQL_USER: "test"
|
5
|
+
MYSQL_PASSWORD: "test"
|
6
|
+
MYSQL_ALLOW_EMPTY_PASSWORD: "true"
|
7
|
+
MYSQL_DATABASE: "rescue_from_duplicate"
|
8
|
+
ports:
|
9
|
+
- "29291:3306"
|
10
|
+
|
11
|
+
postgres:
|
12
|
+
image: postgres:10.3
|
13
|
+
environment:
|
14
|
+
POSTGRES_USER: "test"
|
15
|
+
POSTGRES_PASSWORD: "test"
|
16
|
+
POSTGRES_DB: "rescue_from_duplicate"
|
17
|
+
ports:
|
18
|
+
- "29292:5432"
|
@@ -45,7 +45,7 @@ module RescueFromDuplicate::ActiveRecord
|
|
45
45
|
def exception_handler(exception)
|
46
46
|
columns = exception_columns(exception)
|
47
47
|
return unless columns
|
48
|
-
columns.sort
|
48
|
+
columns = columns.sort
|
49
49
|
|
50
50
|
self.class._rescue_from_duplicate_handlers.detect do |handler|
|
51
51
|
handler.rescue? && columns == handler.columns
|
@@ -2,16 +2,16 @@ require 'spec_helper'
|
|
2
2
|
include RescueFromDuplicate
|
3
3
|
|
4
4
|
shared_examples 'database error rescuing' do
|
5
|
-
let(:uniqueness_exception) { ::ActiveRecord::RecordNotUnique.new(message
|
5
|
+
let(:uniqueness_exception) { ::ActiveRecord::RecordNotUnique.new(message) }
|
6
6
|
|
7
7
|
subject { Rescuable.new }
|
8
8
|
|
9
9
|
before do
|
10
|
-
allow(Rescuable).to
|
10
|
+
allow(Rescuable).to(receive(:connection).and_return(double(indexes: [Rescuable.index])))
|
11
11
|
end
|
12
12
|
|
13
13
|
describe "#create_or_update when the validation fails" do
|
14
|
-
before { Base.
|
14
|
+
before { allow(Base).to(receive(:exception).and_return(uniqueness_exception)) }
|
15
15
|
|
16
16
|
context "when the validator is present" do
|
17
17
|
it "adds an error to the model" do
|
@@ -21,19 +21,19 @@ shared_examples 'database error rescuing' do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
context "when the validator is not present" do
|
24
|
-
before { Rescuable.
|
24
|
+
before { allow(Rescuable).to(receive(:validators).and_return([Rescuable.presence_validator])) }
|
25
25
|
|
26
26
|
it "raises an exception" do
|
27
|
-
expect{ subject.create_or_update }.to raise_error(ActiveRecord::RecordNotUnique)
|
27
|
+
expect { subject.create_or_update }.to raise_error(ActiveRecord::RecordNotUnique)
|
28
28
|
end
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
32
|
describe "#create_or_update when using rescuer without validation" do
|
33
33
|
before {
|
34
|
-
Rescuable.
|
35
|
-
Rescuable.
|
36
|
-
Base.
|
34
|
+
allow(Rescuable).to(receive(:_validators).and_return({}))
|
35
|
+
allow(Rescuable).to(receive(:_rescue_from_duplicates).and_return([Rescuable.uniqueness_rescuer]))
|
36
|
+
allow(Base).to(receive(:exception).and_return(uniqueness_exception))
|
37
37
|
}
|
38
38
|
|
39
39
|
it "adds an error to the model" do
|
@@ -44,18 +44,14 @@ shared_examples 'database error rescuing' do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
describe RescueFromDuplicate::ActiveRecord do
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
it_behaves_like 'database error rescuing'
|
51
|
-
end
|
47
|
+
context 'mysql' do
|
48
|
+
let(:message) { "Duplicate entry '1-Rescuable-toto' for key 'index_rescuable_on_shop_id_and_type_and_name'" }
|
49
|
+
it_behaves_like 'database error rescuing'
|
52
50
|
end
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
it_behaves_like 'database error rescuing'
|
58
|
-
end
|
52
|
+
context 'pgsql' do
|
53
|
+
let(:message) { "PG::UniqueViolation: ERROR: duplicate key value violates unique constraint \"index_rescuable_on_shop_id_and_type_and_name\"\nDETAIL: Key (shop_id, type, name)=(1, Rescuable, toto) already exists.\n: INSERT INTO \"postgresql_models\" (\"shop_id\", \"type\", \"name\") VALUES ($1, $2, $3) RETURNING \"id\"" }
|
54
|
+
it_behaves_like 'database error rescuing'
|
59
55
|
end
|
60
56
|
|
61
57
|
context 'sqlite3' do
|
data/spec/rescuer_spec.rb
CHANGED
@@ -35,14 +35,10 @@ describe Sqlite3Model do
|
|
35
35
|
it_behaves_like 'a model with rescued unique error without validator'
|
36
36
|
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
it_behaves_like 'a model with rescued unique error without validator'
|
41
|
-
end
|
38
|
+
describe MysqlModel do
|
39
|
+
it_behaves_like 'a model with rescued unique error without validator'
|
42
40
|
end
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
it_behaves_like 'a model with rescued unique error without validator'
|
47
|
-
end
|
42
|
+
describe PostgresqlModel do
|
43
|
+
it_behaves_like 'a model with rescued unique error without validator'
|
48
44
|
end
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/model.rb
CHANGED
@@ -1,18 +1,30 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
1
|
+
require "active_record"
|
2
|
+
require "json"
|
3
|
+
require "yaml"
|
4
|
+
|
5
|
+
CONNECTIONS = {
|
6
|
+
test_sqlite3: {
|
7
|
+
adapter: "sqlite3",
|
8
|
+
database: "/tmp/rescue_from_duplicate.db",
|
9
|
+
},
|
10
|
+
test_postgresql: {
|
11
|
+
adapter: "postgresql",
|
12
|
+
database: "rescue_from_duplicate",
|
13
|
+
username: "test",
|
14
|
+
password: "test",
|
15
|
+
host: "127.0.0.1",
|
16
|
+
port: "29292",
|
17
|
+
},
|
18
|
+
test_mysql: {
|
19
|
+
adapter: "mysql2",
|
20
|
+
database: "rescue_from_duplicate",
|
21
|
+
username: "test",
|
22
|
+
password: "test",
|
23
|
+
host: "127.0.0.1",
|
24
|
+
port: "29291",
|
25
|
+
},
|
13
26
|
}
|
14
|
-
|
15
|
-
class CreateAllTables < ActiveRecord::Migration
|
27
|
+
class CreateAllTables < ActiveRecord::Migration[5.2]
|
16
28
|
def self.recreate_table(name, *args, &block)
|
17
29
|
execute "drop table if exists #{name}"
|
18
30
|
|
@@ -30,17 +42,13 @@ class CreateAllTables < ActiveRecord::Migration
|
|
30
42
|
end
|
31
43
|
|
32
44
|
def self.up
|
33
|
-
|
34
|
-
|
35
|
-
recreate_table(:mysql_models)
|
36
|
-
end
|
45
|
+
ActiveRecord::Base.establish_connection(CONNECTIONS.fetch(:test_mysql))
|
46
|
+
recreate_table(:mysql_models)
|
37
47
|
|
38
|
-
|
39
|
-
|
40
|
-
recreate_table(:postgresql_models)
|
41
|
-
end
|
48
|
+
ActiveRecord::Base.establish_connection(CONNECTIONS.fetch(:test_postgresql))
|
49
|
+
recreate_table(:postgresql_models)
|
42
50
|
|
43
|
-
ActiveRecord::Base.establish_connection(
|
51
|
+
ActiveRecord::Base.establish_connection(CONNECTIONS.fetch(:test_sqlite3))
|
44
52
|
recreate_table(:sqlite3_models)
|
45
53
|
end
|
46
54
|
end
|
@@ -50,43 +58,37 @@ CreateAllTables.up
|
|
50
58
|
|
51
59
|
|
52
60
|
module TestModel
|
53
|
-
|
54
|
-
|
55
|
-
included do
|
56
|
-
rescue_from_duplicate :handle, scope: :relation_id, message: "handle must be unique for this relation"
|
61
|
+
def self.included(base)
|
62
|
+
base.rescue_from_duplicate(:handle, scope: :relation_id, message: "handle must be unique for this relation")
|
57
63
|
|
58
|
-
|
59
|
-
|
64
|
+
base.validates(:name, uniqueness: { rescue_from_duplicate: true }, allow_nil: true)
|
65
|
+
base.validates(:size, uniqueness: { rescue_from_duplicate: true }, allow_nil: true)
|
60
66
|
end
|
61
67
|
end
|
62
68
|
|
63
|
-
|
64
|
-
|
65
|
-
include TestModel
|
69
|
+
class MysqlModel < ActiveRecord::Base
|
70
|
+
include TestModel
|
66
71
|
|
67
|
-
|
68
|
-
end
|
72
|
+
establish_connection(CONNECTIONS.fetch(:test_mysql))
|
69
73
|
end
|
70
74
|
|
71
|
-
|
72
|
-
|
73
|
-
include TestModel
|
75
|
+
class PostgresqlModel < ActiveRecord::Base
|
76
|
+
include TestModel
|
74
77
|
|
75
|
-
|
76
|
-
end
|
78
|
+
establish_connection(CONNECTIONS.fetch(:test_postgresql))
|
77
79
|
end
|
78
80
|
|
79
81
|
class Sqlite3Model < ActiveRecord::Base
|
80
82
|
include TestModel
|
81
83
|
|
82
|
-
establish_connection
|
84
|
+
establish_connection(CONNECTIONS.fetch(:test_sqlite3))
|
83
85
|
end
|
84
86
|
|
85
87
|
Models = [
|
86
|
-
Sqlite3Model
|
88
|
+
Sqlite3Model,
|
89
|
+
MysqlModel,
|
90
|
+
PostgresqlModel,
|
87
91
|
]
|
88
|
-
Models << MysqlModel if defined?(MysqlModel)
|
89
|
-
Models << PostgresqlModel if defined?(PostgresqlModel)
|
90
92
|
|
91
93
|
|
92
94
|
RSpec.configure do |config|
|
data/spec/validator_spec.rb
CHANGED
@@ -5,7 +5,8 @@ shared_examples 'a model with rescued uniqueness validator' do
|
|
5
5
|
context 'when catching a race condition' do
|
6
6
|
|
7
7
|
before(:each) {
|
8
|
-
ActiveRecord::Validations::UniquenessValidator
|
8
|
+
allow_any_instance_of(ActiveRecord::Validations::UniquenessValidator)
|
9
|
+
.to(receive(:validate_each)).and_return(nil)
|
9
10
|
described_class.create!(name: 'toto', size: 5)
|
10
11
|
}
|
11
12
|
|
@@ -55,7 +56,7 @@ shared_examples 'missing index finding' do
|
|
55
56
|
|
56
57
|
context 'indexes are missing' do
|
57
58
|
before {
|
58
|
-
described_class.
|
59
|
+
allow(described_class).to(receive(:_rescue_from_duplicate_handlers).and_return([
|
59
60
|
RescueFromDuplicate::UniquenessRescuer.new(
|
60
61
|
::ActiveRecord::Validations::UniquenessValidator.new(
|
61
62
|
attributes: [:name],
|
@@ -63,7 +64,7 @@ shared_examples 'missing index finding' do
|
|
63
64
|
)
|
64
65
|
),
|
65
66
|
RescueFromDuplicate::Rescuer.new(:name, scope: [:hello])
|
66
|
-
])
|
67
|
+
]))
|
67
68
|
}
|
68
69
|
|
69
70
|
it 'returns the missing indexes' do
|
@@ -88,16 +89,12 @@ describe Sqlite3Model do
|
|
88
89
|
it_behaves_like 'missing index finding'
|
89
90
|
end
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
it_behaves_like 'missing index finding'
|
95
|
-
end
|
92
|
+
describe MysqlModel do
|
93
|
+
it_behaves_like 'a model with rescued uniqueness validator'
|
94
|
+
it_behaves_like 'missing index finding'
|
96
95
|
end
|
97
96
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
it_behaves_like 'missing index finding'
|
102
|
-
end
|
97
|
+
describe PostgresqlModel do
|
98
|
+
it_behaves_like 'a model with rescued uniqueness validator'
|
99
|
+
it_behaves_like 'missing index finding'
|
103
100
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-rescue_from_duplicate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Guillaume Malette
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-04-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -151,11 +151,7 @@ files:
|
|
151
151
|
- README.md
|
152
152
|
- Rakefile
|
153
153
|
- activerecord-rescue_from_duplicate.gemspec
|
154
|
-
-
|
155
|
-
- gemfiles/Gemfile.ar-4.0
|
156
|
-
- gemfiles/Gemfile.ar-4.1
|
157
|
-
- gemfiles/Gemfile.ar-4.2
|
158
|
-
- gemfiles/Gemfile.ar-edge
|
154
|
+
- docker-compose.yml
|
159
155
|
- lib/activerecord-rescue_from_duplicate.rb
|
160
156
|
- lib/rescue_from_duplicate/active_record.rb
|
161
157
|
- lib/rescue_from_duplicate/active_record/extension.rb
|
@@ -190,7 +186,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
190
186
|
version: '0'
|
191
187
|
requirements: []
|
192
188
|
rubyforge_project:
|
193
|
-
rubygems_version: 2.
|
189
|
+
rubygems_version: 2.7.6
|
194
190
|
signing_key:
|
195
191
|
specification_version: 4
|
196
192
|
summary: Rescue from MySQL and Sqlite duplicate errors when trying to insert records
|
data/gemfiles/Gemfile.ar-3.2
DELETED
data/gemfiles/Gemfile.ar-4.0
DELETED
data/gemfiles/Gemfile.ar-4.1
DELETED
data/gemfiles/Gemfile.ar-4.2
DELETED
data/gemfiles/Gemfile.ar-edge
DELETED
@@ -1,12 +0,0 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem 'rails', github: 'rails/rails'
|
4
|
-
gem 'arel', github: 'rails/arel'
|
5
|
-
|
6
|
-
gem 'bundler', '~> 1.3'
|
7
|
-
gem 'rake'
|
8
|
-
gem 'rspec'
|
9
|
-
gem 'sqlite3'
|
10
|
-
gem 'pg', '~> 0.11'
|
11
|
-
gem 'mysql2', '~> 0.3.20'
|
12
|
-
gem 'simplecov', require: false
|