elasticsearch-model 0.0.1 → 0.1.0.rc1
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/.gitignore +3 -0
- data/LICENSE.txt +1 -1
- data/README.md +669 -8
- data/Rakefile +52 -0
- data/elasticsearch-model.gemspec +48 -17
- data/examples/activerecord_article.rb +77 -0
- data/examples/activerecord_associations.rb +153 -0
- data/examples/couchbase_article.rb +66 -0
- data/examples/datamapper_article.rb +71 -0
- data/examples/mongoid_article.rb +68 -0
- data/examples/ohm_article.rb +70 -0
- data/examples/riak_article.rb +52 -0
- data/gemfiles/3.gemfile +11 -0
- data/gemfiles/4.gemfile +11 -0
- data/lib/elasticsearch/model.rb +151 -1
- data/lib/elasticsearch/model/adapter.rb +145 -0
- data/lib/elasticsearch/model/adapters/active_record.rb +97 -0
- data/lib/elasticsearch/model/adapters/default.rb +44 -0
- data/lib/elasticsearch/model/adapters/mongoid.rb +90 -0
- data/lib/elasticsearch/model/callbacks.rb +35 -0
- data/lib/elasticsearch/model/client.rb +61 -0
- data/lib/elasticsearch/model/importing.rb +94 -0
- data/lib/elasticsearch/model/indexing.rb +332 -0
- data/lib/elasticsearch/model/naming.rb +101 -0
- data/lib/elasticsearch/model/proxy.rb +127 -0
- data/lib/elasticsearch/model/response.rb +70 -0
- data/lib/elasticsearch/model/response/base.rb +44 -0
- data/lib/elasticsearch/model/response/pagination.rb +96 -0
- data/lib/elasticsearch/model/response/records.rb +71 -0
- data/lib/elasticsearch/model/response/result.rb +50 -0
- data/lib/elasticsearch/model/response/results.rb +32 -0
- data/lib/elasticsearch/model/searching.rb +107 -0
- data/lib/elasticsearch/model/serializing.rb +35 -0
- data/lib/elasticsearch/model/support/forwardable.rb +44 -0
- data/lib/elasticsearch/model/version.rb +1 -1
- data/test/integration/active_record_associations_parent_child.rb +138 -0
- data/test/integration/active_record_associations_test.rb +306 -0
- data/test/integration/active_record_basic_test.rb +139 -0
- data/test/integration/active_record_import_test.rb +74 -0
- data/test/integration/active_record_namespaced_model_test.rb +49 -0
- data/test/integration/active_record_pagination_test.rb +109 -0
- data/test/integration/mongoid_basic_test.rb +178 -0
- data/test/test_helper.rb +57 -0
- data/test/unit/adapter_active_record_test.rb +93 -0
- data/test/unit/adapter_default_test.rb +31 -0
- data/test/unit/adapter_mongoid_test.rb +87 -0
- data/test/unit/adapter_test.rb +69 -0
- data/test/unit/callbacks_test.rb +30 -0
- data/test/unit/client_test.rb +27 -0
- data/test/unit/importing_test.rb +97 -0
- data/test/unit/indexing_test.rb +364 -0
- data/test/unit/module_test.rb +46 -0
- data/test/unit/naming_test.rb +76 -0
- data/test/unit/proxy_test.rb +88 -0
- data/test/unit/response_base_test.rb +40 -0
- data/test/unit/response_pagination_test.rb +159 -0
- data/test/unit/response_records_test.rb +87 -0
- data/test/unit/response_result_test.rb +52 -0
- data/test/unit/response_results_test.rb +31 -0
- data/test/unit/response_test.rb +57 -0
- data/test/unit/searching_search_request_test.rb +73 -0
- data/test/unit/searching_test.rb +39 -0
- data/test/unit/serializing_test.rb +17 -0
- metadata +418 -11
@@ -0,0 +1,88 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::SearchTest < Test::Unit::TestCase
|
4
|
+
context "Searching module" do
|
5
|
+
class ::DummyProxyModel
|
6
|
+
include Elasticsearch::Model::Proxy
|
7
|
+
|
8
|
+
def self.foo
|
9
|
+
'classy foo'
|
10
|
+
end
|
11
|
+
|
12
|
+
def bar
|
13
|
+
'insta barr'
|
14
|
+
end
|
15
|
+
|
16
|
+
def as_json(options)
|
17
|
+
{foo: 'bar'}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class ::DummyProxyModelWithCallbacks
|
22
|
+
def self.before_save(&block)
|
23
|
+
(@callbacks ||= {})[block.hash] = block
|
24
|
+
end
|
25
|
+
|
26
|
+
def changed_attributes; [:foo]; end
|
27
|
+
|
28
|
+
def changes
|
29
|
+
{:foo => ['One', 'Two']}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
should "setup the class proxy method" do
|
34
|
+
assert_respond_to DummyProxyModel, :__elasticsearch__
|
35
|
+
end
|
36
|
+
|
37
|
+
should "setup the instance proxy method" do
|
38
|
+
assert_respond_to DummyProxyModel.new, :__elasticsearch__
|
39
|
+
end
|
40
|
+
|
41
|
+
should "register the hook for before_save callback" do
|
42
|
+
::DummyProxyModelWithCallbacks.expects(:before_save).returns(true)
|
43
|
+
DummyProxyModelWithCallbacks.__send__ :include, Elasticsearch::Model::Proxy
|
44
|
+
end
|
45
|
+
|
46
|
+
should "set the @__changed_attributes variable before save" do
|
47
|
+
instance = ::DummyProxyModelWithCallbacks.new
|
48
|
+
instance.__elasticsearch__.expects(:instance_variable_set).with do |name, value|
|
49
|
+
assert_equal :@__changed_attributes, name
|
50
|
+
assert_equal({foo: 'Two'}, value)
|
51
|
+
end
|
52
|
+
|
53
|
+
::DummyProxyModelWithCallbacks.__send__ :include, Elasticsearch::Model::Proxy
|
54
|
+
|
55
|
+
::DummyProxyModelWithCallbacks.instance_variable_get(:@callbacks).each do |n,b|
|
56
|
+
instance.instance_eval(&b)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
should "delegate methods to the target" do
|
61
|
+
assert_respond_to DummyProxyModel.__elasticsearch__, :foo
|
62
|
+
assert_respond_to DummyProxyModel.new.__elasticsearch__, :bar
|
63
|
+
|
64
|
+
assert_raise(NoMethodError) { DummyProxyModel.__elasticsearch__.xoxo }
|
65
|
+
assert_raise(NoMethodError) { DummyProxyModel.new.__elasticsearch__.xoxo }
|
66
|
+
|
67
|
+
assert_equal 'classy foo', DummyProxyModel.__elasticsearch__.foo
|
68
|
+
assert_equal 'insta barr', DummyProxyModel.new.__elasticsearch__.bar
|
69
|
+
end
|
70
|
+
|
71
|
+
should "return the proxy class from instance proxy" do
|
72
|
+
assert_equal Elasticsearch::Model::Proxy::ClassMethodsProxy, DummyProxyModel.new.__elasticsearch__.class.class
|
73
|
+
end
|
74
|
+
|
75
|
+
should "return the origin class from instance proxy" do
|
76
|
+
assert_equal DummyProxyModel, DummyProxyModel.new.__elasticsearch__.klass
|
77
|
+
end
|
78
|
+
|
79
|
+
should "delegate as_json from the proxy to target" do
|
80
|
+
assert_equal({foo: 'bar'}, DummyProxyModel.new.__elasticsearch__.as_json)
|
81
|
+
end
|
82
|
+
|
83
|
+
should "have inspect method indicating the proxy" do
|
84
|
+
assert_match /PROXY/, DummyProxyModel.__elasticsearch__.inspect
|
85
|
+
assert_match /PROXY/, DummyProxyModel.new.__elasticsearch__.inspect
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::BaseTest < Test::Unit::TestCase
|
4
|
+
context "Response base module" do
|
5
|
+
class OriginClass
|
6
|
+
def self.index_name; 'foo'; end
|
7
|
+
def self.document_type; 'bar'; end
|
8
|
+
end
|
9
|
+
|
10
|
+
class DummyBaseClass
|
11
|
+
include Elasticsearch::Model::Response::Base
|
12
|
+
end
|
13
|
+
|
14
|
+
RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [] } }
|
15
|
+
|
16
|
+
setup do
|
17
|
+
@search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
|
18
|
+
@response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
19
|
+
@search.stubs(:execute!).returns(RESPONSE)
|
20
|
+
end
|
21
|
+
|
22
|
+
should "access klass, response, total and max_score" do
|
23
|
+
r = DummyBaseClass.new OriginClass, @response
|
24
|
+
|
25
|
+
assert_equal OriginClass, r.klass
|
26
|
+
assert_equal @response, r.response
|
27
|
+
assert_equal RESPONSE, r.response.response
|
28
|
+
assert_equal 123, r.total
|
29
|
+
assert_equal 456, r.max_score
|
30
|
+
end
|
31
|
+
|
32
|
+
should "have abstract methods results and records" do
|
33
|
+
r = DummyBaseClass.new OriginClass, @response
|
34
|
+
|
35
|
+
assert_raise(Elasticsearch::Model::NotImplemented) { |e| r.results }
|
36
|
+
assert_raise(Elasticsearch::Model::NotImplemented) { |e| r.records }
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::ResponsePaginationTest < Test::Unit::TestCase
|
4
|
+
context "Response pagination" do
|
5
|
+
class ModelClass
|
6
|
+
include ::Kaminari::ConfigurationMethods
|
7
|
+
|
8
|
+
def self.index_name; 'foo'; end
|
9
|
+
def self.document_type; 'bar'; end
|
10
|
+
end
|
11
|
+
|
12
|
+
RESPONSE = { 'took' => '5', 'timed_out' => false, '_shards' => {'one' => 'OK'},
|
13
|
+
'hits' => { 'total' => 100, 'hits' => (1..100).to_a.map { |i| { _id: i } } } }
|
14
|
+
|
15
|
+
setup do
|
16
|
+
@search = Elasticsearch::Model::Searching::SearchRequest.new ModelClass, '*'
|
17
|
+
@response = Elasticsearch::Model::Response::Response.new ModelClass, @search, RESPONSE
|
18
|
+
@response.klass.stubs(:client).returns mock('client')
|
19
|
+
end
|
20
|
+
|
21
|
+
should "have pagination methods" do
|
22
|
+
assert_respond_to @response, :page
|
23
|
+
assert_respond_to @response, :limit_value
|
24
|
+
assert_respond_to @response, :offset_value
|
25
|
+
assert_respond_to @response, :limit
|
26
|
+
assert_respond_to @response, :offset
|
27
|
+
assert_respond_to @response, :total_count
|
28
|
+
end
|
29
|
+
|
30
|
+
context "#page method" do
|
31
|
+
should "advance the from/size" do
|
32
|
+
@response.klass.client
|
33
|
+
.expects(:search)
|
34
|
+
.with do |definition|
|
35
|
+
assert_equal 25, definition[:from]
|
36
|
+
assert_equal 25, definition[:size]
|
37
|
+
end
|
38
|
+
.returns(RESPONSE)
|
39
|
+
|
40
|
+
assert_nil @response.search.definition[:from]
|
41
|
+
assert_nil @response.search.definition[:size]
|
42
|
+
|
43
|
+
@response.page(2).to_a
|
44
|
+
assert_equal 25, @response.search.definition[:from]
|
45
|
+
assert_equal 25, @response.search.definition[:size]
|
46
|
+
end
|
47
|
+
|
48
|
+
should "advance the from/size further" do
|
49
|
+
@response.klass.client
|
50
|
+
.expects(:search)
|
51
|
+
.with do |definition|
|
52
|
+
assert_equal 75, definition[:from]
|
53
|
+
assert_equal 25, definition[:size]
|
54
|
+
end
|
55
|
+
.returns(RESPONSE)
|
56
|
+
|
57
|
+
@response.page(4).to_a
|
58
|
+
assert_equal 75, @response.search.definition[:from]
|
59
|
+
assert_equal 25, @response.search.definition[:size]
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "limit/offset readers" do
|
64
|
+
should "return the default" do
|
65
|
+
assert_equal 0, @response.limit_value
|
66
|
+
assert_equal 0, @response.offset_value
|
67
|
+
end
|
68
|
+
|
69
|
+
should "return the value from URL parameters" do
|
70
|
+
search = Elasticsearch::Model::Searching::SearchRequest.new ModelClass, '*', size: 10, from: 50
|
71
|
+
@response = Elasticsearch::Model::Response::Response.new ModelClass, search, RESPONSE
|
72
|
+
|
73
|
+
assert_equal 10, @response.limit_value
|
74
|
+
assert_equal 50, @response.offset_value
|
75
|
+
end
|
76
|
+
|
77
|
+
should "return the value from body" do
|
78
|
+
search = Elasticsearch::Model::Searching::SearchRequest.new ModelClass, { query: { match_all: {} }, from: 10, size: 50 }
|
79
|
+
@response = Elasticsearch::Model::Response::Response.new ModelClass, search, RESPONSE
|
80
|
+
|
81
|
+
assert_equal 50, @response.limit_value
|
82
|
+
assert_equal 10, @response.offset_value
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "limit setter" do
|
87
|
+
setup do
|
88
|
+
@response.records
|
89
|
+
@response.results
|
90
|
+
end
|
91
|
+
|
92
|
+
should "set the values" do
|
93
|
+
@response.limit(35)
|
94
|
+
assert_equal 35, @response.search.definition[:size]
|
95
|
+
end
|
96
|
+
|
97
|
+
should "reset the variables" do
|
98
|
+
@response.limit(35)
|
99
|
+
|
100
|
+
assert_nil @response.instance_variable_get(:@response)
|
101
|
+
assert_nil @response.instance_variable_get(:@records)
|
102
|
+
assert_nil @response.instance_variable_get(:@results)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "offset setter" do
|
107
|
+
setup do
|
108
|
+
@response.records
|
109
|
+
@response.results
|
110
|
+
end
|
111
|
+
|
112
|
+
should "set the values" do
|
113
|
+
@response.offset(15)
|
114
|
+
assert_equal 15, @response.search.definition[:from]
|
115
|
+
end
|
116
|
+
|
117
|
+
should "reset the variables" do
|
118
|
+
@response.offset(35)
|
119
|
+
|
120
|
+
assert_nil @response.instance_variable_get(:@response)
|
121
|
+
assert_nil @response.instance_variable_get(:@records)
|
122
|
+
assert_nil @response.instance_variable_get(:@results)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
context "total" do
|
127
|
+
should "return the number of hits" do
|
128
|
+
@response.expects(:results).returns(mock('results', total: 100))
|
129
|
+
assert_equal 100, @response.total_count
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context "results" do
|
134
|
+
setup do
|
135
|
+
@search.stubs(:execute!).returns RESPONSE
|
136
|
+
end
|
137
|
+
|
138
|
+
should "return current page and total count" do
|
139
|
+
assert_equal 1, @response.page(1).results.current_page
|
140
|
+
assert_equal 100, @response.results.total_count
|
141
|
+
|
142
|
+
assert_equal 5, @response.page(5).results.current_page
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
context "records" do
|
147
|
+
setup do
|
148
|
+
@search.stubs(:execute!).returns RESPONSE
|
149
|
+
end
|
150
|
+
|
151
|
+
should "return current page and total count" do
|
152
|
+
assert_equal 1, @response.page(1).records.current_page
|
153
|
+
assert_equal 100, @response.records.total_count
|
154
|
+
|
155
|
+
assert_equal 5, @response.page(5).records.current_page
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::RecordsTest < Test::Unit::TestCase
|
4
|
+
context "Response records" do
|
5
|
+
class DummyCollection
|
6
|
+
include Enumerable
|
7
|
+
|
8
|
+
def each(&block); ['FOO'].each(&block); end
|
9
|
+
def size; ['FOO'].size; end
|
10
|
+
def empty?; ['FOO'].empty?; end
|
11
|
+
def foo; 'BAR'; end
|
12
|
+
end
|
13
|
+
|
14
|
+
class DummyModel
|
15
|
+
def self.index_name; 'foo'; end
|
16
|
+
def self.document_type; 'bar'; end
|
17
|
+
|
18
|
+
def self.find(*args)
|
19
|
+
DummyCollection.new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [{'foo' => 'bar'}] } }
|
24
|
+
RESULTS = Elasticsearch::Model::Response::Results.new DummyModel, RESPONSE
|
25
|
+
|
26
|
+
setup do
|
27
|
+
search = Elasticsearch::Model::Searching::SearchRequest.new DummyModel, '*'
|
28
|
+
search.stubs(:execute!).returns RESPONSE
|
29
|
+
|
30
|
+
response = Elasticsearch::Model::Response::Response.new DummyModel, search
|
31
|
+
@records = Elasticsearch::Model::Response::Records.new DummyModel, response
|
32
|
+
end
|
33
|
+
|
34
|
+
should "access the records" do
|
35
|
+
assert_respond_to @records, :records
|
36
|
+
assert_equal 1, @records.records.size
|
37
|
+
assert_equal 'FOO', @records.records.first
|
38
|
+
end
|
39
|
+
|
40
|
+
should "delegate Enumerable methods to records" do
|
41
|
+
assert ! @records.empty?
|
42
|
+
assert_equal 'FOO', @records.first
|
43
|
+
end
|
44
|
+
|
45
|
+
should "delegate methods to records" do
|
46
|
+
assert_respond_to @records, :foo
|
47
|
+
assert_equal 'BAR', @records.foo
|
48
|
+
end
|
49
|
+
|
50
|
+
should "have each_with_hit method" do
|
51
|
+
@records.each_with_hit do |record, hit|
|
52
|
+
assert_equal 'FOO', record
|
53
|
+
assert_equal 'bar', hit.foo
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
should "have map_with_hit method" do
|
58
|
+
assert_equal ['FOO---bar'], @records.map_with_hit { |record, hit| "#{record}---#{hit.foo}" }
|
59
|
+
end
|
60
|
+
|
61
|
+
context "with adapter" do
|
62
|
+
module DummyAdapter
|
63
|
+
module RecordsMixin
|
64
|
+
def records
|
65
|
+
['FOOBAR']
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def records_mixin
|
70
|
+
RecordsMixin
|
71
|
+
end; module_function :records_mixin
|
72
|
+
end
|
73
|
+
|
74
|
+
should "delegate the records method to the adapter" do
|
75
|
+
Elasticsearch::Model::Adapter.expects(:from_class)
|
76
|
+
.with(DummyModel)
|
77
|
+
.returns(DummyAdapter)
|
78
|
+
|
79
|
+
@records = Elasticsearch::Model::Response::Records.new DummyModel,
|
80
|
+
RESPONSE
|
81
|
+
|
82
|
+
assert_equal ['FOOBAR'], @records.records
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::ResultTest < Test::Unit::TestCase
|
4
|
+
context "Response result" do
|
5
|
+
|
6
|
+
should "have method access to properties" do
|
7
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', bar: { bam: 'baz' }
|
8
|
+
|
9
|
+
assert_respond_to result, :foo
|
10
|
+
assert_respond_to result, :bar
|
11
|
+
|
12
|
+
assert_equal 'bar', result.foo
|
13
|
+
assert_equal 'baz', result.bar.bam
|
14
|
+
|
15
|
+
assert_raise(NoMethodError) { result.xoxo }
|
16
|
+
end
|
17
|
+
|
18
|
+
should "delegate method calls to `_source` when available" do
|
19
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: 'baz' }
|
20
|
+
|
21
|
+
assert_respond_to result, :foo
|
22
|
+
assert_respond_to result, :_source
|
23
|
+
assert_respond_to result, :bar
|
24
|
+
|
25
|
+
assert_equal 'bar', result.foo
|
26
|
+
assert_equal 'baz', result._source.bar
|
27
|
+
assert_equal 'baz', result.bar
|
28
|
+
end
|
29
|
+
|
30
|
+
should "delegate methods to @result" do
|
31
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar'
|
32
|
+
|
33
|
+
assert_equal 'bar', result.foo
|
34
|
+
assert_equal 'bar', result.fetch('foo')
|
35
|
+
assert_equal 'moo', result.fetch('NOT_EXIST', 'moo')
|
36
|
+
|
37
|
+
assert_respond_to result, :to_hash
|
38
|
+
assert_equal({'foo' => 'bar'}, result.to_hash)
|
39
|
+
|
40
|
+
assert_raise(NoMethodError) { result.does_not_exist }
|
41
|
+
end
|
42
|
+
|
43
|
+
should "delegate as_json to @result even when ActiveSupport changed half of Ruby" do
|
44
|
+
require 'active_support/json/encoding'
|
45
|
+
result = Elasticsearch::Model::Response::Result.new foo: 'bar'
|
46
|
+
|
47
|
+
result.instance_variable_get(:@result).expects(:as_json)
|
48
|
+
result.as_json(except: 'foo')
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class Elasticsearch::Model::ResultsTest < Test::Unit::TestCase
|
4
|
+
context "Response results" do
|
5
|
+
class OriginClass
|
6
|
+
def self.index_name; 'foo'; end
|
7
|
+
def self.document_type; 'bar'; end
|
8
|
+
end
|
9
|
+
|
10
|
+
RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [{'foo' => 'bar'}] } }
|
11
|
+
|
12
|
+
setup do
|
13
|
+
@search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
|
14
|
+
@response = Elasticsearch::Model::Response::Response.new OriginClass, @search
|
15
|
+
@results = Elasticsearch::Model::Response::Results.new OriginClass, @response
|
16
|
+
@search.stubs(:execute!).returns(RESPONSE)
|
17
|
+
end
|
18
|
+
|
19
|
+
should "access the results" do
|
20
|
+
assert_respond_to @results, :results
|
21
|
+
assert_equal 1, @results.results.size
|
22
|
+
assert_equal 'bar', @results.results.first.foo
|
23
|
+
end
|
24
|
+
|
25
|
+
should "delegate Enumerable methods to results" do
|
26
|
+
assert ! @results.empty?
|
27
|
+
assert_equal 'bar', @results.first.foo
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|