lol_dba 2.1.5 → 2.1.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +179 -0
  3. data/.gitignore +1 -1
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +7 -0
  6. data/.travis.yml +16 -9
  7. data/Appraisals +19 -12
  8. data/Gemfile +1 -8
  9. data/Gemfile.lock +60 -59
  10. data/README.md +5 -2
  11. data/Rakefile +4 -4
  12. data/bin/lol_dba +2 -2
  13. data/gemfiles/rails_3_2.gemfile +0 -3
  14. data/gemfiles/rails_3_2.gemfile.lock +33 -31
  15. data/gemfiles/rails_4_0.gemfile +0 -3
  16. data/gemfiles/rails_4_0.gemfile.lock +31 -27
  17. data/gemfiles/rails_4_1.gemfile +0 -3
  18. data/gemfiles/rails_4_1.gemfile.lock +29 -26
  19. data/gemfiles/rails_4_2.gemfile +0 -3
  20. data/gemfiles/rails_4_2.gemfile.lock +52 -48
  21. data/gemfiles/rails_5_0.gemfile +0 -3
  22. data/gemfiles/rails_5_0.gemfile.lock +55 -51
  23. data/gemfiles/rails_5_1.gemfile +0 -3
  24. data/gemfiles/rails_5_1.gemfile.lock +57 -53
  25. data/gemfiles/rails_5_2.gemfile +9 -0
  26. data/gemfiles/rails_5_2.gemfile.lock +115 -0
  27. data/lib/lol_dba/cli.rb +26 -15
  28. data/lib/lol_dba/index_finding/belongs_to.rb +32 -0
  29. data/lib/lol_dba/index_finding/error_logging.rb +15 -0
  30. data/lib/lol_dba/index_finding/has_and_belongs_to_many.rb +20 -0
  31. data/lib/lol_dba/index_finding/has_many.rb +47 -0
  32. data/lib/lol_dba/index_finding/index_finder.rb +81 -0
  33. data/lib/lol_dba/index_finding/migration_formatter.rb +50 -0
  34. data/lib/lol_dba/index_finding/relation_inspector.rb +30 -0
  35. data/lib/lol_dba/index_finding/relation_inspector_factory.rb +13 -0
  36. data/lib/lol_dba/rails_compatibility.rb +47 -0
  37. data/lib/lol_dba/railtie.rb +2 -2
  38. data/lib/lol_dba/sql_migrations/migration.rb +51 -0
  39. data/lib/lol_dba/sql_migrations/migration_mocker.rb +70 -0
  40. data/lib/lol_dba/sql_migrations/sql_generator.rb +49 -0
  41. data/lib/lol_dba/sql_migrations/writer.rb +29 -0
  42. data/lib/lol_dba/version.rb +1 -1
  43. data/lib/lol_dba.rb +14 -188
  44. data/lib/tasks/lol_dba.rake +7 -8
  45. data/lol_dba.gemspec +19 -16
  46. data/spec/associations_index_spec.rb +43 -56
  47. data/spec/fixtures/app/models/address.rb +0 -1
  48. data/spec/fixtures/app/models/billable_week.rb +1 -3
  49. data/spec/fixtures/app/models/company.rb +0 -1
  50. data/spec/fixtures/app/models/complex_billable_week.rb +0 -1
  51. data/spec/fixtures/app/models/complex_timesheet.rb +0 -1
  52. data/spec/fixtures/app/models/country.rb +1 -1
  53. data/spec/fixtures/app/models/favourite.rb +0 -2
  54. data/spec/fixtures/app/models/freelancer.rb +1 -3
  55. data/spec/fixtures/app/models/gift.rb +0 -2
  56. data/spec/fixtures/app/models/god.rb +1 -1
  57. data/spec/fixtures/app/models/project.rb +0 -2
  58. data/spec/fixtures/app/models/timesheet.rb +1 -3
  59. data/spec/fixtures/app/models/user.rb +0 -2
  60. data/spec/fixtures/app/models/worker.rb +0 -1
  61. data/spec/fixtures/app/models/worker_user.rb +2 -3
  62. data/spec/fixtures/schema.rb +53 -53
  63. data/spec/migration_formatter_spec.rb +66 -0
  64. data/spec/spec_helper.rb +17 -9
  65. data/spec/sql_generator_spec.rb +9 -0
  66. metadata +88 -19
  67. data/lib/lol_dba/migration.rb +0 -40
  68. data/lib/lol_dba/sql_generator.rb +0 -96
  69. data/lib/lol_dba/writer.rb +0 -25
  70. data/spec/common_function_spec.rb +0 -96
