findex 0.1.0 → 0.2.0

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.
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