tire 0.2.0 → 0.2.1
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/.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
|
|