solr-ruby 0.0.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/lib/solr.rb +18 -0
- data/lib/solr/connection.rb +158 -0
- data/lib/solr/document.rb +71 -0
- data/lib/solr/exception.rb +13 -0
- data/lib/solr/field.rb +35 -0
- data/lib/solr/request.rb +24 -0
- data/lib/solr/request/add_document.rb +63 -0
- data/lib/solr/request/base.rb +29 -0
- data/lib/solr/request/commit.rb +21 -0
- data/lib/solr/request/delete.rb +50 -0
- data/lib/solr/request/dismax.rb +43 -0
- data/lib/solr/request/index_info.rb +17 -0
- data/lib/solr/request/optimize.rb +21 -0
- data/lib/solr/request/ping.rb +36 -0
- data/lib/solr/request/select.rb +54 -0
- data/lib/solr/request/standard.rb +105 -0
- data/lib/solr/request/update.rb +22 -0
- data/lib/solr/response.rb +24 -0
- data/lib/solr/response/add_document.rb +17 -0
- data/lib/solr/response/base.rb +42 -0
- data/lib/solr/response/commit.rb +32 -0
- data/lib/solr/response/delete.rb +13 -0
- data/lib/solr/response/dismax.rb +8 -0
- data/lib/solr/response/index_info.rb +26 -0
- data/lib/solr/response/optimize.rb +14 -0
- data/lib/solr/response/ping.rb +28 -0
- data/lib/solr/response/ruby.rb +42 -0
- data/lib/solr/response/standard.rb +60 -0
- data/lib/solr/response/xml.rb +37 -0
- data/lib/solr/xml.rb +47 -0
- data/test/unit/add_document_test.rb +40 -0
- data/test/unit/commit_test.rb +41 -0
- data/test/unit/connection_test.rb +55 -0
- data/test/unit/delete_test.rb +56 -0
- data/test/unit/dismax_request_test.rb +26 -0
- data/test/unit/document_test.rb +59 -0
- data/test/unit/field_test.rb +42 -0
- data/test/unit/ping_test.rb +51 -0
- data/test/unit/request_test.rb +61 -0
- data/test/unit/response_test.rb +42 -0
- data/test/unit/solr_mock_base.rb +40 -0
- data/test/unit/standard_request_test.rb +108 -0
- data/test/unit/standard_response_test.rb +174 -0
- data/test/unit/suite.rb +25 -0
- metadata +92 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
class Solr::Response::IndexInfo < Solr::Response::Ruby
|
14
|
+
def initialize(ruby_code)
|
15
|
+
super(ruby_code)
|
16
|
+
end
|
17
|
+
|
18
|
+
def num_docs
|
19
|
+
return @data['index']['numDocs']
|
20
|
+
end
|
21
|
+
|
22
|
+
def field_names
|
23
|
+
return @data['fields'].keys
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
class Solr::Response::Optimize < Solr::Response::Commit
|
14
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
require 'rexml/xpath'
|
14
|
+
|
15
|
+
class Solr::Response::Ping < Solr::Response::Xml
|
16
|
+
|
17
|
+
def initialize(xml)
|
18
|
+
super(xml)
|
19
|
+
@ok = REXML::XPath.first(@doc, './solr/ping') ? true : false
|
20
|
+
end
|
21
|
+
|
22
|
+
# returns true or false depending on whether the ping
|
23
|
+
# was successful or not
|
24
|
+
def ok?
|
25
|
+
@ok
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
class Solr::Response::Ruby < Solr::Response::Base
|
14
|
+
attr_reader :data
|
15
|
+
|
16
|
+
def initialize(ruby_code)
|
17
|
+
super(ruby_code)
|
18
|
+
begin
|
19
|
+
#TODO: what about pulling up data/header/response to ResponseBase,
|
20
|
+
# or maybe a new middle class like SelectResponseBase since
|
21
|
+
# all Select queries return this same sort of stuff??
|
22
|
+
# XML (&wt=xml) and Ruby (&wt=ruby) responses contain exactly the same structure.
|
23
|
+
# a goal of solrb is to make it irrelevant which gets used under the hood,
|
24
|
+
# but favor Ruby responses.
|
25
|
+
@data = eval(ruby_code)
|
26
|
+
@header = @data['responseHeader']
|
27
|
+
raise "response should be a hash" unless @data.kind_of? Hash
|
28
|
+
raise "response header missing" unless @header.kind_of? Hash
|
29
|
+
rescue SyntaxError => e
|
30
|
+
raise Solr::Exception.new("invalid ruby code: #{e}")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def ok?
|
35
|
+
@header['status'] == 0
|
36
|
+
end
|
37
|
+
|
38
|
+
def query_time
|
39
|
+
@header['QTime']
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
class Solr::Response::Standard < Solr::Response::Ruby
|
14
|
+
FacetValue = Struct.new(:name, :value)
|
15
|
+
include Enumerable
|
16
|
+
|
17
|
+
def initialize(ruby_code)
|
18
|
+
super(ruby_code)
|
19
|
+
@response = @data['response']
|
20
|
+
raise "response section missing" unless @response.kind_of? Hash
|
21
|
+
end
|
22
|
+
|
23
|
+
def total_hits
|
24
|
+
@response['numFound']
|
25
|
+
end
|
26
|
+
|
27
|
+
def start
|
28
|
+
@response['start']
|
29
|
+
end
|
30
|
+
|
31
|
+
def hits
|
32
|
+
@response['docs']
|
33
|
+
end
|
34
|
+
|
35
|
+
def max_score
|
36
|
+
@response['maxScore']
|
37
|
+
end
|
38
|
+
|
39
|
+
def field_facets(field)
|
40
|
+
facets = []
|
41
|
+
values = @data['facet_counts']['facet_fields'][field]
|
42
|
+
0.upto(values.size / 2 - 1) do |i|
|
43
|
+
n = i * 2
|
44
|
+
facets << FacetValue.new(values[n], values[n+1])
|
45
|
+
end
|
46
|
+
|
47
|
+
facets
|
48
|
+
end
|
49
|
+
|
50
|
+
def highlighted(id, field)
|
51
|
+
@data['highlighting'][id.to_s][field.to_s]
|
52
|
+
end
|
53
|
+
|
54
|
+
# supports enumeration of hits
|
55
|
+
# TODO revisit - should this iterate through *all* hits by re-requesting more?
|
56
|
+
def each
|
57
|
+
@response['docs'].each {|hit| yield hit}
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
require 'rexml/document'
|
14
|
+
require 'solr/exception'
|
15
|
+
|
16
|
+
class Solr::Response::Xml < Solr::Response::Base
|
17
|
+
attr_reader :doc, :status_code, :status_message
|
18
|
+
|
19
|
+
def initialize(xml)
|
20
|
+
super(xml)
|
21
|
+
# parse the xml
|
22
|
+
@doc = REXML::Document.new(xml)
|
23
|
+
# look for the result code and string
|
24
|
+
result = REXML::XPath.first(@doc, './result')
|
25
|
+
if result
|
26
|
+
@status_code = result.attributes['status']
|
27
|
+
@status_message = result.text
|
28
|
+
end
|
29
|
+
rescue REXML::ParseException => e
|
30
|
+
raise Solr::Exception.new("invalid response xml: #{e}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def ok?
|
34
|
+
return @status_code == '0'
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
data/lib/solr/xml.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
module Solr::XML
|
14
|
+
end
|
15
|
+
|
16
|
+
begin
|
17
|
+
|
18
|
+
# If we can load rubygems and libxml-ruby...
|
19
|
+
require 'rubygems'
|
20
|
+
require 'xml/libxml'
|
21
|
+
|
22
|
+
# then make a few modifications to XML::Node so it can stand in for REXML::Element
|
23
|
+
class XML::Node
|
24
|
+
# element.add_element(another_element) should work
|
25
|
+
alias_method :add_element, :<<
|
26
|
+
|
27
|
+
# element.attributes['blah'] should work
|
28
|
+
def attributes
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
# element.text = "blah" should work
|
33
|
+
def text=(x)
|
34
|
+
self << x.to_s
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# And use XML::Node for our XML generation
|
39
|
+
Solr::XML::Element = XML::Node
|
40
|
+
|
41
|
+
rescue LoadError => e # If we can't load either rubygems or libxml-ruby
|
42
|
+
|
43
|
+
# Just use REXML.
|
44
|
+
require 'rexml/document'
|
45
|
+
Solr::XML::Element = REXML::Element
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
require 'solr_mock_base'
|
14
|
+
|
15
|
+
class AddDocumentTest < SolrMockBaseTestCase
|
16
|
+
|
17
|
+
def test_add_document_response
|
18
|
+
conn = Solr::Connection.new('http://localhost:9999/solr')
|
19
|
+
set_post_return('<result status="0"></result>')
|
20
|
+
doc = {:id => '123', :text => 'Tlon, Uqbar, Orbis Tertius'}
|
21
|
+
response = conn.send(Solr::Request::AddDocument.new(doc))
|
22
|
+
assert_equal true, response.ok?
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_bad_add_document_response
|
26
|
+
conn = Solr::Connection.new('http://localhost:9999/solr')
|
27
|
+
set_post_return('<result status="400"></result>')
|
28
|
+
doc = {:id => '123', :text => 'Tlon, Uqbar, Orbis Tertius'}
|
29
|
+
response = conn.send(Solr::Request::AddDocument.new(doc))
|
30
|
+
assert_equal false, response.ok?
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_shorthand
|
34
|
+
conn = Solr::Connection.new('http://localhost:9999/solr')
|
35
|
+
set_post_return('<result status="0"></result>')
|
36
|
+
doc = {:id => '123', :text => 'Tlon, Uqbar, Orbis Tertius'}
|
37
|
+
assert_equal true, conn.add(:id => '123', :text => 'Tlon, Uqbar, Orbis Tetius')
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
require 'solr_mock_base'
|
14
|
+
|
15
|
+
class CommitTest < SolrMockBaseTestCase
|
16
|
+
|
17
|
+
def test_commit
|
18
|
+
xml = '<result status="0"></result>'
|
19
|
+
conn = Solr::Connection.new('http://localhost:9999/solr')
|
20
|
+
set_post_return(xml)
|
21
|
+
response = conn.send(Solr::Request::Commit.new)
|
22
|
+
assert_kind_of Solr::Response::Commit, response
|
23
|
+
assert true, response.ok?
|
24
|
+
|
25
|
+
# test shorthand
|
26
|
+
assert_equal true, conn.commit
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_invalid_commit
|
30
|
+
xml = '<foo>bar</foo>'
|
31
|
+
conn = Solr::Connection.new('http://localhost:9999/solr')
|
32
|
+
set_post_return(xml)
|
33
|
+
response = conn.send(Solr::Request::Commit.new)
|
34
|
+
assert_kind_of Solr::Response::Commit, response
|
35
|
+
assert_equal false, response.ok?
|
36
|
+
|
37
|
+
# test shorthand
|
38
|
+
assert_equal false, conn.commit
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
require 'test/unit'
|
14
|
+
require 'solr'
|
15
|
+
require 'solr_mock_base'
|
16
|
+
|
17
|
+
class ConnectionTest < SolrMockBaseTestCase
|
18
|
+
def test_mock
|
19
|
+
connection = Connection.new("http://localhost:9999")
|
20
|
+
set_post_return("foo")
|
21
|
+
assert_equal "foo", connection.post(Solr::Request::AddDocument.new)
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_bad_url
|
25
|
+
assert_raise(RuntimeError) do
|
26
|
+
Connection.new("ftp://localhost:9999")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_connection_initialize
|
31
|
+
connection = Solr::Connection.new("http://localhost:8983/solr")
|
32
|
+
assert_equal 'localhost', connection.url.host
|
33
|
+
assert_equal 8983, connection.url.port
|
34
|
+
assert_equal '/solr', connection.url.path
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_non_standard_context
|
38
|
+
connection = Solr::Connection.new("http://localhost:8983/index")
|
39
|
+
assert_equal '/index', connection.url.path
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_xml_response
|
43
|
+
connection = Connection.new("http://localhost:9999")
|
44
|
+
set_post_return "<bogus/>"
|
45
|
+
response = connection.send(Solr::Request::Ping.new)
|
46
|
+
assert_equal "<bogus/>", response.raw_response
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_ruby_response
|
50
|
+
connection = Connection.new("http://localhost:9999")
|
51
|
+
set_post_return "{'responseHeader' => {}, 'response' => {}}"
|
52
|
+
response = connection.send(Solr::Request::Standard.new(:query => 'foo'))
|
53
|
+
assert_equal({'responseHeader' => {}, 'response' => {}}, response.data)
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# The ASF licenses this file to You under the Apache License, Version 2.0
|
2
|
+
# (the "License"); you may not use this file except in compliance with
|
3
|
+
# the License. You may obtain a copy of the License at
|
4
|
+
#
|
5
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
#
|
7
|
+
# Unless required by applicable law or agreed to in writing, software
|
8
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
9
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
10
|
+
# See the License for the specific language governing permissions and
|
11
|
+
# limitations under the License.
|
12
|
+
|
13
|
+
require 'solr_mock_base'
|
14
|
+
|
15
|
+
class DeleteTest < SolrMockBaseTestCase
|
16
|
+
|
17
|
+
def test_delete_request
|
18
|
+
request = Solr::Request::Delete.new(:id => '123')
|
19
|
+
assert_match(/<delete>[\s]*<id>123<\/id>[\s]*<\/delete>/m, request.to_s)
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_delete_by_query_request
|
23
|
+
request = Solr::Request::Delete.new(:query => 'name:summers')
|
24
|
+
assert_match(/<delete>[\s]*<query>name:summers<\/query>[\s]*<\/delete>/m, request.to_s)
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_delete_response
|
28
|
+
conn = Solr::Connection.new 'http://localhost:9999/solr'
|
29
|
+
set_post_return('<result status="0"></result>')
|
30
|
+
response = conn.send(Solr::Request::Delete.new(:id => 123))
|
31
|
+
assert_equal true, response.ok?
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_bad_delete_request
|
35
|
+
assert_raise(Solr::Exception) do
|
36
|
+
Solr::Request::Delete.new(:bogus => :param)
|
37
|
+
end
|
38
|
+
|
39
|
+
assert_raise(Solr::Exception) do
|
40
|
+
Solr::Request::Delete.new(:id => 529, :query => "id:529")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_bad_delete_response
|
45
|
+
conn = Solr::Connection.new 'http://localhost:9999/solr'
|
46
|
+
set_post_return('<result status="400">uhoh</result>')
|
47
|
+
response = conn.send(Solr::Request::Delete.new(:id => 123))
|
48
|
+
assert_equal false, response.ok?
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_delete_by_i18n_query_request
|
52
|
+
request = Solr::Request::Delete.new(:query => 'ëäïöü')
|
53
|
+
assert_match(/<delete>[\s]*<query>ëäïöü<\/query>[\s]*<\/delete>/m, request.to_s)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|