tire 0.4.0.pre → 0.4.0.rc
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/README.markdown +6 -10
- data/examples/rails-application-template.rb +6 -6
- data/examples/tire-dsl.rb +10 -9
- data/lib/tire.rb +8 -0
- data/lib/tire/dsl.rb +7 -6
- data/lib/tire/index.rb +22 -12
- data/lib/tire/model/import.rb +3 -2
- data/lib/tire/model/indexing.rb +21 -13
- data/lib/tire/model/naming.rb +2 -1
- data/lib/tire/model/persistence.rb +1 -1
- data/lib/tire/results/collection.rb +20 -17
- data/lib/tire/results/item.rb +1 -1
- data/lib/tire/rubyext/ruby_1_8.rb +7 -0
- data/lib/tire/search.rb +33 -19
- data/lib/tire/search/facet.rb +5 -0
- data/lib/tire/search/query.rb +8 -3
- data/lib/tire/tasks.rb +47 -14
- data/lib/tire/utils.rb +17 -0
- data/lib/tire/version.rb +13 -2
- data/test/integration/active_model_indexing_test.rb +1 -0
- data/test/integration/active_model_searchable_test.rb +7 -5
- data/test/integration/active_record_searchable_test.rb +159 -72
- data/test/integration/count_test.rb +34 -0
- data/test/integration/dsl_search_test.rb +22 -0
- data/test/integration/explanation_test.rb +44 -0
- data/test/integration/facets_test.rb +15 -0
- data/test/integration/fuzzy_queries_test.rb +20 -0
- data/test/integration/mongoid_searchable_test.rb +1 -0
- data/test/integration/persistent_model_test.rb +22 -1
- data/test/integration/text_query_test.rb +17 -3
- data/test/models/active_record_models.rb +43 -1
- data/test/models/mongoid_models.rb +0 -1
- data/test/models/persistent_article_in_namespace.rb +12 -0
- data/test/models/supermodel_article.rb +5 -10
- data/test/test_helper.rb +16 -2
- data/test/unit/index_test.rb +90 -16
- data/test/unit/model_import_test.rb +4 -4
- data/test/unit/model_search_test.rb +13 -10
- data/test/unit/results_collection_test.rb +6 -0
- data/test/unit/results_item_test.rb +8 -0
- data/test/unit/search_facet_test.rb +9 -0
- data/test/unit/search_query_test.rb +36 -7
- data/test/unit/search_test.rb +70 -1
- data/test/unit/tire_test.rb +23 -12
- data/tire.gemspec +11 -8
- metadata +90 -48
@@ -39,8 +39,8 @@ module Tire
|
|
39
39
|
end
|
40
40
|
|
41
41
|
should "call the passed block on every batch, and NOT manipulate the documents array" do
|
42
|
-
Tire::Index.any_instance.expects(:bulk_store).with
|
43
|
-
Tire::Index.any_instance.expects(:bulk_store).with
|
42
|
+
Tire::Index.any_instance.expects(:bulk_store).with { |c,o| c == [1, 2] }
|
43
|
+
Tire::Index.any_instance.expects(:bulk_store).with { |c,o| c == [3, 4] }
|
44
44
|
|
45
45
|
runs = 0
|
46
46
|
ImportModel.import :per_page => 2 do |documents|
|
@@ -53,8 +53,8 @@ module Tire
|
|
53
53
|
end
|
54
54
|
|
55
55
|
should "manipulate the documents in passed block" do
|
56
|
-
Tire::Index.any_instance.expects(:bulk_store).with
|
57
|
-
Tire::Index.any_instance.expects(:bulk_store).with
|
56
|
+
Tire::Index.any_instance.expects(:bulk_store).with { |c,o| c == [2, 3] }
|
57
|
+
Tire::Index.any_instance.expects(:bulk_store).with { |c,o| c == [4, 5] }
|
58
58
|
|
59
59
|
ImportModel.import :per_page => 2 do |documents|
|
60
60
|
# Add 1 to every "document" and return them
|
@@ -357,7 +357,13 @@ module Tire
|
|
357
357
|
:type => 'object',
|
358
358
|
:properties => {
|
359
359
|
:first_name => { :type => 'string' },
|
360
|
-
:last_name => { :type => 'string', :boost => 100 }
|
360
|
+
:last_name => { :type => 'string', :boost => 100 },
|
361
|
+
:posts => {
|
362
|
+
:type => 'object',
|
363
|
+
:properties => {
|
364
|
+
:title => { :type => 'string', :boost => 10 }
|
365
|
+
}
|
366
|
+
}
|
361
367
|
}
|
362
368
|
}
|
363
369
|
}
|
@@ -378,6 +384,10 @@ module Tire
|
|
378
384
|
indexes :author do
|
379
385
|
indexes :first_name, :type => 'string'
|
380
386
|
indexes :last_name, :type => 'string', :boost => 100
|
387
|
+
|
388
|
+
indexes :posts do
|
389
|
+
indexes :title, :type => 'string', :boost => 10
|
390
|
+
end
|
381
391
|
end
|
382
392
|
end
|
383
393
|
|
@@ -385,6 +395,7 @@ module Tire
|
|
385
395
|
|
386
396
|
assert_not_nil ModelWithNestedMapping.mapping[:author][:properties][:last_name]
|
387
397
|
assert_equal 100, ModelWithNestedMapping.mapping[:author][:properties][:last_name][:boost]
|
398
|
+
assert_equal 10, ModelWithNestedMapping.mapping[:author][:properties][:posts][:properties][:title][:boost]
|
388
399
|
end
|
389
400
|
|
390
401
|
should "define mapping for nested documents" do
|
@@ -519,20 +530,12 @@ module Tire
|
|
519
530
|
@model = ActiveModelArticle.new 'id' => 1, 'title' => 'Test'
|
520
531
|
assert_nil MultiJson.decode(@model.to_indexed_json)[:id]
|
521
532
|
assert_nil MultiJson.decode(@model.to_indexed_json)['id']
|
522
|
-
|
523
|
-
@model = SupermodelArticle.new 'id' => 1, 'title' => 'Test'
|
524
|
-
assert_nil MultiJson.decode(@model.to_indexed_json)[:id]
|
525
|
-
assert_nil MultiJson.decode(@model.to_indexed_json)['id']
|
526
533
|
end
|
527
534
|
|
528
535
|
should "not include the type property in serialized document (_source)" do
|
529
536
|
@model = ActiveModelArticle.new 'type' => 'foo', 'title' => 'Test'
|
530
537
|
assert_nil MultiJson.decode(@model.to_indexed_json)[:type]
|
531
538
|
assert_nil MultiJson.decode(@model.to_indexed_json)['type']
|
532
|
-
|
533
|
-
@model = SupermodelArticle.new 'type' => 'foo', 'title' => 'Test'
|
534
|
-
assert_nil MultiJson.decode(@model.to_indexed_json)[:type]
|
535
|
-
assert_nil MultiJson.decode(@model.to_indexed_json)['type']
|
536
539
|
end
|
537
540
|
|
538
541
|
should "serialize itself with serializable_hash when no mapping is set" do
|
@@ -592,7 +595,7 @@ module Tire
|
|
592
595
|
assert_equal( {:one => 1}.to_json, model.to_indexed_json )
|
593
596
|
|
594
597
|
end
|
595
|
-
|
598
|
+
|
596
599
|
should "serialize mapped properties when mapping procs are set" do
|
597
600
|
class ::ModelWithMappingProcs
|
598
601
|
extend ActiveModel::Naming
|
@@ -119,6 +119,12 @@ module Tire
|
|
119
119
|
assert_equal "article", document._type
|
120
120
|
end
|
121
121
|
|
122
|
+
should "properly decode type" do
|
123
|
+
@response = { 'hits' => { 'hits' => [ { '_id' => 1, '_type' => 'foo%2Fbar' } ] } }
|
124
|
+
document = Results::Collection.new(@response).first
|
125
|
+
assert_equal "foo/bar", document._type
|
126
|
+
end
|
127
|
+
|
122
128
|
end
|
123
129
|
|
124
130
|
context "wrapping results with selected fields" do
|
@@ -60,6 +60,14 @@ module Tire
|
|
60
60
|
assert_equal 'Test', @document.title
|
61
61
|
end
|
62
62
|
|
63
|
+
should "not care about symbols or strings in composite keys" do
|
64
|
+
@document = Results::Item.new :highlight => { 'name.ngrams' => 'abc' }
|
65
|
+
|
66
|
+
assert_not_nil @document.highlight['name.ngrams']
|
67
|
+
assert_equal 'abc', @document.highlight['name.ngrams']
|
68
|
+
assert_equal @document.highlight['name.ngrams'], @document.highlight['name.ngrams'.to_sym]
|
69
|
+
end
|
70
|
+
|
63
71
|
should "allow to retrieve values from nested hashes" do
|
64
72
|
assert_not_nil @document.author.name
|
65
73
|
assert_equal 'Kafka', @document.author.name
|
@@ -137,6 +137,15 @@ module Tire::Search
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
+
context "filter facet" do
|
141
|
+
should "encode facet options" do
|
142
|
+
f = Facet.new('filter_facet') do
|
143
|
+
filter :tags, 'ruby'
|
144
|
+
end
|
145
|
+
assert_equal({ :filter_facet => { :filter => { :term => { :tags => 'ruby' } } } }.to_json, f.to_json)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
140
149
|
end
|
141
150
|
|
142
151
|
end
|
@@ -5,26 +5,33 @@ module Tire::Search
|
|
5
5
|
class QueryTest < Test::Unit::TestCase
|
6
6
|
|
7
7
|
context "Query" do
|
8
|
-
|
9
8
|
should "be serialized to JSON" do
|
10
9
|
assert_respond_to Query.new, :to_json
|
11
10
|
end
|
12
11
|
|
13
12
|
should "return itself as a Hash" do
|
14
13
|
assert_respond_to Query.new, :to_hash
|
15
|
-
assert_equal( { :term => { :foo => 'bar' } }, Query.new.term(:foo, 'bar').to_hash )
|
14
|
+
assert_equal( { :term => { :foo => { :term => 'bar' } } }, Query.new.term(:foo, 'bar').to_hash )
|
16
15
|
end
|
17
16
|
|
18
17
|
should "allow a block to be given" do
|
19
|
-
assert_equal( { :term => { :foo => 'bar' } }.to_json, Query.new do
|
18
|
+
assert_equal( { :term => { :foo => { :term => 'bar' } } }.to_json, Query.new do
|
20
19
|
term(:foo, 'bar')
|
21
20
|
end.to_json)
|
22
21
|
end
|
22
|
+
end
|
23
23
|
|
24
|
+
context "Term query" do
|
24
25
|
should "allow search for single term" do
|
25
|
-
assert_equal( { :term => { :foo => 'bar' } }, Query.new.term(:foo, 'bar') )
|
26
|
+
assert_equal( { :term => { :foo => { :term => 'bar' } } }, Query.new.term(:foo, 'bar') )
|
26
27
|
end
|
27
28
|
|
29
|
+
should "allow search for single term passing an options hash" do
|
30
|
+
assert_equal( { :term => { :foo => { :term => 'bar', :boost => 2.0 } } }, Query.new.term(:foo, 'bar', :boost => 2.0) )
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context "Terms query" do
|
28
35
|
should "allow search for multiple terms" do
|
29
36
|
assert_equal( { :terms => { :foo => ['bar', 'baz'] } }, Query.new.terms(:foo, ['bar', 'baz']) )
|
30
37
|
end
|
@@ -33,11 +40,15 @@ module Tire::Search
|
|
33
40
|
assert_equal( { :terms => { :foo => ['bar', 'baz'], :minimum_match => 2 } },
|
34
41
|
Query.new.terms(:foo, ['bar', 'baz'], :minimum_match => 2) )
|
35
42
|
end
|
43
|
+
end
|
36
44
|
|
45
|
+
context "Range query" do
|
37
46
|
should "allow search for a range" do
|
38
47
|
assert_equal( { :range => { :age => { :gte => 21 } } }, Query.new.range(:age, { :gte => 21 }) )
|
39
48
|
end
|
49
|
+
end
|
40
50
|
|
51
|
+
context "Text query" do
|
41
52
|
should "allow search with a text search" do
|
42
53
|
assert_equal( { :text => {'field' => {:query => 'foo'}}}, Query.new.text('field', 'foo'))
|
43
54
|
end
|
@@ -46,7 +57,9 @@ module Tire::Search
|
|
46
57
|
assert_equal( { :text => {'field' => {:query => 'foo', :operator => 'and'}}},
|
47
58
|
Query.new.text('field', 'foo', :operator => 'and'))
|
48
59
|
end
|
60
|
+
end
|
49
61
|
|
62
|
+
context "Query String query" do
|
50
63
|
should "allow search with a query string" do
|
51
64
|
assert_equal( { :query_string => { :query => 'title:foo' } },
|
52
65
|
Query.new.string('title:foo') )
|
@@ -66,7 +79,9 @@ module Tire::Search
|
|
66
79
|
assert_equal( { :query_string => { :query => 'foo', :fields => ['title.*'], :use_dis_max => true } },
|
67
80
|
Query.new.string('foo', :fields => ['title.*'], :use_dis_max => true) )
|
68
81
|
end
|
82
|
+
end
|
69
83
|
|
84
|
+
context "Custom Score query" do
|
70
85
|
should "allow to set script for custom score queries" do
|
71
86
|
query = Query.new.custom_score(:script => "_score * doc['price'].value") do
|
72
87
|
string 'foo'
|
@@ -84,15 +99,30 @@ module Tire::Search
|
|
84
99
|
assert_equal 1, query[:custom_score][:params][:a]
|
85
100
|
assert_equal 2, query[:custom_score][:params][:b]
|
86
101
|
end
|
102
|
+
end
|
87
103
|
|
104
|
+
context "All query" do
|
88
105
|
should "search for all documents" do
|
89
106
|
assert_equal( { :match_all => { } }, Query.new.all )
|
90
107
|
end
|
108
|
+
end
|
91
109
|
|
110
|
+
context "IDs query" do
|
92
111
|
should "search for documents by IDs" do
|
93
112
|
assert_equal( { :ids => { :values => [1, 2], :type => 'foo' } },
|
94
113
|
Query.new.ids([1, 2], 'foo') )
|
95
114
|
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context "FuzzyQuery" do
|
118
|
+
|
119
|
+
should "allow a fuzzy search" do
|
120
|
+
assert_equal( { :fuzzy => { :foo => { :term => 'bar' } } }, Query.new.fuzzy(:foo, 'bar') )
|
121
|
+
end
|
122
|
+
|
123
|
+
should "allow a fuzzy search with an options hash" do
|
124
|
+
assert_equal( { :term => { :foo => { :term => 'bar', :boost => 1.0, :min_similarity => 0.5 } } }, Query.new.term(:foo, 'bar', :boost => 1.0, :min_similarity => 0.5 ) )
|
125
|
+
end
|
96
126
|
|
97
127
|
end
|
98
128
|
|
@@ -159,7 +189,6 @@ module Tire::Search
|
|
159
189
|
|
160
190
|
end
|
161
191
|
|
162
|
-
|
163
192
|
context "FilteredQuery" do
|
164
193
|
|
165
194
|
should "not raise an error when no block is given" do
|
@@ -173,7 +202,7 @@ module Tire::Search
|
|
173
202
|
end
|
174
203
|
|
175
204
|
query[:filtered].tap do |f|
|
176
|
-
assert_equal( { :term => { :foo => 'bar' } }, f[:query].to_hash )
|
205
|
+
assert_equal( { :term => { :foo => { :term => 'bar' } } }, f[:query].to_hash )
|
177
206
|
assert_equal( { :tags => ['ruby'] }, f[:filter][:and].first[:terms] )
|
178
207
|
end
|
179
208
|
end
|
@@ -202,7 +231,7 @@ module Tire::Search
|
|
202
231
|
end
|
203
232
|
|
204
233
|
query[:filtered].tap do |f|
|
205
|
-
assert_equal( { :term => { :foo => 'bar' } }, f[:query].to_hash )
|
234
|
+
assert_equal( { :term => { :foo => { :term => 'bar' } } }, f[:query].to_hash )
|
206
235
|
assert_equal( { :tags => ['ruby'] }, f[:filter][:and].first[:terms] )
|
207
236
|
end
|
208
237
|
end
|
data/test/unit/search_test.rb
CHANGED
@@ -35,6 +35,48 @@ module Tire
|
|
35
35
|
assert_match %r|index/bar/_search|, s.url
|
36
36
|
end
|
37
37
|
|
38
|
+
should "allow to pass search parameters" do
|
39
|
+
s = Search::Search.new('index', :routing => 123, :timeout => 1) { query { string 'foo' } }
|
40
|
+
|
41
|
+
assert ! s.params.empty?
|
42
|
+
|
43
|
+
assert_match %r|routing=123|, s.params
|
44
|
+
assert_match %r|timeout=1|, s.params
|
45
|
+
end
|
46
|
+
|
47
|
+
should "encode search parameters in the request" do
|
48
|
+
Configuration.client.expects(:get).with do |url, payload|
|
49
|
+
url.include? 'routing=123&timeout=1'
|
50
|
+
end.returns mock_response( { 'hits' => { 'hits' => [ {:_id => 1} ] } }.to_json )
|
51
|
+
|
52
|
+
Search::Search.new('index', :routing => 123, :timeout => 1) { query { string 'foo' } }.perform
|
53
|
+
end
|
54
|
+
|
55
|
+
should "encode missing params as an empty string" do
|
56
|
+
Configuration.client.expects(:get).with do |url, payload|
|
57
|
+
(! url.include? '?') && (! url.include? '&')
|
58
|
+
end.returns mock_response( { 'hits' => { 'hits' => [ {:_id => 1} ] } }.to_json )
|
59
|
+
|
60
|
+
s = Search::Search.new('index') { query { string 'foo' } }
|
61
|
+
s.perform
|
62
|
+
|
63
|
+
assert_equal '', s.params
|
64
|
+
end
|
65
|
+
|
66
|
+
should "properly encode namespaced document type" do
|
67
|
+
Configuration.client.expects(:get).with do |url, payload|
|
68
|
+
url.match %r|index/my_application%2Farticle/_search|
|
69
|
+
end.returns mock_response( { 'hits' => { 'hits' => [ {:_id => 1} ] } }.to_json )
|
70
|
+
|
71
|
+
s = Search::Search.new('index', :type => 'my_application/article') do
|
72
|
+
query { string 'foo' }
|
73
|
+
end
|
74
|
+
s.perform
|
75
|
+
|
76
|
+
assert_match %r|index/my_application%2Farticle/_search|, s.url
|
77
|
+
assert_match %r|index/my_application%2Farticle/_search|, s.to_curl
|
78
|
+
end
|
79
|
+
|
38
80
|
should "allow to pass block to query" do
|
39
81
|
Search::Query.any_instance.expects(:instance_eval)
|
40
82
|
|
@@ -180,7 +222,7 @@ module Tire
|
|
180
222
|
hash = MultiJson.decode( s.to_json )
|
181
223
|
assert_equal [{'title' => 'desc'}, '_score'], hash['sort']
|
182
224
|
end
|
183
|
-
|
225
|
+
|
184
226
|
end
|
185
227
|
|
186
228
|
context "facets" do
|
@@ -343,6 +385,33 @@ module Tire
|
|
343
385
|
|
344
386
|
end
|
345
387
|
|
388
|
+
context "explain" do
|
389
|
+
|
390
|
+
should "default to false" do
|
391
|
+
s = Search::Search.new('index') do
|
392
|
+
end
|
393
|
+
hash = MultiJson.decode( s.to_json )
|
394
|
+
assert_nil hash['explain']
|
395
|
+
end
|
396
|
+
|
397
|
+
should "set the explain field in the request when true" do
|
398
|
+
s = Search::Search.new('index') do
|
399
|
+
explain true
|
400
|
+
end
|
401
|
+
hash = MultiJson.decode( s.to_json )
|
402
|
+
assert_equal true, hash['explain']
|
403
|
+
end
|
404
|
+
|
405
|
+
should "not set the explain field when false" do
|
406
|
+
s = Search::Search.new('index') do
|
407
|
+
explain false
|
408
|
+
end
|
409
|
+
hash = MultiJson.decode( s.to_json )
|
410
|
+
assert_nil hash['explain']
|
411
|
+
end
|
412
|
+
|
413
|
+
end
|
414
|
+
|
346
415
|
context "boolean queries" do
|
347
416
|
|
348
417
|
should "wrap other queries" do
|
data/test/unit/tire_test.rb
CHANGED
@@ -23,21 +23,17 @@ module Tire
|
|
23
23
|
end
|
24
24
|
|
25
25
|
should "allow searching with a Ruby Hash" do
|
26
|
-
|
27
|
-
|
28
|
-
returns( mock_response('{}') )
|
29
|
-
Tire::Results::Collection.expects(:new)
|
26
|
+
payload = { :query => { :query_string => { :query => 'foo' } } }
|
27
|
+
Search::Search.expects(:new).with('dummy', :payload => payload).returns( stub(:perform => true) )
|
30
28
|
|
31
|
-
Tire.search 'dummy',
|
29
|
+
Tire.search 'dummy', payload
|
32
30
|
end
|
33
31
|
|
34
32
|
should "allow searching with a JSON string" do
|
35
|
-
|
36
|
-
|
37
|
-
returns( mock_response('{}') )
|
38
|
-
Tire::Results::Collection.expects(:new)
|
33
|
+
payload = '{"query":{"query_string":{"query":"foo"}}}'
|
34
|
+
Search::Search.expects(:new).with('dummy', :payload => payload).returns( stub(:perform => true) )
|
39
35
|
|
40
|
-
Tire.search 'dummy',
|
36
|
+
Tire.search 'dummy', payload
|
41
37
|
end
|
42
38
|
|
43
39
|
should "raise an error when passed incorrect payload" do
|
@@ -48,8 +44,8 @@ module Tire
|
|
48
44
|
|
49
45
|
should "raise SearchRequestFailed when receiving bad response from backend" do
|
50
46
|
assert_raise(Search::SearchRequestFailed) do
|
51
|
-
Tire::Configuration.client.expects(:
|
52
|
-
Tire.search
|
47
|
+
Tire::Configuration.client.expects(:get).returns( mock_response('INDEX DOES NOT EXIST', 404) )
|
48
|
+
Tire.search('not-existing', :query => { :query_string => { :query => 'foo' }}).results
|
53
49
|
end
|
54
50
|
end
|
55
51
|
|
@@ -70,6 +66,21 @@ module Tire
|
|
70
66
|
|
71
67
|
end
|
72
68
|
|
69
|
+
context "utils" do
|
70
|
+
|
71
|
+
should "encode a string for URL" do
|
72
|
+
assert_equal 'foo+bar', Utils.escape('foo bar')
|
73
|
+
assert_equal 'foo%2Fbar', Utils.escape('foo/bar')
|
74
|
+
assert_equal 'foo%21', Utils.escape('foo!')
|
75
|
+
end
|
76
|
+
|
77
|
+
should "encode a string from URL" do
|
78
|
+
assert_equal 'foo bar', Utils.unescape('foo+bar')
|
79
|
+
assert_equal 'foo/bar', Utils.unescape('foo%2Fbar')
|
80
|
+
assert_equal 'foo!', Utils.unescape('foo%21')
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
73
84
|
end
|
74
85
|
|
75
86
|
end
|
data/tire.gemspec
CHANGED
@@ -28,27 +28,30 @@ Gem::Specification.new do |s|
|
|
28
28
|
#
|
29
29
|
s.add_dependency "rake"
|
30
30
|
s.add_dependency "rest-client", "~> 1.6.0"
|
31
|
-
s.add_dependency "multi_json", "~> 1.
|
32
|
-
s.add_dependency "activemodel", "
|
33
|
-
s.add_dependency "hashr", "~> 0.0.
|
31
|
+
s.add_dependency "multi_json", "~> 1.1"
|
32
|
+
s.add_dependency "activemodel", ">= 3.0"
|
33
|
+
s.add_dependency "hashr", "~> 0.0.19"
|
34
|
+
s.add_dependency "rack", ">= 1.4" if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
|
34
35
|
|
35
36
|
# = Development dependencies
|
36
37
|
#
|
37
|
-
s.add_development_dependency "bundler", "
|
38
|
+
s.add_development_dependency "bundler", ">= 1.1"
|
38
39
|
s.add_development_dependency "yajl-ruby", "~> 0.8.0"
|
39
40
|
s.add_development_dependency "shoulda"
|
40
41
|
s.add_development_dependency "mocha"
|
41
|
-
s.add_development_dependency "activerecord", "
|
42
|
-
s.add_development_dependency "mongoid", "~> 2.2.1"
|
42
|
+
s.add_development_dependency "activerecord", ">= 3.0"
|
43
43
|
s.add_development_dependency "sqlite3"
|
44
|
-
s.add_development_dependency "
|
44
|
+
s.add_development_dependency "mongoid", "~> 2.2.1"
|
45
|
+
s.add_development_dependency "bson_ext"
|
46
|
+
s.add_development_dependency "redis-persistence"
|
45
47
|
s.add_development_dependency "curb"
|
48
|
+
s.add_development_dependency "minitest"
|
46
49
|
|
47
50
|
# These gems are not needed for CI at <http://travis-ci.org/#!/karmi/tire>
|
48
51
|
#
|
49
52
|
unless ENV["CI"]
|
50
53
|
s.add_development_dependency "rdoc"
|
51
|
-
s.add_development_dependency "turn", "~> 0.9"
|
54
|
+
s.add_development_dependency "turn", "~> 0.9" if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
|
52
55
|
end
|
53
56
|
|
54
57
|
s.description = <<-DESC
|