@@ -0,0 +1,47 @@
1
+ module LolDba
2
+ class RailsCompatibility
3
+ class << self
4
+ def migrator
5
+ ActiveRecord::Migrator.new(:up, migrations_path)
6
+ end
7
+
8
+ def tables
9
+ if ::ActiveRecord::VERSION::MAJOR >= 5
10
+ ActiveRecord::Base.connection.data_sources
11
+ else
12
+ ActiveRecord::Base.connection.tables
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def migrations_path
19
+ ar_version = Gem::Version.new(ActiveRecord::VERSION::STRING)
20
+ if ar_version >= Gem::Version.new('5.2.0')
21
+ ar_5_2_0_migrations_path
22
+ elsif ar_version >= Gem::Version.new('5.0.0')
23
+ ar_5_0_0_migrations_path
24
+ elsif ar_version >= Gem::Version.new('4.0.0')
25
+ ar_4_0_0_migrations_path
26
+ else
27
+ ActiveRecord::Migrator.migrations_path
28
+ end
29
+ end
30
+
31
+ def ar_5_2_0_migrations_path
32
+ paths = ActiveRecord::Migrator.migrations_paths
33
+ ActiveRecord::MigrationContext.new(paths).migrations
34
+ end
35
+
36
+ def ar_5_0_0_migrations_path
37
+ paths = ActiveRecord::Migrator.migrations_paths
38
+ ActiveRecord::Migrator.migrations(paths)
39
+ end
40
+
41
+ def ar_4_0_0_migrations_path
42
+ path = ActiveRecord::Migrator.migrations_path
43
+ ActiveRecord::Migrator.migrations(path)
44
+ end
45
+ end
46
+ end
47
+ end
@@ -4,7 +4,7 @@ require 'rails'
4
4
  module LolDba
5
5
  class Railtie < Rails::Railtie
6
6
  rake_tasks do
7
- load "tasks/lol_dba.rake"
7
+ load 'tasks/lol_dba.rake'
8
8
  end
9
9
  end
