tire 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.markdown CHANGED
@@ -209,8 +209,13 @@ Fortunately, _Tire_ makes blending _ElasticSearch_ features into your models tri
209
209
  ActiveModel Integration
210
210
  -----------------------
211
211
 
212
- Let's suppose you have an `Article` class in your Rails application. To make it searchable with
213
- _Tire_, you just `include` it:
212
+ If you're the type with no time for lengthy introductions, you can generate a fully working
213
+ example Rails application, with an `ActiveRecord` model and a search form, to play with:
214
+
215
+ $ rails new searchapp -m https://github.com/karmi/tire/raw/master/examples/rails-application-template.rb
216
+
217
+ For the rest, let's suppose you have an `Article` class in your Rails application.
218
+ To make it searchable with _Tire_, you just `include` it:
214
219
 
215
220
  class Article < ActiveRecord::Base
216
221
  include Tire::Model::Search
@@ -224,14 +229,18 @@ When you now save a record:
224
229
  :author => "Captain Nemo",
225
230
  :published_on => Time.now
226
231
 
227
- it is automatically added into the index, because of the included callbacks. The document attributes
228
- are indexed exactly as when you call the `Article#to_json` method.
232
+ it is automatically added into the index, because of the included callbacks.
233
+ (You may want to skip them in special cases, like when your records are indexed via some external
234
+ mechanism, let's say CouchDB or RabbitMQ [river](http://www.elasticsearch.org/blog/2010/09/28/the_river.html)
235
+ for _ElasticSearch_.)
236
+
237
+ The document attributes are indexed exactly as when you call the `Article#to_json` method.
229
238
 
230
239
  Now you can search the records:
231
240
 
232
241
  Article.search 'love'
233
242
 
234
- OK. Often, this is where the game stops. Not here.
243
+ OK. This is where the game stops, often. Not here.
235
244
 
236
245
  First of all, you may use the full query DSL, as explained above, with filters, sorting,
237
246
  advanced facet aggregation, highlighting, etc:
@@ -292,7 +301,7 @@ so you can pass any parameters to the `search` method in the controller, as usua
292
301
 
293
302
  OK. Chances are, you have lots of records stored in the underlying database. How will you get them to _ElasticSearch_? Easy:
294
303
 
295
- Article.index.import Article.all
304
+ Article.elasticsearch_index.import Article.all
296
305
 
297
306
  However, this way, all your records are loaded into memory, serialized into JSON,
298
307
  and sent down the wire to _ElasticSearch_. Not practical, you say? You're right.
