rsolr 1.1.2 → 2.0.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/rsolr/xml.rb CHANGED
@@ -2,100 +2,11 @@ begin; require 'nokogiri'; rescue LoadError; end
2
2
  require 'time'
3
3
 
4
4
  module RSolr::Xml
5
-
6
- class Document
7
-
8
- # "attrs" is a hash for setting the "doc" xml attributes
9
- # "fields" is an array of Field objects
10
- attr_accessor :attrs, :fields
11
-
12
- # "doc_hash" must be a Hash/Mash object
13
- # If a value in the "doc_hash" is an array,
14
- # a field object is created for each value...
15
- def initialize(doc_hash = {})
16
- @fields = []
17
- doc_hash.each_pair do |field,values|
18
- # create a new field for each value (multi-valued)
19
- wrap(values).each do |v|
20
- v = format_value(v)
21
- next if v.empty?
22
- @fields << RSolr::Xml::Field.new({:name=>field}, v)
23
- end
24
- end
25
- @attrs={}
26
- end
5
+ require 'rsolr/document'
27
6
 
28
- # returns an array of fields that match the "name" arg
29
- def fields_by_name(name)
30
- @fields.select{|f|f.name==name}
31
- end
32
-
33
- # returns the *first* field that matches the "name" arg
34
- def field_by_name(name)
35
- @fields.detect{|f|f.name==name}
36
- end
37
-
38
- #
39
- # Add a field value to the document. Options map directly to
40
- # XML attributes in the Solr <field> node.
41
- # See http://wiki.apache.org/solr/UpdateXmlMessages#head-8315b8028923d028950ff750a57ee22cbf7977c6
42
- #
43
- # === Example:
44
- #
45
- # document.add_field('title', 'A Title', :boost => 2.0)
46
- #
47
- def add_field(name, value, options = {})
48
- @fields << RSolr::Xml::Field.new(options.merge({:name=>name}), value)
49
- end
50
-
51
- private
52
-
53
- def format_value(v)
54
- case v
55
- when Time
56
- v.getutc.iso8601
57
- when DateTime
58
- v.to_time.getutc.iso8601
59
- when Date
60
- Time.utc(v.year, v.mon, v.mday).iso8601
61
- else
62
- v.to_s
63
- end
64
- end
7
+ Document = RSolr::Document
8
+ Field = RSolr::Field
65
9
 
66
- def wrap(object)
67
- if object.nil?
68
- []
69
- elsif object.respond_to?(:to_ary)
70
- object.to_ary || [object]
71
- elsif object.is_a? Enumerable
72
- object
73
- else
74
- [object]
75
- end
76
- end
77
- end
78
-
79
- class Field
80
-
81
- # "attrs" is a hash for setting the "doc" xml attributes
82
- # "value" is the text value for the node
83
- attr_accessor :attrs, :value
84
-
85
- # "attrs" must be a hash
86
- # "value" should be something that responds to #_to_s
87
- def initialize(attrs, value)
88
- @attrs = attrs
89
- @value = value
90
- end
91
-
92
- # the value of the "name" attribute
93
- def name
94
- @attrs[:name]
95
- end
96
-
97
- end
98
-
99
10
  class Generator
100
11
  class << self
101
12
  attr_accessor :use_nokogiri
@@ -162,13 +73,9 @@ module RSolr::Xml
162
73
  build do |xml|
163
74
  xml.add(add_attrs) do |add_node|
164
75
  data.each do |doc|
165
- doc = RSolr::Xml::Document.new(doc) if doc.respond_to?(:each_pair)
76
+ doc = RSolr::Document.new(doc) if doc.respond_to?(:each_pair)
166
77
  yield doc if block_given?
167
- doc_node_builder = lambda do |doc_node|
168
- doc.fields.each do |field_obj|
169
- doc_node.field field_obj.value, field_obj.attrs
170
- end
171
- end
78
+ doc_node_builder = to_xml(doc)
172
79
  self.class.use_nokogiri ? add_node.doc_(doc.attrs,&doc_node_builder) : add_node.doc(doc.attrs,&doc_node_builder)