10
- end
10
+ end
@@ -0,0 +1,51 @@
1
+ module LolDba
2
+ class Migration
3
+ attr_reader :full_name, :writer
4
+
5
+ def initialize(migration_file)
6
+ @full_name = File.basename(migration_file, '.rb')
7
+ @writer = LolDba::Writer.new("#{migration}.sql")
8
+ require Rails.root.join(migration_file)
9
+ end
10
+
11
+ def number
12
+ /^(\d+)_(.*)$/.match(full_name)[1]
13
+ end
14
+
15
+ def name
16
+ /^(\d+)_(.*)$/.match(full_name)[2]
17
+ end
18
+
19
+ def to_s
20
+ full_name
21
+ end
22
+
23
+ def migration_class
24
+ name.camelize.split('.')[0].constantize
25
+ end
26
+
27
+ def up
28
+ generate_instead_of_executing do
29
+ migration_class.migrate(:up)
30
+ connection.execute("INSERT INTO schema_migrations (version) VALUES (#{number})")
31
+ end
32
+ end
33
+
34
+ def down
35
+ generate_instead_of_executing do
36
+ migration_class.migrate(:down)
37
+ connection.execute("DELETE FROM schema_migrations WHERE version = #{number}")
38
+ end
39
+ end
40
+
41
+ def connection
42
+ ActiveRecord::Base.connection
43
+ end
44
+
45
+ def generate_instead_of_executing
46
+ LolDba::MigrationMocker.redefine_migration_methods(writer)
47
+ yield
48
+ LolDba::MigrationMocker.reset_methods
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,70 @@
1
+ module LolDba
2
+ class MigrationMocker
3
+ def initialize(writer)
4
+ @writer = writer
5
+ end
6
+
7
+ def redefine_migration_methods
8
+ save_original_methods
9
+ redefine_metadata_methods
10
+ redefine_execute_methods(:execute)
11
+ # needed for activerecord-sqlserver-adapter
12
+ redefine_execute_methods(:do_execute)
13
+ end
14
+
15
+ def self.reset_methods
16
+ methods_to_modify.each do |method_name|
17
+ begin
18
+ connection_class.send(:alias_method, method_name, "orig_#{method_name}".to_sym)
19
+ rescue StandardError
20
+ nil
21
+ end
22
+ end
23
+ end
24
+
25
+ private_class_method
26
+
27
+ def self.connection
28
+ ActiveRecord::Base.connection
29
+ end
30
+
31
+ def self.redefine_connection_method(method, &block)
32
+ connection.class.send(:define_method, method, block)
33
+ end
34
+
35
+ def self.methods_to_modify
36
+ %i[execute do_execute rename_column change_column column_for tables indexes select_all] & connection.methods
37
+ end
38
+
39
+ private
40
+
41
+ def save_original_methods
42
+ methods_to_modify.each do |method_name|
43
+ orig_name = "orig_#{method_name}".to_sym
44
+ connection.class.send(:alias_method, orig_name, method_name)
45
+ end
46
+ end
47
+
48
+ def redefine_metadata_methods
49
+ redefine_connection_method(:column_for) { |*args| args.last }
50
+ redefine_connection_method(:change_column) { |*_args| [] }
51
+ redefine_connection_method(:rename_column) { |*_args| [] }
52
+ redefine_connection_method(:tables) { |*_args| [] }
53
+ redefine_connection_method(:select_all) { |*_args| [] }
54
+ redefine_connection_method(:indexes) { |*_args| [] }
55
+ # returns always the default(args[2])
56
+ redefine_connection_method(:index_name_exists?) { |*args| args[2] }
57
+ end
58
+
59
+ def redefine_execute_methods(name)
60
+ redefine_connection_method(name) do |*args|
61
+ query = args.first
62
+ if query =~ /SELECT "schema_migrations"."version"/ || query =~ /^SHOW/
63
+ orig_execute(*args)
64
+ else
65
+ @writer.write(to_sql(query, args.last))
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,49 @@
1
+ module LolDba
2
+ class SqlGenerator
3
+ def initialize(which)
4
+ @which = which
5
+ end
6
+
7
+ def run
8
+ LolDba::Writer.reset_output_dir
9
+ migrations(@which).each do |file|
10
+ LolDba::Migration.new(file).up
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def migrations(which)
17
+ if which == 'all'
18
+ migrator.migrations.collect(&:filename)
19
+ elsif which == 'pending'
20
+ pending_migrations
21
+ else
22
+ specific_migration(which)
23
+ end
24
+ end
25
+
26
+ def pending_migrations
27
+ pending = migrator.pending_migrations
28
+ if pending.empty?
29
+ puts 'No pending migrations.'
30
+ exit
31
+ end
32
+ pending.collect(&:filename)
33
+ end
34
+
35
+ def specific_migration(which)
36
+ migration = migrator.migrations.find { |m| m.version == which.to_i }
37
+ if migration.present?
38
+ [migration.filename]
39
+ else
40
+ puts "There are no migrations for version #{which}."
41
+ exit
42
+ end
43
+ end
44
+
45
+ def migrator
46
+ LolDba::RailsCompatibility.migrator
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,29 @@
1
+ module LolDba
2
+ class Writer
3
+ def initialize(file_name)
4
+ @file_name = file_name
5
+ end
6
+
7
+ def self.reset_output_dir
8
+ FileUtils.rm_rf output_dir
9
+ Dir.mkdir output_dir
10
+ end
11
+
12
+ def write(string)
13
+ return unless @file_name.present?
14
+ File.open(path, 'a') { |file| file << string << ";\n" }
15
+ end
16
+
17
+ private_class_method
18
+
19
+ def self.output_dir
20
+ File.join(Rails.root, 'db', 'migrate_sql')
21
+ end
22
+
23
+ private
24
+
25
+ def path
26
+ File.join(output_dir, @file_name)
27
+ end
28
+ end
29
+ end
@@ -1,3 +1,3 @@
1
1
  module LolDba
2
- VERSION = "2.1.5" unless defined? LolDba::VERSION
2
+ VERSION = '2.1.6'.freeze unless defined? LolDba::VERSION
3
3
  end
data/lib/lol_dba.rb CHANGED
@@ -1,190 +1,16 @@
1
1
  module LolDba
