tire 0.5.5 → 0.5.6

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -11,8 +11,7 @@ communicating by JSON over RESTful HTTP, based on [Lucene](http://lucene.apache.
11
11
 
12
12
  This Readme provides a brief overview of _Tire's_ features. The more detailed documentation is at <http://karmi.github.com/tire/>.
13
13
 
14
- Both of these documents contain a lot of information. Please set aside some time to read them thoroughly, before you blindly dive into „somehow making it work“. Just skimming through it **won't work** for you. For more information, please refer to the [integration test suite](https://github.com/karmi/tire/tree/master/test/integration)
15
- and [issues](https://github.com/karmi/tire/issues).
14
+ Both of these documents contain a lot of information. Please set aside some time to read them thoroughly, before you blindly dive into „somehow making it work“. Just skimming through it **won't work** for you. For more information, please see the project [Wiki](https://github.com/karmi/tire/wiki/_pages), search the [issues](https://github.com/karmi/tire/issues), and refer to the [integration test suite](https://github.com/karmi/tire/tree/master/test/integration).
16
15
 
17
16
  Installation
18
17
  ------------
@@ -632,8 +631,9 @@ in addition to model instance, use the `each_with_hit` method:
632
631
  # One (score: 0.300123)
633
632
  ```
634
633
 
635
- Note that _Tire_ search results are fully compatible with [`will_paginate`](https://github.com/mislav/will_paginate),
636
- so you can pass all the usual parameters to the `search` method in the controller:
634
+ Note that _Tire_ search results are fully compatible with [_WillPaginate_](https://github.com/mislav/will_paginate)
635
+ and [_Kaminari_](https://github.com/amatsuda/kaminari), so you can pass all the usual parameters to the
636
+ `search` method in the controller:
637
637
 
638
638
  ```ruby
639
639
  @articles = Article.search params[:q], :page => (params[:page] || 1)
@@ -648,20 +648,15 @@ OK. Chances are, you have lots of records stored in your database. How will you
648
648
  This way, however, all your records are loaded into memory, serialized into JSON,
649
649
  and sent down the wire to _Elasticsearch_. Not practical, you say? You're right.
650
650
 
651
- Provided your model implements some sort of _pagination_ — and it probably does —, you can just run:
651
+ When your model is an `ActiveRecord::Base` or `Mongoid::Document` one, or when it implements
652
+ some sort of pagination, you can just run:
652
653
 
653
654
  ```ruby
654
655
  Article.import
655
656
  ```
656
657
 
657
- In this case, the `Article.paginate` method is called, and your records are sent to the index
658
- in chunks of 1000. If that number doesn't suit you, just provide a better one:
659
-
660
- ```ruby
661
- Article.import :per_page => 100
662
- ```
663
-
664
- Any other parameters you provide to the `import` method are passed down to the `paginate` method.
658
+ Depending on the setup of your model, either `find_in_batches`, `limit..skip` or pagination is used
659
+ to import your data.
665
660
 
666
661
  Are we saying you have to fiddle with this thing in a `rails console` or silly Ruby scripts? No.
667
662
  Just call the included _Rake_ task on the command line:
@@ -677,13 +672,6 @@ provided by the `mapping` block in your model):
677
672
  $ rake environment tire:import CLASS='Article' FORCE=true
678
673
  ```
679
674
 
680
- When importing records from multiple tables, you can fight the n+1 queries problem by passing
681
- `include` parameters to the `paginate` method:
682
-
683
- ```bash
684
- rake environment tire:import PARAMS='{:include => ["comments"]}' CLASS=Article FORCE=true
685
- ```
686
-
687
675
  When you'll spend more time with _Elasticsearch_, you'll notice how
688
676
  [index aliases](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html)
689
677
  are the best idea since the invention of inverted index.
@@ -695,21 +683,16 @@ You can index your data into a fresh index (and possibly update an alias once ev
695
683
 
696
684
  Finally, consider the Rake importing task just a convenient starting point. If you're loading
697
685
  substantial amounts of data, want better control on which data will be indexed, etc., use the
698
- lower-level Tire API with eg. `ActiveRecordBase#find_in_batches`:
686
+ lower-level Tire API with eg. `ActiveRecordBase#find_in_batches` directly:
699
687
 
700
688
  ```ruby
701
- Article.where("published_on > ?", Time.parse("2012-10-01")).find_in_batches do |group|
702
- Tire.index("articles").import group
689
+ Article.where("published_on > ?", Time.parse("2012-10-01")).find_in_batches(include: authors) do |batch|
690
+ Tire.index("articles").import batch
703
691
  end
704
692
  ```
705
-
706
- OK. All this time we have been talking about `ActiveRecord` models, since
707
- it is a reasonable _Rails_' default for the storage layer.
708
-
709
- But what if you use another database such as [MongoDB](http://www.mongodb.org/),
710
- another object mapping library, such as [Mongoid](http://mongoid.org/) or [MongoMapper](http://mongomapper.com/)?
711
-
712
- Well, things stay mostly the same:
693
+ If you're using a different database, such as [MongoDB](http://www.mongodb.org/),
694
+ another object mapping library, such as [Mongoid](http://mongoid.org/) or [MongoMapper](http://mongomapper.com/),
695
+ things stay mostly the same:
713
696
 
714
697
  ```ruby
715
698
  class Article
@@ -779,7 +762,7 @@ and extensions to the core _Tire_ functionality — be sure to check them out.
779
762
  Other Clients
780
763
  -------------
781
764
 
782
- Check out [other _Elasticsearch_ clients](http://www.elasticsearch.org/guide/appendix/clients.html).
765
+ Check out [other _Elasticsearch_ clients](http://www.elasticsearch.org/guide/clients/).
783
766
 
784
767
 
785
768
  Feedback
@@ -7,49 +7,53 @@ module Tire
7
7
  module Client
8
8
 
9
9
  class Curb
10
- @client = ::Curl::Easy.new
11
- @client.resolve_mode = :ipv4
12
-
13
- # @client.verbose = true
10
+ def self.client
11
+ Thread.current[:client] ||= begin
12
+ client = ::Curl::Easy.new
13
+ client.resolve_mode = :ipv4
14
+ # client.verbose = true
15
+ client
16
+ end
17
+ end
14
18
 
15
19
  def self.get(url, data=nil)
16
- @client.url = url
20
+ client.url = url
17
21
 
18
22
  # FIXME: Curb cannot post bodies with GET requests?
19
23
  # Roy Fielding seems to approve:
20
24
  # <http://tech.groups.yahoo.com/group/rest-discuss/message/9962>
21
25
  if data
22
- @client.post_body = data
23
- @client.http_post
26
+ client.post_body = data
27
+ client.http_post
24
28
  else
25
- @client.http_get
29
+ client.http_get
26
30
  end
27
- Response.new @client.body_str, @client.response_code
31
+ Response.new client.body_str, client.response_code
28
32
  end
29
33
 
30
34
  def self.post(url, data)
31
- @client.url = url
32
- @client.post_body = data
33
- @client.http_post
34
- Response.new @client.body_str, @client.response_code
35
+ client.url = url
36
+ client.post_body = data
37
+ client.http_post
38
+ Response.new client.body_str, client.response_code
35
39
  end
36
40
 
37
41
  def self.put(url, data)
38
- @client.url = url
39
- @client.http_put data
40
- Response.new @client.body_str, @client.response_code
42
+ client.url = url
43
+ client.http_put data
44
+ Response.new client.body_str, client.response_code
41
45
  end
42
46
 
43
47
  def self.delete(url)
44
- @client.url = url
45
- @client.http_delete
46
- Response.new @client.body_str, @client.response_code
48
+ client.url = url
49
+ client.http_delete
50
+ Response.new client.body_str, client.response_code
47
51
  end
48
52
 
49
53
  def self.head(url)
50
- @client.url = url
51
- @client.http_head
52
- Response.new @client.body_str, @client.response_code
54
+ client.url = url
55
+ client.http_head
56
+ Response.new client.body_str, client.response_code
53
57
  end
54
58
 
55
59
  end
data/lib/tire/index.rb CHANGED
@@ -245,12 +245,13 @@ module Tire
245
245
  case
246
246
  when method = options.delete(:method)
247
247
  options = {:page => 1, :per_page => 1000}.merge options
248
- while documents = klass_or_collection.send(method.to_sym, options.merge(:page => options[:page])) \
249
- and documents.to_a.length > 0
248
+ while (documents = klass_or_collection.send(method.to_sym, options.merge(:page => options[:page]))) \
249
+ && documents.to_a.length > 0
250
250
 
251
251
  documents = yield documents if block_given?
252
252
 
253
253
  bulk_store documents, options
254
+ GC.start
254
255
  options[:page] += 1
255
256
  end
256
257
 
@@ -259,8 +260,8 @@ module Tire
259
260
  bulk_store documents, options
260
261
 
261
262
  else
262
- raise ArgumentError, "Please pass either an Enumerable compatible class, or a collection object" +
263
- "with a method for fetching records in batches (such as 'paginate')"
263
+ raise ArgumentError, "Please pass either an Enumerable compatible class, or a collection object " +
264
+ "with a method for fetching records in batches (such as 'paginate')."
264
265
  end
265
266
  end
266
267
 
@@ -1,27 +1,114 @@
1
-
2
1
  module Tire
3
2
  module Model
4
3
 
5
- # Provides support for easy importing of large ActiveRecord- and ActiveModel-bound
6
- # recordsets into model index.
4
+ # Provides support for efficient and effective importing of large recordsets into Elasticsearch.
5
+ #
6
+ # Tire will use dedicated strategies for fetching records in batches when ActiveRecord or Mongoid models are detected.
7
+ #
8
+ # Two dedicated strategies for popular pagination libraries are also provided: WillPaginate and Kaminari.
9
+ # These could be used in situations where your model is neither ActiveRecord nor Mongoid based.
7
10
  #
8
- # Relies on pagination support in your model, namely the `paginate` class method.
11
+ # Note, that it's always possible to use the `Tire::Index#import` method directly.
9
12
  #
10
- # Please refer to the relevant of the README for more information.
13
+ # @note See `Tire::Import::Strategy`.
11
14
  #
12
15
  module Import
13
16
 
14
17
  module ClassMethods
15
-
16
18
  def import options={}, &block
17
- options = { :method => 'paginate' }.update options
18
- index = options[:index] ? Tire::Index.new(options.delete(:index)) : self.index
19
- index.import klass, options, &block
19
+ strategy = Strategy.from_class(klass, options)
20
+ strategy.import &block
21
+ end
22
+ end
23
+
24
+ # Importing strategies for common persistence frameworks (ActiveModel, Mongoid), as well as
25
+ # pagination libraries (WillPaginate, Kaminari).
26
+ #
27
+ module Strategy
28
+ def self.from_class(klass, options={})
29
+ case
30
+ when defined?(::ActiveRecord) && klass.ancestors.include?(::ActiveRecord::Base)
31
+ ActiveRecord.new klass, options
32
+ when defined?(::Mongoid::Document) && klass.ancestors.include?(::Mongoid::Document)
33
+ Mongoid.new klass, options
34
+ when defined?(Kaminari) && klass.respond_to?(:page)
35
+ Kaminari.new klass, options
36
+ when defined?(WillPaginate) && klass.respond_to?(:paginate)
37
+ WillPaginate.new klass, options
38
+ else
39
+ Default.new klass, options
40
+ end
20
41
  end
21
42
 
43
+ module Base
44
+ attr_reader :klass, :options, :index
45
+ def initialize(klass, options={})
46
+ @klass = klass
47
+ @options = {:per_page => 1000}.update(options)
48
+ @index = options[:index] ? Tire::Index.new(options.delete(:index)) : klass.tire.index
49
+ end
50
+ end
51
+
52
+ class ActiveRecord
53
+ include Base
54
+ def import &block
55
+ klass.find_in_batches(:batch_size => options[:per_page]) do |batch|
56
+ index.import batch, options, &block
57
+ end
58
+ self
59
+ end
60
+ end
61
+
62
+ class Mongoid
63
+ include Base
64
+ def import &block
65
+ 0.step(klass.count, options[:per_page]) do |offset|
66
+ items = klass.limit(options[:per_page]).skip(offset)
67
+ index.import items.to_a, options, &block
68
+ end
69
+ self
70
+ end
71
+ end
72
+
73
+ class Kaminari
74
+ include Base
75
+ def import &block
76
+ current = 0
77
+ page = 1
78
+ while current < klass.count
79
+ items = klass.page(page).per(options[:per_page])
80
+ index.import items, options, &block
81
+ current = current + items.size
82
+ page += 1
83
+ end
84
+ self
85
+ end
86
+ end
87
+
88
+ class WillPaginate
89
+ include Base
90
+ def import &block
91
+ current = 0
92
+ page = 1
93
+ while current < klass.count
94
+ items = klass.paginate(:page => page, :per_page => options[:per_page])
95
+ index.import items, options, &block
96
+ current += items.size
97
+ page += 1
98
+ end
99
+ self
100
+ end
101
+ end
102
+
103
+ class Default
104
+ include Base
105
+ def import &block
106
+ index.import klass, options.update(:method => 'paginate'), &block
107
+ self
108
+ end
109
+ end
22
110
  end
23
111
 
24
112
  end
25
-
26
113
  end
27
114
  end
@@ -87,13 +87,14 @@ module Tire
87
87
  attr_accessor :id
88
88
 
89
89
  def initialize(attributes={})
90
- # Make a copy of objects in the property defaults hash, so default values such as `[]` or `{ foo: [] }` are left intact
90
+ # Make a copy of objects in the property defaults hash, so default values
91
+ # such as `[]` or `{ foo: [] }` are preserved.
92
+ #
91
93
  property_defaults = self.class.property_defaults.inject({}) do |hash, item|
92
94
  key, value = item
93
- hash[key.to_s] = value.class.respond_to?(:new) ? value.clone : value
95
+ hash[key.to_sym] = value.class.respond_to?(:new) ? value.clone : value
94
96
  hash
95
97
  end
96
-
97
98
  __update_attributes(property_defaults.merge(attributes))
98
99
  end
99
100
 
@@ -56,6 +56,10 @@ module Tire
56
56
  @value
57
57
  end
58
58
 
59
+ def constant_score(&block)
60
+ @value.update( { :constant_score => ConstantScoreQuery.new(&block).to_hash } ) if block_given?
61
+ end
62
+
59
63
  def fuzzy(field, value, options={})
60
64
  query = { field => { :term => value }.update(options) }
61
65
  @value = { :fuzzy => query }
@@ -182,6 +186,29 @@ module Tire
182
186
  end
183
187
  end
184
188
 
189
+ class ConstantScoreQuery
190
+ def initialize(&block)
191
+ @value = {}
192
+ block.arity < 1 ? self.instance_eval(&block) : block.call(self) if block_given?
193
+ end
194
+
195
+ def filter(type, *options)
196
+ @value.update(:filter => Filter.new(type, *options).to_hash)
197
+ end
198
+
199
+ def query(&block)
200
+ @value.update(:query => Query.new(&block).to_hash)
201
+ end
202
+
203
+ def boost(boost)
204
+ @value.update(:boost => boost)
205
+ end
206
+
207
+ def to_hash
208
+ @value
209
+ end
210
+ end
211
+
185
212
  class DisMaxQuery
186
213
  def initialize(options={}, &block)
187
214
  @options = options
data/lib/tire/tasks.rb CHANGED
@@ -1,116 +1,169 @@
1
1
  require 'rake'
2
- require 'benchmark'
2
+
3
+ module Tire
4
+ module Tasks
5
+
6
+ module Import
7
+ HRULE = '='*90
8
+
9
+ def delete_index(index)
10
+ puts "[IMPORT] Deleting index '#{index.name}'"
11
+ index.delete
12
+ end
13
+
14
+ def create_index(index, klass)
15
+ unless index.exists?
16
+ mapping = MultiJson.encode(klass.tire.mapping_to_hash, :pretty => Tire::Configuration.pretty)
17
+ puts "[IMPORT] Creating index '#{index.name}' with mapping:", mapping
18
+ unless index.create(:mappings => klass.tire.mapping_to_hash, :settings => klass.tire.settings)
19
+ puts "[ERROR] There has been an error when creating the index -- Elasticsearch returned:",
20
+ index.response
21
+ exit(1)
22
+ end
23
+ end
24
+ end
25
+
26
+ def add_pagination_to_klass(klass)
27
+ if defined?(Kaminari) && klass.respond_to?(:page)
28
+ klass.instance_eval do
29
+ def paginate(options = {})
30
+ page(options[:page]).per(options[:per_page])
31
+ end
32
+ end
33
+ end unless klass.respond_to?(:paginate)
34
+ end
35
+
36
+ def progress_bar(klass, total=nil)
37
+ @progress_bars ||= {}
38
+
39
+ if total
40
+ @progress_bars[klass.to_s] ||= ANSI::Progressbar.new(klass.to_s, total)
41
+ else
42
+ @progress_bars[klass.to_s]
43
+ end
44
+ end
45
+
46
+ def import_model(index, klass, params)
47
+ unless progress_bar(klass)
48
+ puts "[IMPORT] Importing '#{klass.to_s}'"
49
+ end
50
+ klass.tire.import(params) do |documents|
51
+ progress_bar(klass).inc documents.size if progress_bar(klass)
52
+ documents
53
+ end
54
+ progress_bar(klass).finish if progress_bar(klass)
55
+ end
56
+
57
+ extend self
58
+ end
59
+
60
+ end
61
+ end
3
62
 
4
63
  namespace :tire do
5
64
 
6
- full_comment_import = <<-DESC.gsub(/ /, '')
7
- Import data from your model using paginate: rake environment tire:import CLASS='MyModel'.
65
+ import_model_desc = <<-DESC.gsub(/ /, '')
66
+ Import data from your model (pass name as CLASS environment variable).
67
+
68
+ $ rake environment tire:import:model CLASS='MyModel'
8
69
 
9
- Pass params for the `paginate` method:
10
- $ rake environment tire:import CLASS='Article' PARAMS='{:page => 1}'
70
+ Pass params for the `import` method:
71
+ $ rake environment tire:import:model CLASS='Article' PARAMS='{:page => 1}'
11
72
 
12
73
  Force rebuilding the index (delete and create):
13
- $ rake environment tire:import CLASS='Article' PARAMS='{:page => 1}' FORCE=1
74
+ $ rake environment tire:import:model CLASS='Article' FORCE=1
14
75
 
15
76
  Set target index name:
16
- $ rake environment tire:import CLASS='Article' INDEX='articles-new'
77
+ $ rake environment tire:import:model CLASS='Article' INDEX='articles-new'
17
78
  DESC
18
- desc full_comment_import
19
- task :import do |t|
20
-
21
- def elapsed_to_human(elapsed)
22
- hour = 60*60
23
- day = hour*24
24
-
25
- case elapsed
26
- when 0..59
27
- "#{sprintf("%1.2f", elapsed)} seconds"
28
- when 60..hour-1
29
- "#{(elapsed/60).floor} minutes and #{(elapsed % 60).floor} seconds"
30
- when hour..day
31
- "#{(elapsed/hour).floor} hours and #{(elapsed/60 % hour).floor} minutes"
32
- else
33
- "#{(elapsed/hour).round} hours"
79
+
80
+ import_all_desc = <<-DESC.gsub(/ /, '')
81
+ Import all indices from `app/models` (or use DIR environment variable).
82
+
83
+ $ rake environment tire:import:all DIR=app/models
84
+ DESC
85
+
86
+ task :import => 'import:model'
87
+
88
+ namespace :import do
89
+ desc import_model_desc
90
+ task :model do
91
+ if defined?(Rails)
92
+ puts "[IMPORT] Rails detected, loading environment..."
93
+ Rake::Task["environment"].invoke
34
94
  end
35
- end
36
95
 
37
- if ENV['CLASS'].to_s == ''
38
- puts '='*90, 'USAGE', '='*90, full_comment_import, ""
39
- exit(1)
40
- end
96
+ if ENV['CLASS'].to_s == ''
97
+ puts HRULE, 'USAGE', HRULE, import_model_desc, ""
98
+ exit(1)
99
+ end
100
+
101
+ klass = eval(ENV['CLASS'].to_s)
102
+ params = eval(ENV['PARAMS'].to_s) || {}
103
+ total = klass.count rescue nil
104
+
105
+ if ENV['INDEX']
106
+ index = Tire::Index.new(ENV['INDEX'])
107
+ params[:index] = index.name
108
+ else
109
+ index = klass.tire.index
110
+ end
41
111
 
42
- klass = eval(ENV['CLASS'].to_s)
43
- params = eval(ENV['PARAMS'].to_s) || {}
112
+ Tire::Tasks::Import.add_pagination_to_klass(klass)
113
+ Tire::Tasks::Import.progress_bar(klass, total) if total
44
114
 
45
- params.update :method => 'paginate'
115
+ Tire::Tasks::Import.delete_index(index) if ENV['FORCE']
116
+ Tire::Tasks::Import.create_index(index, klass)
46
117
 
47
- index = Tire::Index.new( ENV['INDEX'] || klass.tire.index.name )
118
+ Tire::Tasks::Import.import_model(index, klass, params)
48
119
 
49
- if ENV['FORCE']
50
- puts "[IMPORT] Deleting index '#{index.name}'"
51
- index.delete
120
+ puts '[IMPORT] Done.'
52
121
  end
53
122
 
54
- unless index.exists?
55
- mapping = MultiJson.encode(klass.tire.mapping_to_hash, :pretty => Tire::Configuration.pretty)
56
- puts "[IMPORT] Creating index '#{index.name}' with mapping:", mapping
57
- unless index.create( :mappings => klass.tire.mapping_to_hash, :settings => klass.tire.settings )
58
- STDERR.puts "[ERROR] There has been an error when creating the index -- elasticsearch returned:",
59
- index.response
60
- exit(1)
123
+ desc import_all_desc
124
+ task :all do
125
+ if defined?(Rails)
126
+ puts "[IMPORT] Rails detected, loading environment..."
127
+ Rake::Task["environment"].invoke
61
128
  end
62
- end
63
129
 
64
- STDOUT.sync = true
65
- puts "[IMPORT] Starting import for the '#{ENV['CLASS']}' class"
66
- tty_cols = 80
67
- total = klass.count rescue nil
68
- offset = (total.to_s.size*2)+8
69
- done = 0
70
-
71
- STDOUT.puts '-'*tty_cols
72
- elapsed = Benchmark.realtime do
73
-
74
- # Add Kaminari-powered "paginate" method
75
- #
76
- if defined?(Kaminari) && klass.respond_to?(:page)
77
- klass.instance_eval do
78
- def paginate(options = {})
79
- page(options[:page]).per(options[:per_page])
80
- end
81
- end
82
- end unless klass.respond_to?(:paginate)
130
+ dir = ENV['DIR'].to_s != '' ? ENV['DIR'] : Rails.root.join("app/models")
131
+ params = eval(ENV['PARAMS'].to_s) || {}
83
132
 
84
- # Import the documents
85
- #
86
- index.import(klass, params) do |documents|
133
+ puts "[IMPORT] Loading models from: #{dir}"
134
+ Dir.glob(File.join("#{dir}/**/*.rb")).each do |path|
135
+ require path
87
136
 
88
- if total
89
- done += documents.to_a.size
90
- # I CAN HAZ PROGREZ BAR LIEK HOMEBRU!
91
- percent = ( (done.to_f / total) * 100 ).to_i
92
- glyphs = ( percent * ( (tty_cols-offset).to_f/100 ) ).to_i
93
- STDOUT.print( "#" * glyphs )
94
- STDOUT.print( "\r"*tty_cols+"#{done}/#{total} | \e[1m#{percent}%\e[0m " )
95
- end
137
+ model_filename = path[/#{Regexp.escape(dir.to_s)}\/([^\.]+).rb/, 1]
138
+ klass = model_filename.classify.constantize
96
139
 
97
- # Don't forget to return the documents collection back!
98
- documents
140
+ # Skip if the class doesn't have Tire integration
141
+ next unless klass.respond_to?(:tire)
142
+
143
+ total = klass.count rescue nil
144
+
145
+ Tire::Tasks::Import.add_pagination_to_klass(klass)
146
+ Tire::Tasks::Import.progress_bar(klass, total) if total
147
+
148
+ index = klass.tire.index
149
+ Tire::Tasks::Import.delete_index(index) if ENV['FORCE']
150
+ Tire::Tasks::Import.create_index(index, klass)
151
+
152
+ Tire::Tasks::Import.import_model(index, klass, params)
153
+ puts
99
154
  end
155
+
156
+ puts '[Import] Done.'
100
157
  end
101
158
 
102
- puts "", '='*80, "Import finished in #{elapsed_to_human(elapsed)}"
103
159
  end
104
160
 
105
161
  namespace :index do
106
162
 
107
163
  full_comment_drop = <<-DESC.gsub(/ /, '')
108
- Delete indices passed in the INDEX environment variable; separate multiple indices by comma.
164
+ Delete indices passed in the INDEX/INDICES environment variable; separate multiple indices by comma.
109
165
 
110
- Pass name of a single index to drop in the INDEX environmnet variable:
111
166
  $ rake environment tire:index:drop INDEX=articles
112
-
113
- Pass names of multiple indices to drop in the INDEX or INDICES environmnet variable:
114
167
  $ rake environment tire:index:drop INDICES=articles-2011-01,articles-2011-02
115
168
 
116
169
  DESC
@@ -126,7 +179,7 @@ namespace :tire do
126
179
  index_names.each do |name|
127
180
  index = Tire::Index.new(name)
128
181
  print "* Deleting index \e[1m#{index.name}\e[0m... "
129
- puts index.delete ? "\e[32mOK\e[0m" : "\e[31mFAILED\e[0m | #{index.response.body}"
182
+ puts index.delete ? "\e[32mOK\e[0m" : "\e[31mFAILED\e[0m | #{index.response.body}"
130
183
  end
131
184
 
132
185
  puts ""