173
80
  end
174
81
  end
@@ -215,5 +122,24 @@ module RSolr::Xml
215
122
  end
216
123
  end
217
124
  end
125
+
126
+ private
127
+
128
+ def to_xml(doc)
129
+ lambda do |doc_node|
130
+ doc.fields.each do |field_obj|
131
+ value = field_obj.value
132
+ if field_obj.name.to_s == RSolr::Document::CHILD_DOCUMENT_KEY
133
+ child_node_builder = to_xml(field_obj.value)
134
+ self.class.use_nokogiri ? doc_node.doc_(&child_node_builder) : doc_node.doc(&child_node_builder)
135
+ elsif value.is_a?(Hash) && value.length == 1 && field_obj.attrs[:update].nil?
136
+ update_attr, real_value = value.first
137
+ doc_node.field real_value, field_obj.attrs.merge(update: update_attr)
138
+ else
139
+ doc_node.field field_obj.value, field_obj.attrs
140
+ end
141
+ end
142
+ end
143
+ end
218
144
  end
219
145
  end
data/lib/rsolr.rb CHANGED
@@ -1,16 +1,15 @@
1
1
  module RSolr
2
-
3
2
  Dir.glob(File.expand_path("../rsolr/*.rb", __FILE__)).each{|rb_file| require(rb_file)}
4
-
3
+
5
4
  def self.connect *args
6
- driver = Class === args[0] ? args[0] : RSolr::Connection
7
- opts = Hash === args[-1] ? args[-1] : {}
8
- Client.new driver.new, opts
5
+ opts = args.pop if args.last.is_a?(::Hash)
6
+ opts ||= {}
7
+
8
+ connection = args.first
9
+
10
+ Client.new connection, opts
9
11
  end
10
-
11
- # RSolr.escape, which is deprecated as of 2015-02
12
- extend Char
13
-
12
+
14
13
  # backslash escape characters that have special meaning to Solr query parser
15
14
  # per http://lucene.apache.org/core/4_0_0/queryparser/org/apache/lucene/queryparser/classic/package-summary.html#Escaping_Special_Characters
16
15
  # + - & | ! ( ) { } [ ] ^ " ~ * ? : \ /
data/rsolr.gemspec CHANGED
@@ -32,6 +32,8 @@ Gem::Specification.new do |s|
32
32
  s.required_ruby_version = '>= 1.9.3'
33
33
 
34
34
  s.add_dependency 'builder', '>= 2.1.2'
35
+ s.add_dependency 'faraday'
36
+
35
37
  s.add_development_dependency 'activesupport'
36
38
  s.add_development_dependency 'nokogiri', '>= 1.4.0'
37
39
  s.add_development_dependency 'rake', '~> 10.0'
@@ -1,20 +1,15 @@
1
1
  require 'spec_helper'
2
- describe "RSolr::Client" do
3
2
 
4
- module ClientHelper
5
- def client
6
- @client ||= (
7
- connection = RSolr::Connection.new
8
- RSolr::Client.new connection, :url => "http://localhost:9999/solr", :read_timeout => 42, :open_timeout=>43
9
- )
10
- end
3
+ RSpec.describe RSolr::Client do
4
+ let(:connection) { nil }
5
+ let(:connection_options) { { url: "http://localhost:9999/solr", read_timeout: 42, open_timeout: 43, update_format: :xml } }
11
6
 
12
- def client_with_proxy
13
- @client_with_proxy ||= (
14
- connection = RSolr::Connection.new
15
- RSolr::Client.new connection, :url => "http://localhost:9999/solr", :proxy => 'http://localhost:8080', :read_timeout => 42, :open_timeout=>43
16
- )
17
- end
7
+ let(:client) do
8
+ RSolr::Client.new connection, connection_options
9
+ end
10
+
11
+ let(:client_with_proxy) do
12
+ RSolr::Client.new connection, connection_options.merge(proxy: 'http://localhost:8080')
18
13
  end