2
-
3
- require "lol_dba/writer"
4
- require "lol_dba/migration"
5
- require "lol_dba/railtie.rb" if defined?(Rails)
6
-
7
- def self.form_migration_content(migration_name, index_array)
8
- migration = <<EOM
9
- * run `rails g migration #{migration_name}` and add the following content:
10
-
11
-
12
- class #{migration_name} < ActiveRecord::Migration
13
- def change
14
- #{index_array.sort.uniq.join("\n ")}
15
- end
16
- end
17
- EOM
18
- end
19
-
20
- def self.get_through_foreign_key(target_class, reflection_options)
21
- # has_many :through
22
- reflection = target_class.reflections[reflection_options.options[:through].to_s]
23
-
24
- # has_and_belongs_to_many
25
- reflection = reflection_options unless reflection
26
-
27
- # Guess foreign key?
28
- if reflection.options[:foreign_key]
29
- reflection.options[:foreign_key]
30
- else
31
- "#{target_class.name.tableize.singularize}_id"
32
- end
33
- end
34
-
35
- def self.tables
36
- ::ActiveRecord::VERSION::MAJOR >= 5 ? ActiveRecord::Base.connection.data_sources : ActiveRecord::Base.connection.tables
37
- end
38
-
39
- def self.validate_and_sort_indexes(indexes_required)
40
- missing_indexes = {}
41
- warning_messages = ""
42
- indexes_required.each do |table_name, foreign_keys|
43
- next if foreign_keys.blank?
44
- begin
45
- if tables.include?(table_name.to_s)
46
- existing_indexes = ActiveRecord::Base.connection.indexes(table_name.to_sym).collect {|index| index.columns.size > 1 ? index.columns : index.columns.first}
47
- existing_indexes += Array(ActiveRecord::Base.connection.primary_key(table_name.to_s))
48
- keys_to_add = foreign_keys.uniq - existing_indexes
49
- missing_indexes[table_name] = keys_to_add unless keys_to_add.empty?
50
- else
51
- warning_messages << "BUG: table '#{table_name.to_s}' does not exist, please report this bug.\n "
52
- end
53
- rescue Exception => e
54
- puts "ERROR: #{e}"
55
- end
56
- end
57
- return missing_indexes, warning_messages
58
- end
59
-
60
- def self.form_data_for_migration(missing_indexes)
61
- add = []
62
- missing_indexes.each do |table_name, keys_to_add|
63
- keys_to_add.each do |key|
64
- next if key.blank?
65
- next if key_exists?(table_name,key)
66
- if key.is_a?(Array)
67
- keys = key.collect {|k| ":#{k}"}
68
- add << "add_index :#{table_name}, [#{keys.join(', ')}]"
69
- else
70
- add << "add_index :#{table_name}, :#{key}"
71
- end
72
- end
73
- end
74
- return add
75
- end
76
-
77
- def self.check_for_indexes(migration_format = false)
78
- if defined?(Rails) && !Rails.env.test?
79
- Rails.application.eager_load!
80
- end
81
-
82
- model_classes = []
83
- ActiveRecord::Base.descendants.each do |obj|
84
- if Class == obj.class && (!defined?(ActiveRecord::SessionStore::Session) || obj != ActiveRecord::SessionStore::Session)
85
- model_classes << obj
86
- end
87
- end
88
-
89
- @index_migrations = Hash.new([])
90
-
91
- model_classes.each do |class_name|
92
- unless class_name.descends_from_active_record?
93
- index_name = [class_name.inheritance_column, class_name.base_class.primary_key].sort
94
- @index_migrations[class_name.base_class.table_name] += [index_name]
95
- end
96
- reflections = class_name.reflections.stringify_keys
97
- reflections.each_pair do |reflection_name, reflection_options|
98
- begin
99
- index_name = ""
100
- case reflection_options.macro
101
- when :belongs_to
102
- # polymorphic?
103
- table_name = class_name.table_name
104
- if reflection_options.options[:polymorphic]
105
- poly_type = "#{reflection_options.name.to_s}_type"
106
- poly_id = "#{reflection_options.name.to_s}_id"
107
- index_name = [poly_type, poly_id].sort
108
- else
109
- foreign_key = reflection_options.options[:foreign_key]
110
- foreign_key ||= reflection_options.respond_to?(:primary_key_name) ? reflection_options.primary_key_name : reflection_options.foreign_key
111
- next if foreign_key == "left_side_id" # not a clue why rails 4.1+ creates this left_side_id thing
112
- index_name = foreign_key.to_s
113
- end
114
- when :has_and_belongs_to_many
115
- table_name = reflection_options.options[:join_table]
116
- table_name ||= [class_name.table_name, reflection_name.to_s].sort.join('_')
117
- association_foreign_key = reflection_options.options[:association_foreign_key] ||= "#{reflection_name.to_s.singularize}_id"
118
-
119
- foreign_key = get_through_foreign_key(class_name, reflection_options)
120
- index_name = [association_foreign_key, foreign_key].map(&:to_s).sort
121
- when :has_many
122
- through = reflection_options.options[:through]
123
- next unless through && reflections[through.to_s] # has_many tables are threaten by the other side of the relation
124
-
125
- through_class = reflections[through.to_s].klass
126
- table_name = through_class.table_name
127
-
128
- foreign_key = get_through_foreign_key(class_name, reflection_options)
129
-
130
- through_reflections = through_class.reflections.stringify_keys
131
- if source = reflection_options.options[:source]
132
- association_reflection = through_reflections[source.to_s]
133
- next if association_reflection.options[:polymorphic]
134
- association_foreign_key = get_through_foreign_key(association_reflection.klass, reflection_options)
135
- elsif belongs_to_reflections = through_reflections[reflection_name.singularize]
136
- # go to joining model through has_many and find belongs_to
137
- association_foreign_key = belongs_to_reflections.options[:foreign_key]
138
- end
139
-
140
- #FIXME currently we don't support :through => :another_regular_has_many_and_non_through_relation
141
- next if association_foreign_key.nil?
142
- index_name = [association_foreign_key, foreign_key].map(&:to_s).sort
143
- end
144
-
145
- unless index_name == "" || reflection_options.options.include?(:class)
146
- @index_migrations[table_name.to_s] += [index_name]
147
- end
148
-
149
- rescue Exception => e
150
- puts "Some errors here:"
151
- puts "Please, create an issue with the following information here https://github.com/plentz/lol_dba/issues:"
152
- puts "***************************"
153
- puts "Class: #{class_name}"
154
- puts "Association type: #{reflection_options.macro}"
155
- puts "Association options: #{reflection_options.options}"
156
- puts "Exception: #{e.message}"
157
- e.backtrace.each{|trace| puts trace}
158
- end
159
- end # case end
160
- end # each_pair end
161
- missing_indexes, warning_messages = validate_and_sort_indexes(@index_migrations)
162
-
163
- end
164
-
165
- def self.key_exists?(table,key_columns)
166
- result = (Array(key_columns) - ActiveRecord::Base.connection.indexes(table).map { |i| i.columns }.flatten)
167
- #FIXME: Primary key always indexes, but ActiveRecord::Base.connection.indexes not show it!
168
- result = result - Array(ActiveRecord::Base.connection.primary_key(table)) if result
169
- result.empty?
170
- end
171
-
172
- def self.puts_migration_content(migration_name, indexes, warning_messages)
173
- puts warning_messages
174
- add = form_data_for_migration(indexes)
175
- if add.blank?
176
- puts "Yey, no missing indexes found!"
177
- else
178
- tip = "* TIP: if you have a problem with the index name('index name too long') you can solve with the :name option. "
179
- tip += "Something like :name => 'my_index'."
180
- puts tip
181
- puts form_migration_content(migration_name, add)
182
- end
183
- end
184
-
185
- def self.simple_migration
186
- missing_indexes, warning_messages = check_for_indexes(true)
187
-
188
- puts_migration_content("AddMissingIndexes", missing_indexes, warning_messages)
189
- end
2
+ require 'lol_dba/sql_migrations/writer'
3
+ require 'lol_dba/sql_migrations/migration'
4
+ require 'lol_dba/sql_migrations/migration_mocker'
5
+ require 'lol_dba/sql_migrations/sql_generator'
6
+ require 'lol_dba/index_finding/migration_formatter'
7
+ require 'lol_dba/index_finding/relation_inspector'
8
+ require 'lol_dba/index_finding/index_finder'
9
+ require 'lol_dba/index_finding/belongs_to'
10
+ require 'lol_dba/index_finding/error_logging'
11
+ require 'lol_dba/index_finding/has_and_belongs_to_many'
12
+ require 'lol_dba/index_finding/has_many'
13
+ require 'lol_dba/index_finding/relation_inspector_factory'
14
+ require 'lol_dba/rails_compatibility'
15
+ require 'lol_dba/railtie.rb' if defined?(Rails)
190
16
  end
