tire 0.2.0 → 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +2 -1
- data/README.markdown +55 -11
- data/Rakefile +16 -10
- data/examples/rails-application-template.rb +6 -6
- data/examples/tire-dsl.rb +4 -3
- data/lib/tire/client.rb +3 -0
- data/lib/tire/index.rb +4 -3
- data/lib/tire/model/indexing.rb +12 -14
- data/lib/tire/model/percolate.rb +2 -2
- data/lib/tire/model/search.rb +2 -2
- data/lib/tire/results/collection.rb +14 -12
- data/lib/tire/search/facet.rb +6 -0
- data/lib/tire/version.rb +13 -5
- data/test/fixtures/articles/1.json +1 -1
- data/test/fixtures/articles/2.json +1 -1
- data/test/fixtures/articles/3.json +1 -1
- data/test/fixtures/articles/4.json +1 -1
- data/test/fixtures/articles/5.json +1 -1
- data/test/integration/facets_test.rb +17 -0
- data/test/test_helper.rb +1 -1
- data/test/unit/client_test.rb +1 -0
- data/test/unit/index_test.rb +2 -2
- data/test/unit/model_persistence_test.rb +79 -58
- data/test/unit/model_search_test.rb +68 -9
- data/test/unit/results_collection_test.rb +16 -3
- data/test/unit/rubyext_test.rb +1 -2
- data/test/unit/search_facet_test.rb +12 -0
- data/tire.gemspec +14 -5
- metadata +31 -23
data/.travis.yml
CHANGED
data/README.markdown
CHANGED
@@ -19,9 +19,9 @@ Installation
|
|
19
19
|
|
20
20
|
OK. First, you need a running _ElasticSearch_ server. Thankfully, it's easy. Let's define easy:
|
21
21
|
|
22
|
-
$ curl -k -L -o elasticsearch-0.17.
|
23
|
-
$ tar -zxvf elasticsearch-0.17.
|
24
|
-
$ ./elasticsearch-0.17.
|
22
|
+
$ curl -k -L -o elasticsearch-0.17.6.tar.gz http://github.com/downloads/elasticsearch/elasticsearch/elasticsearch-0.17.6.tar.gz
|
23
|
+
$ tar -zxvf elasticsearch-0.17.6.tar.gz
|
24
|
+
$ ./elasticsearch-0.17.6/bin/elasticsearch -f
|
25
25
|
|
26
26
|
See, easy. On a Mac, you can also use _Homebrew_:
|
27
27
|
|
@@ -383,7 +383,7 @@ advanced facet aggregation, highlighting, etc:
|
|
383
383
|
```
|
384
384
|
|
385
385
|
Second, dynamic mapping is a godsend when you're prototyping.
|
386
|
-
For serious usage, though, you'll definitely want to define a custom
|
386
|
+
For serious usage, though, you'll definitely want to define a custom _mapping_ for your models:
|
387
387
|
|
388
388
|
```ruby
|
389
389
|
class Article < ActiveRecord::Base
|
@@ -402,17 +402,63 @@ For serious usage, though, you'll definitely want to define a custom mapping for
|
|
402
402
|
|
403
403
|
In this case, _only_ the defined model attributes are indexed. The `mapping` declaration creates the
|
404
404
|
index when the class is loaded or when the importing features are used, and _only_ when it does not yet exist.
|
405
|
-
(It may well be reasonable to wrap the index creation logic in a class method of your model, so you
|
406
|
-
have better control on index creation when bootstrapping your application or when setting up the test suite.)
|
407
405
|
|
408
|
-
|
409
|
-
|
406
|
+
Chances are, you want to declare also a custom _settings_ for the index, such as set the number of shards,
|
407
|
+
replicas, or create elaborate analyzer chains, such as the hipster's choice: [_ngrams_](https://gist.github.com/1160430).
|
408
|
+
In this case, just wrap the `mapping` method in a `settings` one, passing it the settings as a Hash:
|
410
409
|
|
411
410
|
```ruby
|
412
|
-
class
|
411
|
+
class URL < ActiveRecord::Base
|
413
412
|
include Tire::Model::Search
|
414
413
|
include Tire::Model::Callbacks
|
415
414
|
|
415
|
+
settings :number_of_shards => 1,
|
416
|
+
:number_of_replicas => 1,
|
417
|
+
:analysis => {
|
418
|
+
:filter => {
|
419
|
+
:url_ngram => {
|
420
|
+
"type" => "nGram",
|
421
|
+
"max_gram" => 5,
|
422
|
+
"min_gram" => 3 }
|
423
|
+
},
|
424
|
+
:analyzer => {
|
425
|
+
:url_analyzer => {
|
426
|
+
"tokenizer" => "lowercase",
|
427
|
+
"filter" => ["stop", "url_ngram"],
|
428
|
+
"type" => "custom" }
|
429
|
+
}
|
430
|
+
} do
|
431
|
+
mapping { indexes :url, :type => 'string', :analyzer => "url_analyzer" }
|
432
|
+
end
|
433
|
+
end
|
434
|
+
```
|
435
|
+
|
436
|
+
It may well be reasonable to wrap the index creation logic declared with `Tire.index('urls').create`
|
437
|
+
in a class method of your model, in a module method, etc, so have better control on index creation when bootstrapping your application with Rake tasks or when setting up the test suite.
|
438
|
+
_Tire_ will not hold that against you.
|
439
|
+
|
440
|
+
When you want a tight grip on how the attributes are added to the index, just
|
441
|
+
implement the `to_indexed_json` method in your model.
|
442
|
+
|
443
|
+
The easiest way is to customize the `to_json` serialization support of your model:
|
444
|
+
|
445
|
+
```ruby
|
446
|
+
class Article < ActiveRecord::Base
|
447
|
+
# ...
|
448
|
+
|
449
|
+
include_root_in_json = false
|
450
|
+
def to_indexed_json
|
451
|
+
to_json :except => ['updated_at'], :methods => ['length']
|
452
|
+
end
|
453
|
+
end
|
454
|
+
```
|
455
|
+
|
456
|
+
Of course, it may well be reasonable to define the indexed JSON from the ground up:
|
457
|
+
|
458
|
+
```ruby
|
459
|
+
class Article < ActiveRecord::Base
|
460
|
+
# ...
|
461
|
+
|
416
462
|
def to_indexed_json
|
417
463
|
names = author.split(/\W/)
|
418
464
|
last_name = names.pop
|
@@ -427,7 +473,6 @@ implement the `to_indexed_json` method in your model:
|
|
427
473
|
}
|
428
474
|
}.to_json
|
429
475
|
end
|
430
|
-
|
431
476
|
end
|
432
477
|
```
|
433
478
|
|
@@ -611,7 +656,6 @@ There are todos, plans and ideas, some of which are listed below, in the order o
|
|
611
656
|
* 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))
|
612
657
|
* If we're not stepping on other's toes, bring Tire methods like `index`, `search`, `mapping` also to the class/instance top-level namespace.
|
613
658
|
* Proper RDoc annotations for the source code
|
614
|
-
* [Histogram](http://www.elasticsearch.org/guide/reference/api/search/facets/histogram-facet.html) facets
|
615
659
|
* [Statistical](http://www.elasticsearch.org/guide/reference/api/search/facets/statistical-facet.html) facets
|
616
660
|
* [Geo Distance](http://www.elasticsearch.org/guide/reference/api/search/facets/geo-distance-facet.html) facets
|
617
661
|
* [Index aliases](http://www.elasticsearch.org/guide/reference/api/admin-indices-aliases.html) management
|
data/Rakefile
CHANGED
@@ -14,24 +14,30 @@ end
|
|
14
14
|
namespace :test do
|
15
15
|
Rake::TestTask.new(:unit) do |test|
|
16
16
|
test.libs << 'lib' << 'test'
|
17
|
-
test.
|
17
|
+
test.test_files = FileList["test/unit/*_test.rb"]
|
18
18
|
test.verbose = true
|
19
19
|
end
|
20
20
|
Rake::TestTask.new(:integration) do |test|
|
21
21
|
test.libs << 'lib' << 'test'
|
22
|
-
test.
|
22
|
+
test.test_files = FileList["test/integration/*_test.rb"]
|
23
23
|
test.verbose = true
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
27
|
# Generate documentation
|
28
|
-
begin
|
29
|
-
require '
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
begin
|
29
|
+
begin; require 'sdoc'; rescue LoadError; end
|
30
|
+
require 'rdoc/task'
|
31
|
+
Rake::RDocTask.new do |rdoc|
|
32
|
+
rdoc.rdoc_dir = 'rdoc'
|
33
|
+
rdoc.title = "Tire"
|
34
|
+
rdoc.rdoc_files.include('README.markdown')
|
35
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rdoc do
|
39
|
+
abort "[!] RDoc gem is not available."
|
40
|
+
end
|
35
41
|
end
|
36
42
|
|
37
43
|
# Generate coverage reports
|
@@ -45,7 +51,7 @@ begin
|
|
45
51
|
end
|
46
52
|
rescue LoadError
|
47
53
|
task :rcov do
|
48
|
-
abort "RCov is not available.
|
54
|
+
abort "[!] RCov gem is not available."
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
@@ -62,7 +62,7 @@ file ".gitignore", <<-END.gsub(/ /, '')
|
|
62
62
|
tmp/**/*
|
63
63
|
config/database.yml
|
64
64
|
db/*.sqlite3
|
65
|
-
vendor/elasticsearch-0.
|
65
|
+
vendor/elasticsearch-0.17.6/
|
66
66
|
END
|
67
67
|
|
68
68
|
git :init
|
@@ -71,11 +71,11 @@ git :commit => "-m 'Initial commit: Clean application'"
|
|
71
71
|
|
72
72
|
unless (RestClient.get('http://localhost:9200') rescue false)
|
73
73
|
COMMAND = <<-COMMAND.gsub(/^ /, '')
|
74
|
-
curl -k -L -# -o elasticsearch-0.
|
75
|
-
"http://github.com/downloads/elasticsearch/elasticsearch/elasticsearch-0.
|
76
|
-
tar -zxf elasticsearch-0.
|
77
|
-
rm -f elasticsearch-0.
|
78
|
-
./elasticsearch-0.
|
74
|
+
curl -k -L -# -o elasticsearch-0.17.6.tar.gz \
|
75
|
+
"http://github.com/downloads/elasticsearch/elasticsearch/elasticsearch-0.17.6.tar.gz"
|
76
|
+
tar -zxf elasticsearch-0.17.6.tar.gz
|
77
|
+
rm -f elasticsearch-0.17.6.tar.gz
|
78
|
+
./elasticsearch-0.17.6/bin/elasticsearch -p #{destination_root}/tmp/pids/elasticsearch.pid
|
79
79
|
COMMAND
|
80
80
|
|
81
81
|
puts "\n"
|
data/examples/tire-dsl.rb
CHANGED
@@ -43,9 +43,9 @@ require 'tire'
|
|
43
43
|
|
44
44
|
[ERROR] You don’t appear to have ElasticSearch installed. Please install and launch it with the following commands:
|
45
45
|
|
46
|
-
curl -k -L -o elasticsearch-0.17.
|
47
|
-
tar -zxvf elasticsearch-0.17.
|
48
|
-
./elasticsearch-0.17.
|
46
|
+
curl -k -L -o elasticsearch-0.17.6.tar.gz http://github.com/downloads/elasticsearch/elasticsearch/elasticsearch-0.17.6.tar.gz
|
47
|
+
tar -zxvf elasticsearch-0.17.6.tar.gz
|
48
|
+
./elasticsearch-0.17.6/bin/elasticsearch -f
|
49
49
|
INSTALL
|
50
50
|
|
51
51
|
### Storing and indexing documents
|
@@ -581,6 +581,7 @@ end
|
|
581
581
|
# * [terms](http://www.elasticsearch.org/guide/reference/api/search/facets/terms-facet.html)
|
582
582
|
# * [date](http://www.elasticsearch.org/guide/reference/api/search/facets/date-histogram-facet.html)
|
583
583
|
# * [range](http://www.elasticsearch.org/guide/reference/api/search/facets/range-facet.html)
|
584
|
+
# * [histogram](http://www.elasticsearch.org/guide/reference/api/search/facets/histogram-facet.html)
|
584
585
|
|
585
586
|
# We have seen that _ElasticSearch_ facets enable us to fetch complex aggregations from our data.
|
586
587
|
#
|
data/lib/tire/client.rb
CHANGED
data/lib/tire/index.rb
CHANGED
@@ -9,7 +9,7 @@ module Tire
|
|
9
9
|
end
|
10
10
|
|
11
11
|
def exists?
|
12
|
-
!!Configuration.client.
|
12
|
+
!!Configuration.client.head("#{Configuration.url}/#{@name}")
|
13
13
|
rescue Exception => error
|
14
14
|
false
|
15
15
|
end
|
@@ -105,7 +105,8 @@ module Tire
|
|
105
105
|
when method
|
106
106
|
options = {:page => 1, :per_page => 1000}.merge options
|
107
107
|
while documents = klass_or_collection.send(method.to_sym, options.merge(:page => options[:page])) \
|
108
|
-
and
|
108
|
+
and documents.to_a.length > 0
|
109
|
+
|
109
110
|
documents = yield documents if block_given?
|
110
111
|
|
111
112
|
bulk_store documents
|
@@ -205,7 +206,7 @@ module Tire
|
|
205
206
|
end
|
206
207
|
|
207
208
|
def percolate(*args, &block)
|
208
|
-
document = args.
|
209
|
+
document = args.shift
|
209
210
|
type = get_type_from_document(document)
|
210
211
|
|
211
212
|
document = MultiJson.decode convert_document_to_json(document)
|
data/lib/tire/model/indexing.rb
CHANGED
@@ -5,14 +5,19 @@ module Tire
|
|
5
5
|
|
6
6
|
module ClassMethods
|
7
7
|
|
8
|
+
def settings(*args)
|
9
|
+
@settings ||= {}
|
10
|
+
args.empty? ? (return @settings) : @settings = args.pop
|
11
|
+
yield if block_given?
|
12
|
+
end
|
13
|
+
|
8
14
|
def mapping
|
15
|
+
@mapping ||= {}
|
9
16
|
if block_given?
|
10
|
-
@store_mapping = true
|
11
|
-
|
12
|
-
@store_mapping = false
|
13
|
-
create_index_or_update_mapping
|
17
|
+
@store_mapping = true and yield and @store_mapping = false
|
18
|
+
create_elasticsearch_index
|
14
19
|
else
|
15
|
-
@mapping
|
20
|
+
@mapping
|
16
21
|
end
|
17
22
|
end
|
18
23
|
|
@@ -39,17 +44,10 @@ module Tire
|
|
39
44
|
@store_mapping || false
|
40
45
|
end
|
41
46
|
|
42
|
-
def
|
43
|
-
# STDERR.puts "Creating index with mapping", mapping_to_hash.inspect
|
44
|
-
# STDERR.puts "Index exists?, #{index.exists?}"
|
47
|
+
def create_elasticsearch_index
|
45
48
|
unless elasticsearch_index.exists?
|
46
|
-
elasticsearch_index.create :mappings => mapping_to_hash
|
47
|
-
else
|
48
|
-
# TODO: Update mapping
|
49
|
+
elasticsearch_index.create :mappings => mapping_to_hash, :settings => settings
|
49
50
|
end
|
50
|
-
rescue Exception => e
|
51
|
-
# TODO: STDERR + logger
|
52
|
-
raise
|
53
51
|
end
|
54
52
|
|
55
53
|
def mapping_to_hash
|
data/lib/tire/model/percolate.rb
CHANGED
@@ -10,7 +10,7 @@ module Tire
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def on_percolate(pattern=true,&block)
|
13
|
-
|
13
|
+
percolate!(pattern)
|
14
14
|
after_update_elastic_search_index(block)
|
15
15
|
end
|
16
16
|
|
@@ -22,7 +22,7 @@ module Tire
|
|
22
22
|
module InstanceMethods
|
23
23
|
|
24
24
|
def percolate(&block)
|
25
|
-
index.percolate
|
25
|
+
index.percolate self, block
|
26
26
|
end
|
27
27
|
|
28
28
|
def percolate=(pattern)
|
data/lib/tire/model/search.rb
CHANGED
@@ -60,7 +60,7 @@ module Tire
|
|
60
60
|
#
|
61
61
|
#
|
62
62
|
def search(*args, &block)
|
63
|
-
default_options = {:type => document_type}
|
63
|
+
default_options = {:type => document_type, :index => elasticsearch_index.name}
|
64
64
|
|
65
65
|
if block_given?
|
66
66
|
options = args.shift || {}
|
@@ -72,7 +72,7 @@ module Tire
|
|
72
72
|
sort = Array( options[:order] || options[:sort] )
|
73
73
|
options = default_options.update(options)
|
74
74
|
|
75
|
-
s = Tire::Search::Search.new(
|
75
|
+
s = Tire::Search::Search.new(options.delete(:index), options)
|
76
76
|
s.size( options[:per_page].to_i ) if options[:per_page]
|
77
77
|
s.from( options[:page].to_i <= 1 ? 0 : (options[:per_page].to_i * (options[:page].to_i-1)) ) if options[:page] && options[:per_page]
|
78
78
|
s.sort do
|
@@ -36,25 +36,26 @@ module Tire
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
else
|
39
|
-
|
40
|
-
return [] if @response['hits']['total'] == 0
|
39
|
+
return [] if @response['hits']['hits'].empty?
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
type = @response['hits']['hits'].first['_type']
|
42
|
+
raise NoMethodError, "You have tried to eager load the model instances, " +
|
43
|
+
"but Tire cannot find the model class because " +
|
44
|
+
"document has no _type property." unless type
|
46
45
|
|
46
|
+
begin
|
47
47
|
klass = type.camelize.constantize
|
48
|
-
ids = @response['hits']['hits'].map { |h| h['_id'] }
|
49
|
-
records = @options[:load] === true ? klass.find(ids) : klass.find(ids, @options[:load])
|
50
|
-
|
51
|
-
# Reorder records to preserve order from search results
|
52
|
-
ids.map { |id| records.detect { |record| record.id.to_s == id.to_s } }
|
53
48
|
rescue NameError => e
|
54
|
-
raise NameError, "You have tried to eager load the model instances, but" +
|
49
|
+
raise NameError, "You have tried to eager load the model instances, but " +
|
55
50
|
"Tire cannot find the model class '#{type.camelize}' " +
|
56
51
|
"based on _type '#{type}'.", e.backtrace
|
57
52
|
end
|
53
|
+
|
54
|
+
ids = @response['hits']['hits'].map { |h| h['_id'] }
|
55
|
+
records = @options[:load] === true ? klass.find(ids) : klass.find(ids, @options[:load])
|
56
|
+
|
57
|
+
# Reorder records to preserve order from search results
|
58
|
+
ids.map { |id| records.detect { |record| record.id.to_s == id.to_s } }
|
58
59
|
end
|
59
60
|
end
|
60
61
|
end
|
@@ -70,6 +71,7 @@ module Tire
|
|
70
71
|
def size
|
71
72
|
results.size
|
72
73
|
end
|
74
|
+
alias :length :size
|
73
75
|
|
74
76
|
def [](index)
|
75
77
|
results[index]
|
data/lib/tire/search/facet.rb
CHANGED
@@ -29,6 +29,12 @@ module Tire
|
|
29
29
|
|
30
30
|
def range(field, ranges=[], options={})
|
31
31
|
@value = { :range => { :field => field, :ranges => ranges }.update(options) }
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def histogram(field, options={})
|
36
|
+
@value = { :histogram => (options.delete(:histogram) || {:field => field}.update(options)) }
|
37
|
+
self
|
32
38
|
end
|
33
39
|
|
34
40
|
def to_json
|
data/lib/tire/version.rb
CHANGED
@@ -1,13 +1,21 @@
|
|
1
1
|
module Tire
|
2
|
-
VERSION = "0.2.
|
2
|
+
VERSION = "0.2.1"
|
3
3
|
|
4
4
|
CHANGELOG =<<-END
|
5
5
|
IMPORTANT CHANGES LATELY:
|
6
6
|
|
7
|
-
|
7
|
+
0.2.0
|
8
|
+
---------------------------------------------------------
|
9
|
+
# By default, results are wrapped in Item class
|
8
10
|
# Completely rewritten ActiveModel/ActiveRecord support
|
9
|
-
# Added
|
10
|
-
#
|
11
|
-
|
11
|
+
# Added infrastructure for loading "real" models from database (eagerly or in runtime)
|
12
|
+
# Deprecated the dynamic sort methods in favour of the 'sort { by :field_name }' syntax
|
13
|
+
|
14
|
+
0.2.1
|
15
|
+
---------------------------------------------------------
|
16
|
+
# Lighweight check for index presence
|
17
|
+
# Added the 'settings' method for models to define index settings
|
18
|
+
# Fixed errors when importing data with will_paginate vs Kaminari (MongoDB)
|
19
|
+
# Added support for histogram facets [Paco Guzman]
|
12
20
|
END
|
13
21
|
end
|
@@ -1 +1 @@
|
|
1
|
-
{"title" : "One", "tags" : ["ruby"], "published_on" : "2011-01-01"}
|
1
|
+
{"title" : "One", "tags" : ["ruby"], "published_on" : "2011-01-01", "words" : 125}
|
@@ -1 +1 @@
|
|
1
|
-
{"title" : "Two", "tags" : ["ruby", "python"], "published_on" : "2011-01-02"}
|
1
|
+
{"title" : "Two", "tags" : ["ruby", "python"], "published_on" : "2011-01-02", "words" : 250}
|
@@ -1 +1 @@
|
|
1
|
-
{"title" : "Three", "tags" : ["java"], "published_on" : "2011-01-02"}
|
1
|
+
{"title" : "Three", "tags" : ["java"], "published_on" : "2011-01-02", "words" : 375}
|
@@ -1 +1 @@
|
|
1
|
-
{"title" : "Four", "tags" : ["erlang"], "published_on" : "2011-01-03"}
|
1
|
+
{"title" : "Four", "tags" : ["erlang"], "published_on" : "2011-01-03", "words" : 250}
|
@@ -1 +1 @@
|
|
1
|
-
{"title" : "Five", "tags" : ["javascript", "java"], "published_on" : "2011-01-04"}
|
1
|
+
{"title" : "Five", "tags" : ["javascript", "java"], "published_on" : "2011-01-04", "words" : 125}
|
@@ -76,6 +76,23 @@ module Tire
|
|
76
76
|
|
77
77
|
end
|
78
78
|
|
79
|
+
context "histogram" do
|
80
|
+
should "return aggregated values for all results" do
|
81
|
+
s = Tire.search('articles-test') do
|
82
|
+
query { all }
|
83
|
+
facet 'words' do
|
84
|
+
histogram :words, :interval => 100
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
facets = s.results.facets['words']['entries']
|
89
|
+
assert_equal 3, facets.size, facets.inspect
|
90
|
+
assert_equal({"key" => 100, "count" => 2}, facets.entries[0], facets.inspect)
|
91
|
+
assert_equal({"key" => 200, "count" => 2}, facets.entries[1], facets.inspect)
|
92
|
+
assert_equal({"key" => 300, "count" => 1}, facets.entries[2], facets.inspect)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
79
96
|
end
|
80
97
|
|
81
98
|
end
|
data/test/test_helper.rb
CHANGED
data/test/unit/client_test.rb
CHANGED
data/test/unit/index_test.rb
CHANGED
@@ -15,12 +15,12 @@ module Tire
|
|
15
15
|
end
|
16
16
|
|
17
17
|
should "return true when exists" do
|
18
|
-
Configuration.client.expects(:
|
18
|
+
Configuration.client.expects(:head).returns(mock_response(''))
|
19
19
|
assert @index.exists?
|
20
20
|
end
|
21
21
|
|
22
22
|
should "return false when does not exist" do
|
23
|
-
Configuration.client.expects(:
|
23
|
+
Configuration.client.expects(:head).raises(RestClient::ResourceNotFound)
|
24
24
|
assert ! @index.exists?
|
25
25
|
end
|
26
26
|
|
@@ -247,16 +247,16 @@ module Tire
|
|
247
247
|
|
248
248
|
context "when creating" do
|
249
249
|
|
250
|
-
# TODO: Find a way to mock JSON paylod for Mocha with disregard to Hash entries ordering.
|
251
|
-
# Ruby 1.9 brings ordered Hashes, so tests were failing.
|
252
|
-
|
253
250
|
should "save the document with generated ID in the database" do
|
254
|
-
Configuration.client.expects(:post).
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
251
|
+
Configuration.client.expects(:post).
|
252
|
+
with do |url, payload|
|
253
|
+
doc = MultiJson.decode(payload)
|
254
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/" &&
|
255
|
+
doc['title'] == 'Test' &&
|
256
|
+
doc['tags'] == ['one', 'two']
|
257
|
+
doc['published_on'] == nil
|
258
|
+
end.
|
259
|
+
returns(mock_response('{"ok":true,"_id":"abc123"}'))
|
260
260
|
article = PersistentArticle.create :title => 'Test', :tags => [:one, :two]
|
261
261
|
|
262
262
|
assert article.persisted?, "#{article.inspect} should be `persisted?`"
|
@@ -264,12 +264,15 @@ module Tire
|
|
264
264
|
end
|
265
265
|
|
266
266
|
should "save the document with custom ID in the database" do
|
267
|
-
Configuration.client.expects(:post).
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
267
|
+
Configuration.client.expects(:post).
|
268
|
+
with do |url, payload|
|
269
|
+
doc = MultiJson.decode(payload)
|
270
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/r2d2" &&
|
271
|
+
doc['id'] == 'r2d2' &&
|
272
|
+
doc['title'] == 'Test' &&
|
273
|
+
doc['published_on'] == nil
|
274
|
+
end.
|
275
|
+
returns(mock_response('{"ok":true,"_id":"r2d2"}'))
|
273
276
|
article = PersistentArticle.create :id => 'r2d2', :title => 'Test'
|
274
277
|
|
275
278
|
assert_equal 'r2d2', article.id
|
@@ -286,24 +289,29 @@ module Tire
|
|
286
289
|
context "when creating" do
|
287
290
|
|
288
291
|
should "set the id property" do
|
289
|
-
Configuration.client.expects(:post).
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
292
|
+
Configuration.client.expects(:post).
|
293
|
+
with do |url, payload|
|
294
|
+
doc = MultiJson.decode(payload)
|
295
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/" &&
|
296
|
+
doc['id'] == nil &&
|
297
|
+
doc['title'] == 'Test'
|
298
|
+
end.
|
299
|
+
returns(mock_response('{"ok":true,"_id":"1"}'))
|
295
300
|
|
296
301
|
article = PersistentArticle.create :title => 'Test'
|
297
302
|
assert_equal '1', article.id
|
298
303
|
end
|
299
304
|
|
300
305
|
should "not set the id property if already set" do
|
301
|
-
Configuration.client.expects(:post).
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
306
|
+
Configuration.client.expects(:post).
|
307
|
+
with do |url, payload|
|
308
|
+
doc = MultiJson.decode(payload)
|
309
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/123" &&
|
310
|
+
doc['id'] == '123' &&
|
311
|
+
doc['title'] == 'Test' &&
|
312
|
+
doc['published_on'] == nil
|
313
|
+
end.
|
314
|
+
returns(mock_response('{"ok":true, "_id":"XXX"}'))
|
307
315
|
|
308
316
|
article = PersistentArticle.create :id => '123', :title => 'Test'
|
309
317
|
assert_equal '123', article.id
|
@@ -314,23 +322,30 @@ module Tire
|
|
314
322
|
context "when saving" do
|
315
323
|
|
316
324
|
should "save the document with updated attribute" do
|
317
|
-
article = PersistentArticle.new :id => 1, :title => 'Test'
|
318
|
-
|
319
|
-
Configuration.client.expects(:post).
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
+
article = PersistentArticle.new :id => '1', :title => 'Test'
|
326
|
+
|
327
|
+
Configuration.client.expects(:post).
|
328
|
+
with do |url, payload|
|
329
|
+
doc = MultiJson.decode(payload)
|
330
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/1" &&
|
331
|
+
doc['id'] == '1' &&
|
332
|
+
doc['title'] == 'Test' &&
|
333
|
+
doc['published_on'] == nil
|
334
|
+
end.
|
335
|
+
returns(mock_response('{"ok":true,"_id":"1"}'))
|
325
336
|
assert article.save
|
326
337
|
|
327
338
|
article.title = 'Updated'
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
339
|
+
|
340
|
+
Configuration.client.expects(:post).
|
341
|
+
with do |url, payload|
|
342
|
+
doc = MultiJson.decode(payload)
|
343
|
+
p doc
|
344
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/1" &&
|
345
|
+
doc['id'] == '1' &&
|
346
|
+
doc['title'] == 'Updated'
|
347
|
+
end.
|
348
|
+
returns(mock_response('{"ok":true,"_id":"1"}'))
|
334
349
|
assert article.save
|
335
350
|
end
|
336
351
|
|
@@ -352,17 +367,19 @@ module Tire
|
|
352
367
|
|
353
368
|
should "not set the id property if already set" do
|
354
369
|
article = PersistentArticle.new
|
355
|
-
article.id = '
|
370
|
+
article.id = '456'
|
356
371
|
article.title = 'Test'
|
357
372
|
|
358
|
-
Configuration.client.expects(:post).
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
373
|
+
Configuration.client.expects(:post).
|
374
|
+
with do |url, payload|
|
375
|
+
doc = MultiJson.decode(payload)
|
376
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/456" &&
|
377
|
+
doc['id'] == '456' &&
|
378
|
+
doc['title'] == 'Test'
|
379
|
+
end.
|
380
|
+
returns(mock_response('{"ok":true,"_id":"XXX"}'))
|
364
381
|
assert article.save
|
365
|
-
assert_equal '
|
382
|
+
assert_equal '456', article.id
|
366
383
|
end
|
367
384
|
|
368
385
|
end
|
@@ -370,13 +387,16 @@ module Tire
|
|
370
387
|
context "when destroying" do
|
371
388
|
|
372
389
|
should "delete the document from the database" do
|
373
|
-
Configuration.client.expects(:post).
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
390
|
+
Configuration.client.expects(:post).
|
391
|
+
with do |url, payload|
|
392
|
+
doc = MultiJson.decode(payload)
|
393
|
+
url == "#{Configuration.url}/persistent_articles/persistent_article/123" &&
|
394
|
+
doc['id'] == '123' &&
|
395
|
+
doc['title'] == 'Test'
|
396
|
+
end.returns(mock_response('{"ok":true,"_id":"123"}'))
|
397
|
+
|
398
|
+
Configuration.client.expects(:delete).
|
399
|
+
with("#{Configuration.url}/persistent_articles/persistent_article/123")
|
380
400
|
|
381
401
|
article = PersistentArticle.new :id => '123', :title => 'Test'
|
382
402
|
article.save
|
@@ -409,13 +429,14 @@ module Tire
|
|
409
429
|
context "Persistent model with mapping definition" do
|
410
430
|
|
411
431
|
should "create the index with mapping" do
|
412
|
-
|
432
|
+
expected = {
|
433
|
+
:settings => {},
|
413
434
|
:mappings => { :persistent_article_with_mapping => {
|
414
435
|
:properties => { :title => { :type => 'string', :analyzer => 'snowball', :boost => 10 } }
|
415
436
|
}}
|
416
437
|
}
|
417
438
|
|
418
|
-
Tire::Index.any_instance.expects(:create).with(
|
439
|
+
Tire::Index.any_instance.expects(:create).with(expected)
|
419
440
|
|
420
441
|
class ::PersistentArticleWithMapping
|
421
442
|
|
@@ -84,6 +84,30 @@ module Tire
|
|
84
84
|
ActiveModelArticleWithCustomIndexName.search { query { string 'foo' } }
|
85
85
|
end
|
86
86
|
|
87
|
+
should "allow to pass custom document type" do
|
88
|
+
Tire::Search::Search.
|
89
|
+
expects(:new).
|
90
|
+
with(ActiveModelArticle.index_name, { :type => 'custom_type' }).
|
91
|
+
returns(@stub).
|
92
|
+
twice
|
93
|
+
|
94
|
+
ActiveModelArticle.search 'foo', :type => 'custom_type'
|
95
|
+
ActiveModelArticle.search( :type => 'custom_type' ) { query { string 'foo' } }
|
96
|
+
end
|
97
|
+
|
98
|
+
should "allow to pass custom index name" do
|
99
|
+
Tire::Search::Search.
|
100
|
+
expects(:new).
|
101
|
+
with('custom_index', { :type => ActiveModelArticle.document_type }).
|
102
|
+
returns(@stub).
|
103
|
+
twice
|
104
|
+
|
105
|
+
ActiveModelArticle.search 'foo', :index => 'custom_index'
|
106
|
+
ActiveModelArticle.search( :index => 'custom_index' ) do
|
107
|
+
query { string 'foo' }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
87
111
|
should "allow to refresh index" do
|
88
112
|
Index.any_instance.expects(:refresh)
|
89
113
|
|
@@ -106,9 +130,11 @@ module Tire
|
|
106
130
|
end
|
107
131
|
|
108
132
|
context "searching with a block" do
|
133
|
+
setup do
|
134
|
+
Tire::Search::Search.any_instance.expects(:perform).returns(@stub)
|
135
|
+
end
|
109
136
|
|
110
137
|
should "pass on whatever block it received" do
|
111
|
-
Tire::Search::Search.any_instance.expects(:perform).returns(@stub)
|
112
138
|
Tire::Search::Query.any_instance.expects(:string).with('foo').returns(@stub)
|
113
139
|
|
114
140
|
ActiveModelArticle.search { query { string 'foo' } }
|
@@ -116,7 +142,6 @@ module Tire
|
|
116
142
|
|
117
143
|
should "allow to pass block with argument to query, allowing to use local variables from outer scope" do
|
118
144
|
Tire::Search::Query.any_instance.expects(:instance_eval).never
|
119
|
-
Tire::Search::Search.any_instance.expects(:perform).returns(@stub)
|
120
145
|
Tire::Search::Query.any_instance.expects(:string).with('foo').returns(@stub)
|
121
146
|
|
122
147
|
my_query = 'foo'
|
@@ -245,13 +270,14 @@ module Tire
|
|
245
270
|
context "with custom mapping" do
|
246
271
|
|
247
272
|
should "create the index with mapping" do
|
248
|
-
|
273
|
+
expected = {
|
274
|
+
:settings => {},
|
249
275
|
:mappings => { :model_with_custom_mapping => {
|
250
276
|
:properties => { :title => { :type => 'string', :analyzer => 'snowball', :boost => 10 } }
|
251
277
|
}}
|
252
278
|
}
|
253
279
|
|
254
|
-
Tire::Index.any_instance.expects(:create).with(
|
280
|
+
Tire::Index.any_instance.expects(:create).with(expected)
|
255
281
|
|
256
282
|
class ::ModelWithCustomMapping
|
257
283
|
extend ActiveModel::Naming
|
@@ -270,7 +296,8 @@ module Tire
|
|
270
296
|
end
|
271
297
|
|
272
298
|
should "define mapping for nested properties with a block" do
|
273
|
-
|
299
|
+
expected = {
|
300
|
+
:settings => {},
|
274
301
|
:mappings => { :model_with_nested_mapping => {
|
275
302
|
:properties => {
|
276
303
|
:title => { :type => 'string' },
|
@@ -285,7 +312,7 @@ module Tire
|
|
285
312
|
}
|
286
313
|
}}
|
287
314
|
|
288
|
-
Tire::Index.any_instance.expects(:create).with(
|
315
|
+
Tire::Index.any_instance.expects(:create).with(expected)
|
289
316
|
|
290
317
|
class ::ModelWithNestedMapping
|
291
318
|
extend ActiveModel::Naming
|
@@ -310,6 +337,39 @@ module Tire
|
|
310
337
|
|
311
338
|
end
|
312
339
|
|
340
|
+
context "with settings" do
|
341
|
+
|
342
|
+
should "create the index with settings and mappings" do
|
343
|
+
expected_settings = {
|
344
|
+
:settings => { :number_of_shards => 1, :number_of_replicas => 1 }
|
345
|
+
}
|
346
|
+
|
347
|
+
Tire::Index.any_instance.expects(:create).with do |expected|
|
348
|
+
expected[:settings][:number_of_shards] == 1 &&
|
349
|
+
expected[:mappings].size > 0
|
350
|
+
end
|
351
|
+
|
352
|
+
class ::ModelWithCustomSettings
|
353
|
+
extend ActiveModel::Naming
|
354
|
+
extend ActiveModel::Callbacks
|
355
|
+
|
356
|
+
include Tire::Model::Search
|
357
|
+
include Tire::Model::Callbacks
|
358
|
+
|
359
|
+
settings :number_of_shards => 1, :number_of_replicas => 1 do
|
360
|
+
mapping do
|
361
|
+
indexes :title, :type => 'string'
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
end
|
366
|
+
|
367
|
+
assert_instance_of Hash, ModelWithCustomSettings.settings
|
368
|
+
assert_equal 1, ModelWithCustomSettings.settings[:number_of_shards]
|
369
|
+
end
|
370
|
+
|
371
|
+
end
|
372
|
+
|
313
373
|
context "with index update callbacks" do
|
314
374
|
setup do
|
315
375
|
class ::ModelWithIndexCallbacks
|
@@ -456,9 +516,8 @@ module Tire
|
|
456
516
|
should "pass the arguments to percolate" do
|
457
517
|
filter = lambda { string 'tag:alerts' }
|
458
518
|
|
459
|
-
Tire::Index.any_instance.expects(:percolate).with do |
|
460
|
-
# p [
|
461
|
-
type == 'active_model_article_with_callbacks' &&
|
519
|
+
Tire::Index.any_instance.expects(:percolate).with do |doc,query|
|
520
|
+
# p [doc,query]
|
462
521
|
doc == @article &&
|
463
522
|
query == filter
|
464
523
|
end.returns(["alert"])
|
@@ -22,8 +22,9 @@ module Tire
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
should "have size" do
|
25
|
+
should "have size/length" do
|
26
26
|
assert_equal 3, Results::Collection.new(@default_response).size
|
27
|
+
assert_equal 3, Results::Collection.new(@default_response).length
|
27
28
|
end
|
28
29
|
|
29
30
|
should "allow access to items" do
|
@@ -151,8 +152,8 @@ module Tire
|
|
151
152
|
{'_id' => 2},
|
152
153
|
{'_id' => 3},
|
153
154
|
{'_id' => 4}],
|
154
|
-
'total' => 4,
|
155
|
-
|
155
|
+
'total' => 4 },
|
156
|
+
'took' => 1 }
|
156
157
|
@collection = Results::Collection.new( @default_response, :per_page => 1, :page => 2 )
|
157
158
|
end
|
158
159
|
|
@@ -234,6 +235,18 @@ module Tire
|
|
234
235
|
end
|
235
236
|
end
|
236
237
|
|
238
|
+
should "return empty array for empty hits" do
|
239
|
+
response = { 'hits' => {
|
240
|
+
'hits' => [],
|
241
|
+
'total' => 4
|
242
|
+
},
|
243
|
+
'took' => 1 }
|
244
|
+
@collection = Results::Collection.new( response, :load => true )
|
245
|
+
assert @collection.empty?, 'Collection should be empty'
|
246
|
+
assert @collection.results.empty?, 'Collection results should be empty'
|
247
|
+
assert_equal 0, @collection.size
|
248
|
+
end
|
249
|
+
|
237
250
|
end
|
238
251
|
|
239
252
|
end
|
data/test/unit/rubyext_test.rb
CHANGED
@@ -22,8 +22,7 @@ module Tire
|
|
22
22
|
|
23
23
|
end
|
24
24
|
|
25
|
-
should "have a to_json method from
|
26
|
-
assert defined?(Yajl)
|
25
|
+
should "have a to_json method from a JSON serialization library" do
|
27
26
|
assert_respond_to( {}, :to_json )
|
28
27
|
assert_equal '{"one":1}', { :one => 1}.to_json
|
29
28
|
end
|
@@ -69,6 +69,18 @@ module Tire::Search
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
+
context "histogram facet" do
|
73
|
+
should "encode facet options with default key" do
|
74
|
+
f = Facet.new('histogram') { histogram :age, {:interval => 5} }
|
75
|
+
assert_equal({ :histogram => { :histogram => { :field => 'age', :interval => 5 } } }.to_json, f.to_json)
|
76
|
+
end
|
77
|
+
|
78
|
+
should "encode the JSON if define an histogram" do
|
79
|
+
f = Facet.new('histogram') { histogram :age, {:histogram => {:key_field => "age", :value_field => "age", :interval => 100}} }
|
80
|
+
assert_equal({ :histogram => { :histogram => {:key_field => "age", :value_field => "age", :interval => 100} } }.to_json, f.to_json)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
72
84
|
end
|
73
85
|
|
74
86
|
end
|
data/tire.gemspec
CHANGED
@@ -24,22 +24,31 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.required_rubygems_version = ">= 1.3.6"
|
26
26
|
|
27
|
+
# = Library dependencies
|
28
|
+
#
|
27
29
|
s.add_dependency "rake", ">= 0.8.0"
|
28
30
|
s.add_dependency "rest-client", "~> 1.6.0"
|
29
31
|
s.add_dependency "multi_json", "~> 1.0"
|
30
32
|
s.add_dependency "activemodel", "~> 3.0"
|
31
33
|
|
34
|
+
# = Development dependencies
|
35
|
+
#
|
32
36
|
s.add_development_dependency "bundler", "~> 1.0.0"
|
33
37
|
s.add_development_dependency "yajl-ruby", "~> 0.8.0"
|
34
|
-
s.add_development_dependency "turn"
|
35
38
|
s.add_development_dependency "shoulda"
|
36
39
|
s.add_development_dependency "mocha"
|
37
|
-
s.add_development_dependency "rdoc"
|
38
|
-
s.add_development_dependency "sdoc"
|
39
|
-
s.add_development_dependency "rcov"
|
40
40
|
s.add_development_dependency "activerecord", "~> 3.0.7"
|
41
|
-
s.add_development_dependency "supermodel"
|
42
41
|
s.add_development_dependency "sqlite3"
|
42
|
+
s.add_development_dependency "supermodel"
|
43
|
+
|
44
|
+
# These gems are not needed for CI at <http://travis-ci.org/#!/karmi/tire>
|
45
|
+
#
|
46
|
+
unless ENV["CI"]
|
47
|
+
s.add_development_dependency "sdoc"
|
48
|
+
s.add_development_dependency "rdoc"
|
49
|
+
s.add_development_dependency "rcov"
|
50
|
+
s.add_development_dependency "turn"
|
51
|
+
end
|
43
52
|
|
44
53
|
s.description = <<-DESC
|
45
54
|
Tire is a Ruby client for the ElasticSearch search engine/database.
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 2
|
8
|
-
-
|
9
|
-
version: 0.2.
|
8
|
+
- 1
|
9
|
+
version: 0.2.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Karel Minarik
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-09-01 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -100,7 +100,7 @@ dependencies:
|
|
100
100
|
type: :development
|
101
101
|
version_requirements: *id006
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
|
-
name:
|
103
|
+
name: shoulda
|
104
104
|
prerelease: false
|
105
105
|
requirement: &id007 !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
@@ -112,7 +112,7 @@ dependencies:
|
|
112
112
|
type: :development
|
113
113
|
version_requirements: *id007
|
114
114
|
- !ruby/object:Gem::Dependency
|
115
|
-
name:
|
115
|
+
name: mocha
|
116
116
|
prerelease: false
|
117
117
|
requirement: &id008 !ruby/object:Gem::Requirement
|
118
118
|
requirements:
|
@@ -124,19 +124,21 @@ dependencies:
|
|
124
124
|
type: :development
|
125
125
|
version_requirements: *id008
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
|
-
name:
|
127
|
+
name: activerecord
|
128
128
|
prerelease: false
|
129
129
|
requirement: &id009 !ruby/object:Gem::Requirement
|
130
130
|
requirements:
|
131
|
-
- -
|
131
|
+
- - ~>
|
132
132
|
- !ruby/object:Gem::Version
|
133
133
|
segments:
|
134
|
+
- 3
|
134
135
|
- 0
|
135
|
-
|
136
|
+
- 7
|
137
|
+
version: 3.0.7
|
136
138
|
type: :development
|
137
139
|
version_requirements: *id009
|
138
140
|
- !ruby/object:Gem::Dependency
|
139
|
-
name:
|
141
|
+
name: sqlite3
|
140
142
|
prerelease: false
|
141
143
|
requirement: &id010 !ruby/object:Gem::Requirement
|
142
144
|
requirements:
|
@@ -148,7 +150,7 @@ dependencies:
|
|
148
150
|
type: :development
|
149
151
|
version_requirements: *id010
|
150
152
|
- !ruby/object:Gem::Dependency
|
151
|
-
name:
|
153
|
+
name: supermodel
|
152
154
|
prerelease: false
|
153
155
|
requirement: &id011 !ruby/object:Gem::Requirement
|
154
156
|
requirements:
|
@@ -160,7 +162,7 @@ dependencies:
|
|
160
162
|
type: :development
|
161
163
|
version_requirements: *id011
|
162
164
|
- !ruby/object:Gem::Dependency
|
163
|
-
name:
|
165
|
+
name: sdoc
|
164
166
|
prerelease: false
|
165
167
|
requirement: &id012 !ruby/object:Gem::Requirement
|
166
168
|
requirements:
|
@@ -172,21 +174,19 @@ dependencies:
|
|
172
174
|
type: :development
|
173
175
|
version_requirements: *id012
|
174
176
|
- !ruby/object:Gem::Dependency
|
175
|
-
name:
|
177
|
+
name: rdoc
|
176
178
|
prerelease: false
|
177
179
|
requirement: &id013 !ruby/object:Gem::Requirement
|
178
180
|
requirements:
|
179
|
-
- -
|
181
|
+
- - ">="
|
180
182
|
- !ruby/object:Gem::Version
|
181
183
|
segments:
|
182
|
-
- 3
|
183
184
|
- 0
|
184
|
-
|
185
|
-
version: 3.0.7
|
185
|
+
version: "0"
|
186
186
|
type: :development
|
187
187
|
version_requirements: *id013
|
188
188
|
- !ruby/object:Gem::Dependency
|
189
|
-
name:
|
189
|
+
name: rcov
|
190
190
|
prerelease: false
|
191
191
|
requirement: &id014 !ruby/object:Gem::Requirement
|
192
192
|
requirements:
|
@@ -198,7 +198,7 @@ dependencies:
|
|
198
198
|
type: :development
|
199
199
|
version_requirements: *id014
|
200
200
|
- !ruby/object:Gem::Dependency
|
201
|
-
name:
|
201
|
+
name: turn
|
202
202
|
prerelease: false
|
203
203
|
requirement: &id015 !ruby/object:Gem::Requirement
|
204
204
|
requirements:
|
@@ -317,13 +317,21 @@ post_install_message: |
|
|
317
317
|
|
318
318
|
IMPORTANT CHANGES LATELY:
|
319
319
|
|
320
|
-
|
320
|
+
0.2.0
|
321
|
+
---------------------------------------------------------
|
322
|
+
# By default, results are wrapped in Item class
|
321
323
|
# Completely rewritten ActiveModel/ActiveRecord support
|
322
|
-
# Added
|
323
|
-
#
|
324
|
-
|
324
|
+
# Added infrastructure for loading "real" models from database (eagerly or in runtime)
|
325
|
+
# Deprecated the dynamic sort methods in favour of the 'sort { by :field_name }' syntax
|
326
|
+
|
327
|
+
0.2.1
|
328
|
+
---------------------------------------------------------
|
329
|
+
# Lighweight check for index presence
|
330
|
+
# Added the 'settings' method for models to define index settings
|
331
|
+
# Fixed errors when importing data with will_paginate vs Kaminari (MongoDB)
|
332
|
+
# Added support for histogram facets [Paco Guzman]
|
325
333
|
|
326
|
-
See the full changelog at <http://github.com/karmi/tire/commits/v0.2.
|
334
|
+
See the full changelog at <http://github.com/karmi/tire/commits/v0.2.1>.
|
327
335
|
|
328
336
|
--------------------------------------------------------------------------------
|
329
337
|
|