19
14
 
20
15
  context "initialize" do
@@ -49,61 +44,20 @@ describe "RSolr::Client" do
49
44
  end
50
45
 
51
46
  context "send_and_receive" do
52
- include ClientHelper
53
47
  it "should forward these method calls the #connection object" do
54
48
  [:get, :post, :head].each do |meth|
55
- expect(client.connection).to receive(:execute).
49
+ expect(client).to receive(:execute).
56
50
  and_return({:status => 200, :body => "{}", :headers => {}})
57
51
  client.send_and_receive '', :method => meth, :params => {}, :data => nil, :headers => {}
58
52
  end
59
53
  end
60
-
61
- it "should be timeout aware" do
62
- [:get, :post, :head].each do |meth|
63
- expect(client.connection).to receive(:execute).with(client, hash_including(:read_timeout => 42, :open_timeout=>43))
64
- client.send_and_receive '', :method => meth, :params => {}, :data => nil, :headers => {}
65
- end
66
- end
67
- end
68
-
69
- context "execute" do
70
- include ClientHelper
71
- let :request_context do
72
- {
73
- :method => :post,
74
- :params => {},
75
- :data => nil,
76
- :headers => {},
77
- :path => '',
78
- :uri => client.base_uri,
79
- :retry_503 => 1
80
- }
81
- end
82
- it "should retry 503s if requested" do
83
- expect(client.connection).to receive(:execute).exactly(2).times.and_return(
84
- {:status => 503, :body => "{}", :headers => {'Retry-After' => 0}},
85
- {:status => 200, :body => "{}", :headers => {}}
86
- )
87
- client.execute request_context
88
- end
89
- it "should not retry a 503 if the retry-after is too large" do
90
- expect(client.connection).to receive(:execute).exactly(1).times.and_return(
91
- {:status => 503, :body => "{}", :headers => {'Retry-After' => 10}}
92
- )
93
- expect {
94
- Timeout.timeout(0.5) do
95
- client.execute({:retry_after_limit => 0}.merge(request_context))
96
- end
97
- }.to raise_error(RSolr::Error::Http)
98
- end
99
54
  end
100
55
 
101
56
  context "post" do
102
- include ClientHelper
103
57
  it "should pass the expected params to the connection's #execute method" do
104
58
  request_opts = {:data => "the data", :method=>:post, :headers => {"Content-Type" => "text/plain"}}