@@ -2,14 +2,13 @@ require 'lol_dba'
2
2
  require 'lol_dba/sql_generator'
3
3
 
4
4
  namespace :db do
5
- desc "Display a migration for adding/removing all necessary indexes based on associations"
6
- task :find_indexes => :environment do
7
- LolDba.simple_migration
5
+ desc 'Display a migration for adding/removing all necessary indexes based on associations'
6
+ task find_indexes: :environment do
7
+ LolDba::IndexFinder.run
8
8
  end
9
- desc "Generate .sql files for your migrations inside db/migrate_sql folder"
10
- task :migrate_sql, [:which] => :environment do |t, args|
11
- args.with_defaults(:which => 'all')
12
- LolDba::SqlGenerator.generate(args[:which])
9
+ desc 'Generate .sql files for your migrations inside db/migrate_sql folder'
10
+ task :migrate_sql, [:which] => :environment do |_t, args|
11
+ args.with_defaults(which: 'all')
12
+ LolDba::SqlGenerator.run(args[:which])
13
13
  end
14
-
15
14
  end
data/lol_dba.gemspec CHANGED
@@ -1,27 +1,30 @@
1
- $LOAD_PATH << File.join(File.dirname(__FILE__), "lib")
2
- require "lol_dba/version.rb"
1
+ $LOAD_PATH << File.join(File.dirname(__FILE__), 'lib')
2
+ require 'lol_dba/version.rb'
3
3
 
