findex 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009 Flip Sasser
1
+ Copyright (c) 2010 Flip Sasser
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.markdown CHANGED
@@ -18,9 +18,12 @@ You may want to configure it as a gem in environment.rb instead, since you're go
18
18
 
19
19
  rake gems:install
20
20
 
21
- Now add an initializer hook. I typically use RAILS_ROOT/config/initializers/jsroutes.rb:
21
+ Now add it to your projects' Rakefile:
22
22
 
23
-
23
+ begin
24
+ require 'findex/tasks'
25
+ rescue MissingSourceFile
26
+ end
24
27
 
25
28
  ## Find Missing Indexes ##
26
29
 
@@ -50,4 +53,4 @@ First, get some instructions:
50
53
 
51
54
  Read the instructions above and start finding missing indexes! Thanks to Matt Janowski for the inspiration (http://robots.thoughtbot.com/post/163627511/a-grand-piano-for-your-violin) and Thoughtbot / Jon Yurek for the core of the indexes detection code!
52
55
 
53
- Copyright (c) 2009 Flip Sasser, released under the MIT license.
56
+ Copyright (c) 2010 Flip Sasser, released under the MIT license.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/lib/findex/tasks.rb CHANGED
@@ -5,14 +5,15 @@ require 'rake/tasklib'
5
5
  namespace :db do
6
6
  desc 'Finds indexes your application probably needs'
7
7
  task :indexes => [:environment, :prepare] do
8
- indices = Findex.get_indices(:geo, [:name, [:id, :type]], :primary, :reflection, [:type, [:boolean, :date, :datetime, :time]])
9
- Findex.send_indices(indices)
8
+ indices = @findex.get_indices(:geo, [:name, [:id, :type]], :primary, :reflection, [:type, [:boolean, :date, :datetime, :time]])
9
+ @findex.send_indices(indices)
10
10
  end
11
11
 
12
12
  task :prepare do
13
- @generate_migration = ENV['migration'] == 'true'
14
- @perform_index = ENV['perform'] == 'true'
15
- @tables = ENV['tables'] ? ENV['tables'].split(',').map(&:strip) : nil
13
+ @findex = Findex.new
14
+ @findex.generate_migration = ENV['migration'] == 'true'
15
+ @findex.perform_index = ENV['perform'] == 'true'
16
+ @findex.tables = ENV['tables'] ? ENV['tables'].split(',').map(&:strip) : nil
16
17
  Dir[File.join(Rails.root, 'app', 'models', '*.rb')].each do |file|
17
18
  load(file)
18
19
  end
@@ -21,20 +22,20 @@ namespace :db do
21
22
  namespace :indexes do
22
23
  desc 'Finds unindexed boolean columns'
23
24
  task :boolean => [:environment, :prepare] do
24
- @migration_name = 'boolean'
25
- Findex.send_indices(Findex.get_indices([:type, [:boolean]]))
25
+ @findex.migration_name = 'boolean'
26
+ @findex.send_indices(@findex.get_indices([:type, [:boolean]]))
26
27
  end
27
28
 
28
29
  desc 'Finds unindexed date, time, and datetime columns'
29
30
  task :datetime => [:environment, :prepare] do
30
- @migration_name = 'datetime'
31
- Findex.send_indices(Findex.get_indices([:type, [:date, :datetime, :time]]))
31
+ @findex.migration_name = 'datetime'
32
+ @findex.send_indices(@findex.get_indices([:type, [:date, :datetime, :time]]))
32
33
  end
33
34
 
34
35
  desc 'Finds unindexed geo columns'
35
36
  task :geo => [:environment, :prepare] do
36
- @migration_name = 'geo'
37
- Findex.send_indices(Findex.get_indices(:geo))
37
+ @findex.migration_name = 'geo'
38
+ @findex.send_indices(@findex.get_indices(:geo))
38
39
  end
39
40
 
40
41
  desc 'Prints instructions on how to use rake:db:indexes'
@@ -48,7 +49,7 @@ namespace :db do
48
49
  puts ' `rake db:indexes migration=true`'
49
50
  puts ''
50
51
  puts ' You can also target specific column types, like so:'
51
- for type in [:boolean, :datetime, :geo, :primary, :relationships]
52
+ [:boolean, :datetime, :geo, :primary, :relationships].each do |type|
52
53
  puts " `rake db:indexes:#{type}`"
53
54
  end
54
55
  puts ''
@@ -61,17 +62,17 @@ namespace :db do
61
62
 
62
63
  desc 'Generates a migration file with the recommended indexes'
63
64
  task :migration => :environment do
64
- @generate_migration = true
65
- @perform_index = false
66
- indices = Findex.get_indices(:geo, [:name, [:id, :type]], :primary, :reflection, [:type, [:boolean, :date, :datetime, :time]])
67
- Findex.send_indices(indices)
65
+ @findex.generate_migration = true
66
+ @findex.perform_index = false
67
+ indices = @findex.get_indices(:geo, [:name, [:id, :type]], :primary, :reflection, [:type, [:boolean, :date, :datetime, :time]])
68
+ @findex.send_indices(indices)
68
69
  end
69
70
 
70
71
  desc 'Finds unindexed columns matching the names you supply'
71
72
  task :names => [:environment, :prepare] do
72
73
  if ENV['names']
73
- indices = Findex.get_indices([:name, ENV['names'].split(',').map(&:strip).map(&:intern)])
74
- Findex.send_indices(indices)
74
+ indices = @findex.get_indices([:name, ENV['names'].split(',').map(&:strip).map(&:intern)])
75
+ @findex.send_indices(indices)
75
76
  else
76
77
  puts ''
77
78
  puts ' You must pass in a comma-separated collection of names like so'
@@ -82,29 +83,29 @@ namespace :db do
82
83
 
83
84
  desc 'Performs a migration with the recommended indexes'
84
85
  task :perform => :environment do
85
- @generate_migration = false
86
- @perform_index = true
87
- indices = Findex.get_indices(:geo, [:name, [:id, :type]], :primary, :reflection, [:type, [:boolean, :date, :datetime, :time]])
88
- Findex.send_indices(indices)
86
+ @findex.generate_migration = false
87
+ @findex.perform_index = true
88
+ indices = @findex.get_indices(:geo, [:name, [:id, :type]], :primary, :reflection, [:type, [:boolean, :date, :datetime, :time]])
89
+ @findex.send_indices(indices)
89
90
  end
90
91
 
91
92
  desc 'Finds unindexed primary keys'
92
93
  task :primary => [:environment, :prepare] do
93
- @migration_name = 'primary'
94
- Findex.send_indices(Findex.get_indices(:primary))
94
+ @findex.migration_name = 'primary'
95
+ @findex.send_indices(@findex.get_indices(:primary))
95
96
  end
96
97
 
97
98
  desc 'Finds unindexed relationship foreign keys'
98
99
  task :relationships => [:environment, :prepare] do
99
- @migration_name = 'relationship'
100
- Findex.send_indices(Findex.get_indices(:reflection))
100
+ @findex.migration_name = 'relationship'
101
+ @findex.send_indices(@findex.get_indices(:reflection))
101
102
  end
102
103
 
103
104
  desc 'Finds unindexed columns matching the types you supply'
104
105
  task :types => [:environment, :prepare] do
105
106
  if ENV['types']
106
- indices = Findex.get_indices([:type, ENV['types'].split(',').map(&:strip).map(&:intern)])
107
- Findex.send_indices(indices)
107
+ indices = @findex.get_indices([:type, ENV['types'].split(',').map(&:strip).map(&:intern)])
108
+ @findex.send_indices(indices)
108
109
  else
109
110
  puts ''
110
111
  puts ' You must pass in a comma-separated collection of types like so'
@@ -116,13 +117,13 @@ namespace :db do
116
117
  end
117
118
  end
118
119
 
119
- module Findex
120
- def self.check_index(*args)
120
+ class Findex
121
+ def check_index(*args)
121
122
  index = args.shift
122
123
  !args.any?{|array| array.any?{|comparison_index| comparison_index == index}}
123
124
  end
124
125
 
125
- def self.collect_indices(indices)
126
+ def collect_indices(indices)
126
127
  indices.collect{|table, columns| [table, columns.sort{|a, b|
127
128
  if a == :id
128
129
  -1
@@ -134,11 +135,11 @@ module Findex
134
135
  }]}.sort{|a, b| a[0].to_s <=> b[0].to_s}
135
136
  end
136
137
 
137
- def self.connection
138
+ def connection
138
139
  @connection ||= ActiveRecord::Base.connection
139
140
  end
140
141
 
141
- def self.get_indices(*args)
142
+ def get_indices(*args)
142
143
  indices = {}
143
144
  ObjectSpace.each_object(Class) do |model|
144
145
  next unless model.ancestors.include?(ActiveRecord::Base) && model != ActiveRecord::Base && model.table_exists?
@@ -151,7 +152,7 @@ module Findex
151
152
  collect_indices(indices)
152
153
  end
153
154
 
154
- def self.get_model_geo_indices(model, indices, existing_indices)
155
+ def get_model_geo_indices(model, indices, existing_indices)
155
156
  indices[model.table_name] ||= []
156
157
  parse_columns(model) do |column, column_name|
157
158
  if column.type == :decimal && column.name =~ /(lat|lng)/ && model.column_names.include?(alternate_column_name = column.name.gsub(/(^|_)(lat|lng)($|_)/) { "#{$1}#{$2 == 'lat' ? 'lng' : 'lat'}#{$3}"})
@@ -162,7 +163,7 @@ module Findex
162
163
  indices
163
164
  end
164
165
 
165
- def self.get_model_name_indices(model, names, indices, existing_indices)
166
+ def get_model_name_indices(model, names, indices, existing_indices)
166
167
  indices[model.table_name] ||= []
167
168
  parse_columns(model) do |column, column_name|
168
169
  if names.include?(column_name) && check_index(column_name, indices[model.table_name], existing_indices)
@@ -172,7 +173,7 @@ module Findex
172
173
  indices
173
174
  end
174
175
 
175
- def self.get_model_primary_indices(model, indices, existing_indices)
176
+ def get_model_primary_indices(model, indices, existing_indices)
176
177
  indices[model.table_name] ||= []
177
178
  parse_columns(model) do |column, column_name|
178
179
  if column.primary && check_index(column_name, indices[model.table_name], existing_indices)
@@ -182,9 +183,9 @@ module Findex
182
183
  indices
183
184
  end
184
185
 
185
- def self.get_model_reflection_indices(model, indices, existing_indices)
186
+ def get_model_reflection_indices(model, indices, existing_indices)
186
187
  indices[model.table_name] ||= []
187
- for name, reflection in model.reflections
188
+ model.reflections.each do |name, reflection|
188
189
  case reflection.macro.to_sym
189
190
  when :belongs_to
190
191
  foreign_key = reflection.primary_key_name.to_sym
@@ -202,7 +203,7 @@ module Findex
202
203
  indices
203
204
  end
204
205
 
205
- def self.get_model_type_indices(model, types, indices, existing_indices)
206
+ def get_model_type_indices(model, types, indices, existing_indices)
206
207
  indices[model.table_name] ||= []
207
208
  parse_columns(model) do |column, column_name|
208
209
  if types.include?(column.type) && check_index(column_name, indices[model.table_name], existing_indices)
@@ -212,17 +213,17 @@ module Findex
212
213
  indices
213
214
  end
214
215
 
215
- def self.parse_columns(model)
216
+ def parse_columns(model)
216
217
  model.columns.each{|column| yield(column, column.name.to_sym)} if block_given?
217
218
  end
218
219
 
219
- def self.send_indices(indices)
220
+ def send_indices(indices)
220
221
  if @generate_migration
221
222
  require 'rails_generator'
222
223
  migration_path = File.join(RAILS_ROOT, 'db', 'migrate')
223
224
  migration_number = 1
224
225
  migration_test = "add#{"_#{@migration_name}" if @migration_name}_indexes"
225
- for file in Dir[File.join(migration_path, '*.rb')]
226
+ Dir[File.join(migration_path, '*.rb')].each do |file|
226
227
  file = File.basename(file)
227
228
  next unless file =~ /^\d+_#{migration_test}(\d+)\.rb$/
228
229
  migration_number += 1
@@ -232,25 +233,29 @@ module Findex
232
233
  if migration = Dir[File.join(migration_path, "*#{migration_name}.rb")].first
233
234
  migration_up = []
234
235
  migration_down = []
235
- for table, columns in indices.sort{|a, b| a[0].to_s <=> b[0].to_s}
236
+ indices.sort{|a, b| a[0].to_s <=> b[0].to_s}.each do |table, columns|
236
237
  next if columns.empty?
237
- migration_up << "\s\s\s\s# Indices for `#{table}`"
238
- migration_down << "\s\s\s\s# Remove indices for `#{table}`"
239
- for column in columns
240
- migration_up << "\s\s\s\sadd_index :#{table}, #{column.inspect}"
241
- migration_down << "\s\s\s\sremove_index :#{table}, #{column.inspect}"
238
+ index_up = []
239
+ index_down = []
240
+ index_up.push("\s\s\s\s# Indices for `#{table}`")
241
+ index_down.push("\s\s\s\s# Remove indices for `#{table}`")
242
+ columns.each do |column|
243
+ index_up.push("\s\s\s\sadd_index :#{table}, #{column.inspect}")
244
+ index_down.push("\s\s\s\sremove_index :#{table}, #{column.inspect}")
242
245
  end
246
+ migration_up.push(index_up.join("\n"))
247
+ migration_down.push(index_down.join("\n"))
243
248
  end
244
- migration_contents = File.read(migration).gsub("def self.up", "def self.up\n#{migration_up.join("\n")}").gsub("def self.down", "def self.down\n#{migration_down.join("\n")}")
249
+ migration_contents = File.read(migration).gsub("def self.up", "def self.up\n#{migration_up.join("\n\n")}").gsub("def self.down", "def self.down\n#{migration_down.join("\n\n")}")
245
250
  File.open(migration, 'w+') do |file|
246
251
  file.puts migration_contents
247
- end
252
+ end
248
253
  end
249
254
  else
250
- for table, columns in indices.sort{|a, b| a[0].to_s <=> b[0].to_s}
255
+ indices.sort{|a, b| a[0].to_s <=> b[0].to_s}.each do |table, columns|
251
256
  next if columns.empty?
252
257
  puts "\s\s# Indices for `#{table}`"
253
- for column in columns
258
+ columns.each do |column|
254
259
  if @perform_index
255
260
  ActiveRecord::Migration.add_index(table, column)
256
261
  else
@@ -261,4 +266,20 @@ module Findex
261
266
  end
262
267
  end
263
268
  end
269
+
270
+ def generate_migration=(value)
271
+ @generate_migration = !!value
272
+ end
273
+
274
+ def perform_index=(value)
275
+ @perform_index = !!value
276
+ end
277
+
278
+ def tables=(tables)
279
+ @tables = tables
280
+ end
281
+
282
+ def migration_name=(value)
283
+ @migration_name = value
284
+ end
264
285
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: findex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Flip Sasser