105
- expect(client.connection).to receive(:execute).
106
- with(client, hash_including(request_opts)).
59
+ expect(client).to receive(:execute).
60
+ with(hash_including(request_opts)).
107
61
  and_return(
108
62
  :body => "",
109
63
  :status => 200,
@@ -114,18 +68,22 @@ describe "RSolr::Client" do
114
68
  end
115
69
 
116
70
  context "xml" do
117
- include ClientHelper
118
71
  it "should return an instance of RSolr::Xml::Generator" do
119
72
  expect(client.xml).to be_a RSolr::Xml::Generator
120
73
  end
121
74
  end
122
75
 
76
+ context "json" do
77
+ it "should return an instance of RSolr::JSON::Generator" do
78
+ expect(client.json).to be_a RSolr::JSON::Generator
79
+ end
80
+ end
81
+
123
82
  context "add" do
124
- include ClientHelper
125
83
  it "should send xml to the connection's #post method" do
126
- expect(client.connection).to receive(:execute).
84
+ expect(client).to receive(:execute).
127
85
  with(
128
- client, hash_including({
86
+ hash_including({
129
87
  :path => "update",
130
88
  :headers => {"Content-Type"=>"text/xml"},
131
89
  :method => :post,
@@ -142,14 +100,54 @@ describe "RSolr::Client" do
142
100
  and_return("<xml/>")
143
101
  client.add({:id=>1}, :add_attributes => {:commitWith=>10})
144
102
  end
103
+
104
+ context 'when the client is configured for json updates' do
105
+ let(:client) do
106
+ RSolr::Client.new nil, :url => "http://localhost:9999/solr", :read_timeout => 42, :open_timeout=>43, :update_format => :json
107
+ end
108
+ it "should send json to the connection's #post method" do
109
+ expect(client).to receive(:execute).
110
+ with(hash_including({
111
+ :path => 'update',
112
+ :headers => {"Content-Type" => 'application/json'},
113
+ :method => :post,
114
+ :data => '{"hello":"this is json"}'
115
+ })
116
+ ).
117
+ and_return(
118
+ :body => "",
119
+ :status => 200,
120
+ :headers => {"Content-Type"=>"text/xml"}
121
+ )
122
+ expect(client.json).to receive(:add).
123
+ with({:id => 1}, {:commitWith=>10}).
124
+ and_return('{"hello":"this is json"}')
125
+ client.add({:id=>1}, :add_attributes => {:commitWith=>10})
126
+ end
127
+
128
+ it "should send json to the connection's #post method" do
129
+ expect(client).to receive(:execute).
130
+ with(hash_including({
131
+ :path => 'update',
132
+ :headers => {'Content-Type'=>'application/json'},
133
+ :method => :post,
134
+ :data => '{"optimise" : {}}'
135
+ })
136
+ ).
137
+ and_return(
138
+ :body => "",
139
+ :status => 200,
140
+ :headers => {"Content-Type"=>"text/xml"}
141
+ )
142
+ client.update(:data => '{"optimise" : {}}')
143
+ end
144
+ end
145
145
  end
146
146
 
147
147
  context "update" do
148
- include ClientHelper
149
148
  it "should send data to the connection's #post method" do
150
- expect(client.connection).to receive(:execute).
151
- with(
152
- client, hash_including({
149
+ expect(client).to receive(:execute).
150
+ with(hash_including({
153
151
  :path => "update",
154
152
  :headers => {"Content-Type"=>"text/xml"},
155
153
  :method => :post,
@@ -178,12 +176,10 @@ describe "RSolr::Client" do
178
176
  end
179
177
 
180
178
  context "post based helper methods:" do
181
- include ClientHelper
182
179
  [:commit, :optimize, :rollback].each do |meth|
183
180
  it "should send a #{meth} message to the connection's #post method" do
184
- expect(client.connection).to receive(:execute).
185
- with(
186
- client, hash_including({
181
+ expect(client).to receive(:execute).
182
+ with(hash_including({
187
183
  :path => "update",
188
184
  :headers => {"Content-Type"=>"text/xml"},
189
185
  :method => :post,
@@ -201,11 +197,10 @@ describe "RSolr::Client" do
201
197
  end
202
198
 
203
199
  context "delete_by_id" do
204
- include ClientHelper
205
200
  it "should send data to the connection's #post method" do
206
- expect(client.connection).to receive(:execute).
201
+ expect(client).to receive(:execute).
207
202
  with(
208
- client, hash_including({
203
+ hash_including({
209
204
  :path => "update",
210
205
  :headers => {"Content-Type"=>"text/xml"},
211
206
  :method => :post,
@@ -222,11 +217,10 @@ describe "RSolr::Client" do
222
217
  end
223
218
 
224
219
  context "delete_by_query" do
225
- include ClientHelper
226
220
  it "should send data to the connection's #post method" do
227
- expect(client.connection).to receive(:execute).
221
+ expect(client).to receive(:execute).
228
222
  with(
229
- client, hash_including({
223
+ hash_including({
230
224
  :path => "update",
231
225
  :headers => {"Content-Type"=>"text/xml"},
232
226
  :method => :post,
@@ -243,7 +237,6 @@ describe "RSolr::Client" do
243
237
  end
244
238
 
245
239
  context "adapt_response" do
246
- include ClientHelper
247
240
  it 'should not try to evaluate ruby when the :qt is not :ruby' do
248
241
  body = '{"time"=>"NOW"}'
249
242
  result = client.adapt_response({:params=>{}}, {:status => 200, :body => body, :headers => {}})
@@ -281,9 +274,9 @@ describe "RSolr::Client" do
281
274
  end
282
275
 
283
276
  context "indifferent access" do
284
- include ClientHelper
285
277
  it "should raise a RuntimeError if the #with_indifferent_access extension isn't loaded" do
286
- hide_const("HashWithIndifferentAccess")
278
+ hide_const("::RSolr::HashWithIndifferentAccessWithResponse")
279
+ hide_const("ActiveSupport::HashWithIndifferentAccess")
287
280
  body = "{'foo'=>'bar'}"
288
281
  result = client.adapt_response({:params=>{:wt=>:ruby}}, {:status => 200, :body => body, :headers => {}})
289
282
  expect { result.with_indifferent_access }.to raise_error RuntimeError
@@ -306,7 +299,6 @@ describe "RSolr::Client" do
306
299
  end
307
300
 
308
301
  context "build_request" do
309
- include ClientHelper
310
302
  let(:data) { 'data' }
311
303
  let(:params) { { q: 'test', fq: [0,1] } }
312
304
  let(:options) { { method: :post, params: params, data: data, headers: {} } }
@@ -314,7 +306,7 @@ describe "RSolr::Client" do
314
306
 
315
307
  context "when params are symbols" do
316
308
  it 'should return a request context array' do
317
- [/fq=0/, /fq=1/, /q=test/, /wt=ruby/].each do |pattern|
309
+ [/fq=0/, /fq=1/, /q=test/, /wt=json/].each do |pattern|
318
310
  expect(subject[:query]).to match pattern
319
311
  end
320
312
  expect(subject[:data]).to eq("data")
@@ -336,11 +328,11 @@ describe "RSolr::Client" do
336
328
  let(:options) { { method: :post, data: data, headers: {} } }
337
329
 
338
330
  it "sets the Content-Type header to application/x-www-form-urlencoded; charset=UTF-8" do
339
- expect(subject[:query]).to eq("wt=ruby")
331
+ expect(subject[:query]).to eq("wt=json")
340
332
  [/fq=0/, /fq=1/, /q=test/].each do |pattern|
341
333
  expect(subject[:data]).to match pattern
342
334
  end
343
- expect(subject[:data]).not_to match /wt=ruby/
335
+ expect(subject[:data]).not_to match(/wt=json/)
344
336
  expect(subject[:headers]).to eq({"Content-Type" => "application/x-www-form-urlencoded; charset=UTF-8"})
345
337
  end
346
338
  end
@@ -351,7 +343,7 @@ describe "RSolr::Client" do
351
343
  :data => {:q=>'test', :fq=>[0,1]},
352
344
  :headers => {}
353
345
  )
354
- expect(result[:uri].to_s).to match /^http:\/\/localhost:9999\/solr\//
355
- end
346
+ expect(result[:uri].to_s).to match %r{^http://localhost:9999/solr/}
347
+ end
356
348
  end
357
349
  end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr::Document do
4
+ describe RSolr::Field do
5
+ describe ".instance" do
6
+ subject { RSolr::Field }
7
+
8
+ it "uses the class name of the field value" do
9
+ expect(subject.instance({}, Time.new)).to be_a_kind_of(RSolr::TimeField)
10
+ end
11
+
12
+ it "uses the provided type option when it is a class" do
13
+ expect(subject.instance({:type => RSolr::TimeField}, nil)).to be_a_kind_of(RSolr::TimeField)
14
+ end
15
+
16
+ it "uses the provided type option when it is a string" do
17
+ expect(subject.instance({:type => 'Time'}, nil)).to be_a_kind_of(RSolr::TimeField)
18
+ end
19
+
20
+ it "falls back to the base Field class" do
21
+ expect(subject.instance({:type => 'UndefinedType'}, nil)).to be_a_kind_of(RSolr::Field)
22
+ end
23
+
24
+ it "defaults to the base Field class" do
25
+ expect(subject.instance({}, nil)).to be_a_kind_of(RSolr::Field)
26
+ end
27
+ end
28
+ end
29
+
30
+ describe RSolr::TimeField do
31
+ it "convert value to string" do
32
+ time_value = Time.utc(2013, 9, 11, 18, 10, 0)
33
+ expect(RSolr::Field.instance({}, time_value).value).to eq '2013-09-11T18:10:00Z'
34
+ end
35
+
36
+ it "convert time to UTC" do
37
+ time_value = Time.new(2013, 9, 11, 18, 10, 0, '+02:00')
38
+ expect(RSolr::Field.instance({}, time_value).value).to eq '2013-09-11T16:10:00Z'
39
+ end
40
+ end
41
+
42
+ describe RSolr::DateField do
43
+ it "convert value to string" do
44
+ date_value = Date.new(2013, 9, 11)
45
+ expect(RSolr::Field.instance({}, date_value).value).to eq '2013-09-11T00:00:00Z'
46
+ end
47
+ end
48
+ end
@@ -1,5 +1,6 @@
1
1
  require 'spec_helper'
2
- describe "RSolr::Error" do
2
+
3
+ RSpec.describe RSolr::Error do
3
4
  def generate_error_with_backtrace(request, response)
4
5
  raise RSolr::Error::Http.new request, response
5
6
  rescue RSolr::Error::Http => exception
@@ -0,0 +1,175 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe RSolr::JSON do
4
+
5
+ let(:generator){ RSolr::JSON::Generator.new }
6
+
7
+ context :add do
8
+ # add a single hash ("doc")
9
+ it 'should create an add from a hash' do
10
+ data = {
11
+ :id=>"1",
12
+ :name=>'matt'
13
+ }
14
+ message = JSON.parse(generator.add(data), symbolize_names: true)
15
+ expect(message.length).to eq 1
16
+ expect(message.first).to eq data
17
+ end
18
+
19
+ # add an array of hashes
20
+ it 'should create many adds from an array of hashes' do
21
+ data = [
22
+ {
23
+ :id=>"1",
24
+ :name=>'matt'
25
+ },
26
+ {
27
+ :id=>"2",
28
+ :name=>'sam'
29
+ }
30
+ ]
31
+ message = JSON.parse(generator.add(data), symbolize_names: true)
32
+ expect(message).to eq data
33
+ end
34
+
35
+ it 'should yield a Document object when #add is called with a block' do
36
+ documents = [{:id=>1, :name=>'sam', :cat=>['cat 1', 'cat 2']}]
37
+ result = generator.add(documents) do |doc|
38
+ doc.field_by_name(:name).attrs[:boost] = 10
39
+ end
40
+
41
+ message = JSON.parse(result, symbolize_names: true)
42
+
43
+ expect(message.length).to eq 1
44
+ expect(message.first).to include name: { boost: 10, value: 'sam' }
45
+ end
46
+
47
+ context 'with add_attr' do
48
+ it 'should create an add command with the attributes from a hash' do
49
+ data = {
50
+ :id=>"1",
51
+ :name=>'matt'
52
+ }
53
+ message = JSON.parse(generator.add(data, boost: 1), symbolize_names: true)
54
+ expect(message).to include :add
55
+ expect(message[:add][:doc]).to eq data
56
+ expect(message[:add][:boost]).to eq 1
57
+ end
58
+
59
+ it 'should create multiple add command with the attributes from a hash' do
60
+ data = [
61
+ {
62
+ :id=>"1",
63
+ :name=>'matt'
64
+ },
65
+ {
66
+ :id=>"2",
67
+ :name=>'sam'
68
+ },
69
+ ]
70
+
71
+ # custom JSON object class to handle Solr's non-standard JSON command format
72
+ tmp = Class.new do
73
+ def initialize
74
+ @source ||= {}
75
+ end
76
+
77
+ def []=(k, v)
78
+ if k == :add
79
+ @source[k] ||= []
80
+ @source[k] << v.to_h
81
+ elsif v.class == self.class
82
+ @source[k] = v.to_h
83
+ else
84
+ @source[k] = v
85
+ end
86
+ end
87
+
88
+ def to_h
89
+ @source
90
+ end
91
+ end
92
+
93
+ request = generator.add(data, boost: 1)
94
+ message = JSON.parse(request, object_class: tmp, symbolize_names: true).to_h
95
+ expect(message[:add].length).to eq 2
96
+ expect(message[:add].map { |x| x[:doc] }).to eq data
97
+ end
98
+ end
99
+
100
+ it 'allows for atomic updates' do
101
+ data = {
102
+ foo: { set: 'Bar' }
103
+ }
104
+
105
+ message = JSON.parse(generator.add(data), symbolize_names: true)
106
+ expect(message.length).to eq 1
107
+ expect(message.first).to eq data
108
+ end
109
+
110
+ it 'supports nested child documents' do
111
+ data = {
112
+ _childDocuments_: [
113
+ {
114
+ id: 1
115
+ },
116
+ {
117
+ id: 2
118
+ }
119
+ ]
120
+ }
121
+
122
+ message = JSON.parse(generator.add(data), symbolize_names: true)
123
+ expect(message.length).to eq 1
124
+ expect(message.first).to eq data
125
+ end
126
+ end
127
+
128
+ it 'should create multiple fields from array values' do
129
+ data = {
130
+ :id => "1",
131
+ :name => ['matt1', 'matt2']
132
+ }
133
+ message = JSON.parse(generator.add(data), symbolize_names: true)
134
+ expect(message.length).to eq 1
135
+ expect(message.first).to eq data
136
+ end
137
+
138
+ describe '#commit' do
139
+ it 'generates a commit command' do
140
+ expect(JSON.parse(generator.commit, symbolize_names: true)).to eq(commit: {})
141
+ end
142
+ end
143
+
144
+ describe '#optimize' do
145
+ it 'generates a optimize command' do
146
+ expect(JSON.parse(generator.optimize, symbolize_names: true)).to eq(optimize: {})
147
+ end
148
+ end
149
+
150
+ describe '#rollback' do
151
+ it 'generates a rollback command' do
152
+ expect(JSON.parse(generator.rollback, symbolize_names: true)).to eq(rollback: {})
153
+ end
154
+ end
155
+
156
+ describe '#delete_by_id' do
157
+ it 'generates a delete_by_id command for single documents' do
158
+ expect(JSON.parse(generator.delete_by_id('x'), symbolize_names: true)).to eq(delete: 'x')
159
+ end
160
+
161
+ it 'generates a delete_by_id command for an array of documents' do
162
+ expect(JSON.parse(generator.delete_by_id(%w(a b c)), symbolize_names: true)).to eq(delete: %w(a b c))
163
+ end
164
+ end
165
+
166
+ describe '#delete_by_query' do
167
+ it 'generates a delete_by_id command for single documents' do
168
+ expect(JSON.parse(generator.delete_by_query('id:x'), symbolize_names: true)).to eq(delete: { query: 'id:x'})
169
+ end
170
+
171
+ it 'generates a delete_by_id command for an array of documents' do
172
+ expect(JSON.parse(generator.delete_by_id(%w(a b c)), symbolize_names: true)).to eq(delete: %w(a b c))
173
+ end
174
+ end
175
+ end