4
4
  Gem::Specification.new do |s|
5
- s.name = "lol_dba"
5
+ s.name = 'lol_dba'
6
6
  s.version = LolDba::VERSION
7
7
  s.platform = Gem::Platform::RUBY
8
8
 
9
- s.authors = ["Diego Plentz", "Elad Meidar", "Eric Davis", "Muness Alrubaie", "Vladimir Sharshov"]
10
- s.email = ["diego@plentz.org", "elad@eizesus.com", "", "vsharshov@gmail.com"]
11
- s.homepage = "https://github.com/plentz/lol_dba"
12
- s.summary = "A small package of rake tasks to track down missing database indexes and generate sql migration scripts"
13
- s.description = "lol_dba is a small package of rake tasks that scan your application models and displays a list of columns that probably should be indexed. Also, it can generate .sql migration scripts."
14
- s.license = "MIT"
9
+ s.authors = ['Diego Plentz']
10
+ s.email = ['diego@plentz.io']
11
+ s.homepage = 'https://github.com/plentz/lol_dba'
12
+ s.summary = 'A small package of rake tasks to track down missing database indexes and generate sql migration scripts'
13
+ s.description = 'lol_dba is a small package of rake tasks that scan your application models and displays a list of columns that probably should be indexed. Also, it can generate .sql migration scripts.'
14
+ s.license = 'MIT'
15
15
 
16
16
  s.files = `git ls-files`.split("\n")
17
- s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
17
+ s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
- s.require_paths = ["lib", "lib/lol_dba"]
19
+ s.require_paths = ['lib', 'lib/lol_dba']
20
20
 
21
- s.required_ruby_version = ">= 2.0.0"
22
- s.add_dependency "activerecord", ">= 3.0"
23
- s.add_dependency "actionpack", ">= 3.0"
24
- s.add_dependency "railties", ">= 3.0"
21
+ s.required_ruby_version = '>= 2.0.0'
22
+ s.add_dependency 'actionpack', '>= 3.0', '< 6.0'
23
+ s.add_dependency 'activerecord', '>= 3.0', '< 6.0'
24
+ s.add_dependency 'railties', '>= 3.0', '< 6.0'
25
25
 
26
- s.add_development_dependency "appraisal"
26
+ s.add_development_dependency 'appraisal', '~> 2.2'
27
+ s.add_development_dependency 'simplecov', '~> 0.1'
28
+ s.add_development_dependency 'sqlite3', '~> 1.3.5'
29
+ s.add_development_dependency 'rspec-rails'
27
30
  end