@@ -326,11 +335,6 @@ You can index your data into a fresh index (and possibly update an alias if ever
326
335
 
327
336
  $ rake environment tire:import CLASS='Article' INDEX='articles-2011-05'
328
337
 
329
- If you're the type who has no time for long introductions, you can generate a fully working
330
- example Rails application, with an `ActiveRecord` model and a search form, to play with:
331
-
332
- $ rails new searchapp -m https://github.com/karmi/tire/raw/master/examples/rails-application-template.rb
333
-
334
338
  OK. All this time we have been talking about `ActiveRecord` models, since
335
339
  it is a reasonable Rails' default for the storage layer.
336
340
 
@@ -408,6 +412,8 @@ _Tire_ is already used in production by its authors. Nevertheless, it's not cons
408
412
 
409
413
  There are todos, plans and ideas, some of which are listed below, in the order of importance:
410
414
 
415
+ * Wrap all Tire functionality mixed into a model in a "forwardable" object, and proxy everything via this object. (The immediate problem: [Mongoid](http://mongoid.org/docs/indexing.html))
416
+ * If we're not stepping on other's toes, bring Tire methods like `index`, `search`, `mapping` also to the class/instance top-level namespace.
411
417
  * Proper RDoc annotations for the source code
412
418
  * [Histogram](http://www.elasticsearch.org/guide/reference/api/search/facets/histogram-facet.html) facets
413
419
  * [Statistical](http://www.elasticsearch.org/guide/reference/api/search/facets/statistical-facet.html) facets
@@ -2,33 +2,53 @@
2
2
  # Template for generating a no-frills Rails application with support for ElasticSearch full-text search via Tire
3
3
  # ===================================================================================================================
4
4
  #
5
- # This file creates a basic, fully working Rails application
6
- # with support for ElasticSearch full-text search via the Tire gem.
5
+ # This file creates a basic, fully working Rails application with support for ElasticSearch full-text search
6
+ # via the Tire gem [http://github.com/karmi/tire].
7
7
  #
8
+ # You DON'T NEED ELASTICSEARCH INSTALLED, it is installed and launched automatically by this script.
8
9
  #
9
10
  # Requirements
10
11
  # ------------
11
12
  #
13
+ # * Git
12
14
  # * Ruby >= 1.8.7
13
15
  # * Rubygems
14
- # * Rails 3
16
+ # * Rails >= 3.0.7
17
+ # * Sun Java 6 (for ElasticSearch)
15
18
  #
16
19
  #
17
20
  # Usage
18
21
  # -----
19
22
  #
20
- # $ rails new searchapp -m https://github.com/karmi/tire/raw/master/examples/rails-application-template.rb
23
+ # $ rails new tired -m https://github.com/karmi/tire/raw/master/examples/rails-application-template.rb
21
24
  #
22
25
  # ===================================================================================================================
23
26
 
24
27
  require 'rubygems'
25
- require 'restclient'
26
28
 
27
- at_exit do
28
- say_status "Stop", "ElasticSearch", :yellow
29
+ begin
30
+ require 'restclient'
31
+ rescue LoadError
32
+ puts "\n"
33
+ say_status "ERROR", "Rubygem 'rest-client' not installed\n", :red
34
+ puts '-'*80
35
+ say_status "", "gem install rest-client"
36
+ puts "\n"
29
37
 
38
+ if yes?("Should I install it for you?", :bold)
39
+ say_status "gem", "install rest-client", :yellow
40
+ system "gem install rest-client"
41
+ else
42
+ exit(1)
43
+ end
44
+ end
45
+
46
+ at_exit do
30
47
  pid = File.read("#{destination_root}/tmp/pids/elasticsearch.pid") rescue nil
31
- run "kill #{pid}" if pid
48
+ if pid
49
+ say_status "Stop", "ElasticSearch", :yellow
50
+ run "kill #{pid}"
51
+ end
32
52
  end
33
53
 
34
54
  run "rm public/index.html"
@@ -7,7 +7,7 @@ module Tire
7
7
 
8
8
  def import options={}, &block
9
9
  method = options.delete(:method) || 'paginate'
10
- self.index.import self, method, options, &block
10
+ self.elasticsearch_index.import self, method, options, &block
11
11
  end
12
12
 
13
13
  end
@@ -28,8 +28,8 @@ module Tire
28
28
  def create_index_or_update_mapping
29
29
  # STDERR.puts "Creating index with mapping", mapping_to_hash.inspect
30
30
  # STDERR.puts "Index exists?, #{index.exists?}"
31
- unless index.exists?
32
- index.create :mappings => mapping_to_hash
31
+ unless elasticsearch_index.exists?
32
+ elasticsearch_index.create :mappings => mapping_to_hash
33
33
  else
34
34
  # TODO: Update mapping
35
35
  end
@@ -31,7 +31,7 @@ module Tire
31
31
  sort = options[:order] || options[:sort]
32
32
  sort = Array(sort)
33
33
  unless block_given?
34
- s = Tire::Search::Search.new(index.name, options)
34
+ s = Tire::Search::Search.new(elasticsearch_index.name, options)
35
35
  s.query { string query }
36
36
  s.sort do
37
37
  sort.each do |t|
@@ -43,7 +43,7 @@ module Tire
43
43
  s.from( options[:page].to_i <= 1 ? 0 : (options[:per_page].to_i * (options[:page].to_i-1)) ) if options[:page] && options[:per_page]
44
44
  s.perform.results
45
45
  else
46
- s = Tire::Search::Search.new(index.name, options)
46
+ s = Tire::Search::Search.new(elasticsearch_index.name, options)
47
47
  block.arity < 1 ? s.instance_eval(&block) : block.call(s)
48
48
  s.perform.results
49
49
  end
@@ -51,7 +51,15 @@ module Tire
51
51
  Tire::Configuration.wrapper old_wrapper
52
52
  end
53
53
 
54
- def index
54
+ # Wrapper for the ES index for this class
55
+ #
56
+ # TODO: Implement some "forwardable" object named +tire+ for Tire mixins,
57
+ # and proxy everything via this object. If we're not stepping on
58
+ # other libs toes, extend/include also to the top level.
59
+ #
60
+ # The original culprit is Mongoid here, see https://github.com/karmi/tire/issues/7
61
+ #
62
+ def elasticsearch_index
55
63
  @index = Index.new(index_name)
56
64
  end
57
65
 
@@ -64,14 +72,14 @@ module Tire
64
72
  end
65
73
 
66
74
  def index
67
- self.class.index
75
+ self.class.elasticsearch_index
68
76
  end
69
77
 
70
78
  def update_elastic_search_index
71
79
  if destroyed?
72
- self.class.index.remove document_type, self
80
+ index.remove document_type, self
73
81
  else
74
- response = self.class.index.store document_type, self
82
+ response = index.store document_type, self
75
83
  self.id ||= response['_id'] if self.respond_to?(:id=)
76
84
  self
77
85
  end
data/lib/tire/tasks.rb CHANGED
@@ -44,7 +44,7 @@ namespace :tire do
44
44
  klass = eval(ENV['CLASS'].to_s)
45
45
  params = eval(ENV['PARAMS'].to_s) || {}
46
46
 
47
- index = Tire::Index.new( ENV['INDEX'] || klass.index.name )
47
+ index = Tire::Index.new( ENV['INDEX'] || klass.elasticsearch_index.name )
48
48
 
49
49
  if ENV['FORCE']
50
50
  puts "[IMPORT] Deleting index '#{index.name}'"
data/lib/tire/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Tire
2
- VERSION = "0.1.1"
2
+ VERSION = "0.1.2"
3
3
  end
@@ -28,7 +28,7 @@ module Tire
28
28
  assert_equal 'czech', SupermodelArticle.mapping[:title][:analyzer]
29
29
  assert_equal 15, SupermodelArticle.mapping[:title][:boost]
30
30
 
31
- assert_equal 'czech', SupermodelArticle.index.mapping['supermodel_article']['properties']['title']['analyzer']
31
+ assert_equal 'czech', SupermodelArticle.elasticsearch_index.mapping['supermodel_article']['properties']['title']['analyzer']
32
32
  end
33
33
 
34
34
  should "save document into index on save and find it with score" do
@@ -65,7 +65,7 @@ module Tire
65
65
  SupermodelArticle.create! :title => 'foo'
66
66
  SupermodelArticle.create! :title => 'bar'
67
67
 
68
- SupermodelArticle.index.refresh
68
+ SupermodelArticle.elasticsearch_index.refresh
69
69
  results = SupermodelArticle.search 'foo OR bar^100'
70
70
 
71
71
  assert_equal 2, results.count
@@ -37,7 +37,7 @@ module Tire
37
37
  assert_equal 'snowball', ActiveRecordArticle.mapping[:title][:analyzer]
38
38
  assert_equal 10, ActiveRecordArticle.mapping[:title][:boost]
39
39
 
40
- assert_equal 'snowball', ActiveRecordArticle.index.mapping['active_record_article']['properties']['title']['analyzer']
40
+ assert_equal 'snowball', ActiveRecordArticle.elasticsearch_index.mapping['active_record_article']['properties']['title']['analyzer']
41
41
  end
42
42
 
43
43
  should "save document into index on save and find it" do
@@ -75,7 +75,7 @@ module Tire
75
75
  ActiveRecordArticle.create! :title => 'foo'
76
76
  ActiveRecordArticle.create! :title => 'bar'
77
77
 
78
- ActiveRecordArticle.index.refresh
78
+ ActiveRecordArticle.elasticsearch_index.refresh
79
79
  results = ActiveRecordArticle.search 'foo OR bar^100'
80
80
  assert_equal 2, results.count
81
81
 
@@ -85,7 +85,7 @@ module Tire
85
85
  context "with pagination" do
86
86
  setup do
87
87
  1.upto(9) { |number| ActiveRecordArticle.create :title => "Test#{number}" }
88
- ActiveRecordArticle.index.refresh
88
+ ActiveRecordArticle.elasticsearch_index.refresh
89
89
  end
90
90
 
91
91
  context "and parameter searches" do
@@ -253,7 +253,7 @@ module Tire
253
253
  one = ActiveModelArticle.new 'title' => 'One'; one.id = '1'
254
254
  two = ActiveModelArticle.new 'title' => 'Two'; two.id = '2'
255
255
 
256
- ActiveModelArticle.index.bulk_store [ one, two ]
256
+ ActiveModelArticle.elasticsearch_index.bulk_store [ one, two ]
257
257
 
258
258
  end
259
259
 
@@ -20,6 +20,21 @@ module Tire
20
20
  assert_respond_to ActiveModelArticle, :search
21
21
  end
22
22
 
23
+ should_eventually "contain all Tire class/instance methods in a proxy object" do
24
+ end
25
+
26
+ should_eventually "include Tire class methods in class top-level namespace when they do not exist" do
27
+ end
28
+
29
+ should_eventually "include Tire instance methods in instance top-level namespace when they do not exist" do
30
+ end
31
+
32
+ should_eventually "NOT overload existing top-level class methods" do
33
+ end
34
+
35
+ should_eventually "NOT overload existing top-level instance methods" do
36
+ end
37
+
23
38
  should "search in index named after class name by default" do
24
39
  i = 'active_model_articles'
25
40
  Tire::Search::Search.expects(:new).with(i, {}).returns(@stub)
@@ -27,6 +42,9 @@ module Tire
27
42
  ActiveModelArticle.search 'foo'
28
43
  end
29
44
 
45
+ should_eventually "search only in document types for this class by default" do
46
+ end
47
+
30
48
  should "search in custom name" do
31
49
  first = 'custom-index-name'
32
50
  second = 'another-custom-index-name'
@@ -47,7 +65,7 @@ module Tire
47
65
  should "allow to refresh index" do
48
66
  Index.any_instance.expects(:refresh)
49
67
 
50
- ActiveModelArticle.index.refresh
68
+ ActiveModelArticle.elasticsearch_index.refresh
51
69
  end
52
70
 
53
71
  should "wrap results in proper class with ID and score and not change the original wrapper" do
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tire
3
3
  version: !ruby/object:Gem::Version
4
- hash: 25
4
+ hash: 31
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.1
9
+ - 2
10
+ version: 0.1.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Karel Minarik
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-02 00:00:00 +02:00
18
+ date: 2011-05-03 00:00:00 +02:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency