stretcher 1.3.2 → 1.3.3
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/stretcher.rb +2 -0
- data/lib/stretcher/es_component.rb +24 -0
- data/lib/stretcher/index.rb +16 -28
- data/lib/stretcher/index_type.rb +11 -10
- data/lib/stretcher/search_results.rb +5 -5
- data/lib/stretcher/server.rb +19 -19
- data/lib/stretcher/version.rb +1 -1
- data/spec/lib/stretcher_index_spec.rb +10 -10
- data/spec/lib/stretcher_index_type_spec.rb +13 -8
- data/spec/lib/stretcher_server_spec.rb +3 -3
- metadata +3 -2
data/lib/stretcher.rb
CHANGED
@@ -5,6 +5,8 @@ require 'faraday'
|
|
5
5
|
require 'faraday_middleware'
|
6
6
|
require "stretcher/version"
|
7
7
|
require 'stretcher/request_error'
|
8
|
+
require 'stretcher/search_results'
|
9
|
+
require 'stretcher/es_component'
|
8
10
|
require 'stretcher/server'
|
9
11
|
require 'stretcher/index'
|
10
12
|
require 'stretcher/index_type'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Stretcher
|
2
|
+
# Elasticsearch has symmetry across API endpoints for Server, Index, and Type, lets try and provide some common ground
|
3
|
+
class EsComponent
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def do_search(generic_opts={}, explicit_body=nil)
|
8
|
+
uri_str = '/_search'
|
9
|
+
body = nil
|
10
|
+
if explicit_body
|
11
|
+
uri_str << '?' + Util.querify(generic_opts)
|
12
|
+
body = explicit_body
|
13
|
+
else
|
14
|
+
body = generic_opts
|
15
|
+
end
|
16
|
+
|
17
|
+
logger.info { "Stretcher Search: curl -XGET '#{uri_str}' -d '#{body.to_json}'" }
|
18
|
+
response = @server.request(:get, path_uri(uri_str)) do |req|
|
19
|
+
req.body = body
|
20
|
+
end
|
21
|
+
SearchResults.new(:raw => response)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/stretcher/index.rb
CHANGED
@@ -2,9 +2,9 @@ require 'stretcher/search_results'
|
|
2
2
|
module Stretcher
|
3
3
|
# Represents an Index context in elastic search.
|
4
4
|
# Generally should be instantiated via Server#index(name).
|
5
|
-
class Index
|
5
|
+
class Index < EsComponent
|
6
6
|
attr_reader :server, :name, :logger
|
7
|
-
|
7
|
+
|
8
8
|
def initialize(server, name, options={})
|
9
9
|
@server = server
|
10
10
|
@name = name
|
@@ -14,14 +14,14 @@ module Stretcher
|
|
14
14
|
# Returns a Stretcher::IndexType object for the type +name+.
|
15
15
|
# Optionally takes a block, which will be passed a single arg with the Index obj
|
16
16
|
# The block syntax returns the evaluated value of the block
|
17
|
-
#
|
17
|
+
#
|
18
18
|
# my_index.index(:foo) # => #<Stretcher::Index ...>
|
19
19
|
# my_index.index(:foo) {|idx| 1+1} # => 2
|
20
20
|
def type(name, &block)
|
21
21
|
t = IndexType.new(self, name)
|
22
22
|
block ? block.call(t) : t
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
# Given a hash of documents, will bulk index
|
26
26
|
#
|
27
27
|
# docs = [{"_type" => "tweet", "_id" => 91011, "text" => "Bulked"}]
|
@@ -42,7 +42,7 @@ module Stretcher
|
|
42
42
|
req.body = options
|
43
43
|
end
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
# Deletes the index
|
47
47
|
def delete
|
48
48
|
@server.request :delete, path_uri
|
@@ -52,27 +52,27 @@ module Stretcher
|
|
52
52
|
def stats
|
53
53
|
@server.request :get, path_uri("/_stats")
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
# Retrieves status for this index
|
57
57
|
def status
|
58
|
-
@server.request :get, path_uri("/_status")
|
58
|
+
@server.request :get, path_uri("/_status")
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
# Retrieve the mapping for this index
|
62
62
|
def get_mapping
|
63
63
|
@server.request :get, path_uri("/_mapping")
|
64
64
|
end
|
65
|
-
|
65
|
+
|
66
66
|
# Retrieve settings for this index
|
67
67
|
def get_settings
|
68
68
|
@server.request :get, path_uri("/_settings")
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
# Check if the index has been created on the remote server
|
72
72
|
def exists?
|
73
73
|
@server.http.head(path_uri).status != 404
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
# Issues a search with the given query opts and body, both should be hashes
|
77
77
|
#
|
78
78
|
# res = server.index('foo').search(size: 12, {query: {match_all: {}}})
|
@@ -82,22 +82,10 @@ module Stretcher
|
|
82
82
|
# res.results # => [#<Hashie::Mash _id="123" text="Hello">]
|
83
83
|
# res.raw # => #<Hashie::Mash ...> Raw JSON from the search
|
84
84
|
def search(generic_opts={}, explicit_body=nil)
|
85
|
-
|
86
|
-
|
87
|
-
if explicit_body
|
88
|
-
uri_str << '?' + Util.querify(generic_opts)
|
89
|
-
body = explicit_body
|
90
|
-
else
|
91
|
-
body = generic_opts
|
92
|
-
end
|
93
|
-
|
94
|
-
logger.info { "Stretcher Search: curl -XGET '#{uri_str}' -d '#{body.to_json}'" }
|
95
|
-
response = @server.request(:get, path_uri(uri_str)) do |req|
|
96
|
-
req.body = body
|
97
|
-
end
|
98
|
-
SearchResults.new(raw: response)
|
85
|
+
# Written this way to be more RDoc friendly
|
86
|
+
do_search(generic_opts, explicit_body)
|
99
87
|
end
|
100
|
-
|
88
|
+
|
101
89
|
# Searches a list of queries against only this index
|
102
90
|
# This deviates slightly from the official API in that *ONLY*
|
103
91
|
# queries are requried, the empty {} preceding them are not
|
@@ -108,7 +96,7 @@ module Stretcher
|
|
108
96
|
def msearch(queries=[])
|
109
97
|
raise ArgumentError, "msearch takes an array!" unless queries.is_a?(Array)
|
110
98
|
req_body = queries.reduce([]) {|acc,q|
|
111
|
-
acc << {index
|
99
|
+
acc << {:index => name}
|
112
100
|
acc << q
|
113
101
|
acc
|
114
102
|
}
|
@@ -116,7 +104,7 @@ module Stretcher
|
|
116
104
|
end
|
117
105
|
|
118
106
|
# Implements the Analyze API
|
119
|
-
# EX:
|
107
|
+
# EX:
|
120
108
|
# index.analyze("Candles", analyzer: :snowball)
|
121
109
|
# # => #<Hashie::Mash tokens=[#<Hashie::Mash end_offset=7 position=1 start_offset=0 token="candl" type="<ALPHANUM>">]>
|
122
110
|
def analyze(text, analysis_params)
|
data/lib/stretcher/index_type.rb
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
module Stretcher
|
2
2
|
# Represents an index scoped to a specific type.
|
3
3
|
# Generally should be instantiated via Index#type(name).
|
4
|
-
class IndexType
|
4
|
+
class IndexType < EsComponent
|
5
5
|
attr_reader :server, :index, :name, :logger
|
6
|
-
|
6
|
+
|
7
7
|
def initialize(index, name, options={})
|
8
8
|
@index = index
|
9
9
|
@server = index.server
|
@@ -17,12 +17,12 @@ module Stretcher
|
|
17
17
|
res = server.request(:get, path_uri("/#{id}"))
|
18
18
|
raw ? res : res["_source"]
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
# Index an item with a specific ID
|
22
22
|
def put(id, source)
|
23
23
|
server.request(:put, path_uri("/#{id}"), source)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Uses the update api to modify a document with a script
|
27
27
|
# To update a doc with ID 987 for example:
|
28
28
|
# type.update(987, script: "ctx._source.message = 'Updated!'")
|
@@ -30,11 +30,11 @@ module Stretcher
|
|
30
30
|
def update(id, body)
|
31
31
|
server.request(:post, path_uri("/#{id}/_update"), body)
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
# Deletes the document with the given ID
|
35
35
|
def delete(id)
|
36
36
|
res = server.http.delete path_uri("/#{id}")
|
37
|
-
|
37
|
+
|
38
38
|
# Since 404s are just not a problem here, let's simply return false
|
39
39
|
if res.status == 404
|
40
40
|
false
|
@@ -49,7 +49,7 @@ module Stretcher
|
|
49
49
|
def get_mapping
|
50
50
|
@server.request :get, path_uri("/_mapping")
|
51
51
|
end
|
52
|
-
|
52
|
+
|
53
53
|
# Delete the mapping for this type. Note this will delete
|
54
54
|
# All documents of this type as well
|
55
55
|
# http://www.elasticsearch.org/guide/reference/api/admin-indices-delete-mapping.html
|
@@ -63,7 +63,7 @@ module Stretcher
|
|
63
63
|
req.body = body
|
64
64
|
}
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
# Check if this index type is defined, if passed an id
|
68
68
|
# this will check if the given document exists
|
69
69
|
def exists?(id=nil)
|
@@ -72,8 +72,9 @@ module Stretcher
|
|
72
72
|
|
73
73
|
# Issues an Index#search scoped to this type
|
74
74
|
# See Index#search for more details
|
75
|
-
def search(generic_opts={},
|
76
|
-
|
75
|
+
def search(generic_opts={}, explicit_body=nil)
|
76
|
+
# Written this way to be more RDoc friendly
|
77
|
+
do_search(generic_opts, explicit_body)
|
77
78
|
end
|
78
79
|
|
79
80
|
# Full path to this index type
|
@@ -1,25 +1,25 @@
|
|
1
1
|
require 'hashie/dash'
|
2
2
|
module Stretcher
|
3
3
|
# Conveniently represents elastic search results in a more compact fashion
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Available properties:
|
6
|
-
#
|
6
|
+
#
|
7
7
|
# * raw : The raw response from elastic search
|
8
8
|
# * total : The total number of matched docs
|
9
9
|
# * facets : the facets hash
|
10
10
|
# * results : The hit results with _id merged in to _source
|
11
11
|
class SearchResults < Hashie::Dash
|
12
|
-
property :raw, required
|
12
|
+
property :raw, :required => true
|
13
13
|
property :total
|
14
14
|
property :facets
|
15
15
|
property :results
|
16
|
-
|
16
|
+
|
17
17
|
def initialize(*args)
|
18
18
|
super
|
19
19
|
self.total = raw.hits.total
|
20
20
|
self.facets = raw.facets
|
21
21
|
self.results = raw.hits.hits.collect {|r|
|
22
|
-
r['_source'].merge({"_id" => r['_id']})
|
22
|
+
(r.has_key?('_source') ? r['_source'] : r['fields']).merge({"_id" => r['_id']})
|
23
23
|
}
|
24
24
|
end
|
25
25
|
end
|
data/lib/stretcher/server.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module Stretcher
|
2
|
-
class Server
|
2
|
+
class Server < EsComponent
|
3
3
|
attr_reader :uri, :http, :logger
|
4
4
|
|
5
5
|
# Instantiate a new instance in a manner convenient for using the block syntax.
|
@@ -9,7 +9,7 @@ module Stretcher
|
|
9
9
|
s = self.new(*args)
|
10
10
|
yield s
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
# Represents a Server context in elastic search.
|
14
14
|
# Use +with_server+ when you want to use the block syntax.
|
15
15
|
# The options hash takes an optional instance of Logger under :logger.
|
@@ -18,25 +18,25 @@ module Stretcher
|
|
18
18
|
def initialize(uri='http://localhost:9200', options={})
|
19
19
|
@uri = uri
|
20
20
|
|
21
|
-
@http = Faraday.new(:url => @uri) do |builder|
|
21
|
+
@http = Faraday.new(:url => @uri) do |builder|
|
22
22
|
builder.response :mashify
|
23
23
|
builder.response :json, :content_type => /\bjson$/
|
24
|
-
|
24
|
+
|
25
25
|
builder.request :json
|
26
|
-
|
26
|
+
|
27
27
|
builder.adapter :net_http_persistent
|
28
|
-
|
28
|
+
|
29
29
|
builder.options[:read_timeout] = 4
|
30
30
|
builder.options[:open_timeout] = 2
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
if options[:logger]
|
34
34
|
@logger = options[:logger]
|
35
35
|
else
|
36
36
|
@logger = Logger.new(STDOUT)
|
37
37
|
@logger.level = Logger::WARN
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
@logger.formatter = proc do |severity, datetime, progname, msg|
|
41
41
|
"[Stretcher][#{severity}]: #{msg}\n"
|
42
42
|
end
|
@@ -45,11 +45,11 @@ module Stretcher
|
|
45
45
|
# Returns a Stretcher::Index object for the index +name+.
|
46
46
|
# Optionally takes a block, which will be passed a single arg with the Index obj
|
47
47
|
# The block syntax returns the evaluated value of the block
|
48
|
-
#
|
48
|
+
#
|
49
49
|
# my_server.index(:foo) # => #<Stretcher::Index ...>
|
50
50
|
# my_server.index(:foo) {|idx| 1+1} # => 2
|
51
51
|
def index(name, &block)
|
52
|
-
idx = Index.new(self, name, logger
|
52
|
+
idx = Index.new(self, name, :logger => logger)
|
53
53
|
block ? block.call(idx) : idx
|
54
54
|
end
|
55
55
|
|
@@ -68,13 +68,13 @@ module Stretcher
|
|
68
68
|
def status
|
69
69
|
request :get, path_uri("/_status")
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
# Returns true if the server is currently reachable, raises an error otherwise
|
73
73
|
def up?
|
74
74
|
request(:get, path_uri)
|
75
75
|
true
|
76
76
|
end
|
77
|
-
|
77
|
+
|
78
78
|
# Takes an array of msearch data as per
|
79
79
|
# http://www.elasticsearch.org/guide/reference/api/multi-search.html
|
80
80
|
# Should look something like:
|
@@ -92,13 +92,13 @@ module Stretcher
|
|
92
92
|
res = request(:get, path_uri("/_msearch")) {|req|
|
93
93
|
req.body = fmt_body
|
94
94
|
}
|
95
|
-
|
95
|
+
|
96
96
|
errors = res.responses.select {|r| r[:error]}.map(&:error)
|
97
97
|
if !errors.empty?
|
98
|
-
raise RequestError.new(res), "Could not msearch #{errors.inspect}"
|
98
|
+
raise RequestError.new(res), "Could not msearch #{errors.inspect}"
|
99
99
|
end
|
100
|
-
|
101
|
-
res['responses'].map {|r| SearchResults.new(raw
|
100
|
+
|
101
|
+
res['responses'].map {|r| SearchResults.new(:raw => r)}
|
102
102
|
end
|
103
103
|
|
104
104
|
# Retrieves multiple documents, possibly from multiple indexes
|
@@ -108,9 +108,9 @@ module Stretcher
|
|
108
108
|
req.body = body
|
109
109
|
}
|
110
110
|
end
|
111
|
-
|
111
|
+
|
112
112
|
# Implements the Analyze API
|
113
|
-
# EX:
|
113
|
+
# EX:
|
114
114
|
# server.analyze("Candles", analyzer: :snowball)
|
115
115
|
# # => #<Hashie::Mash tokens=[#<Hashie::Mash end_offset=7 position=1 start_offset=0 token="candl" type="<ALPHANUM>">]>
|
116
116
|
# as per: http://www.elasticsearch.org/guide/reference/api/admin-indices-analyze.html
|
@@ -128,7 +128,7 @@ module Stretcher
|
|
128
128
|
# Handy way to query the server, returning *only* the body
|
129
129
|
# Will raise an exception when the status is not in the 2xx range
|
130
130
|
def request(method, *args, &block)
|
131
|
-
logger.info { "Stretcher: Issuing Request #{method.upcase}, #{args}" }
|
131
|
+
logger.info { "Stretcher: Issuing Request #{method.to_s.upcase}, #{args}" }
|
132
132
|
res = if block
|
133
133
|
http.send(method, *args) do |req|
|
134
134
|
# Elastic search does mostly deal with JSON
|
data/lib/stretcher/version.rb
CHANGED
@@ -2,19 +2,19 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Stretcher::Index do
|
4
4
|
let(:server) {
|
5
|
-
Stretcher::Server.new(ES_URL, logger
|
5
|
+
Stretcher::Server.new(ES_URL, :logger => DEBUG_LOGGER)
|
6
6
|
}
|
7
7
|
let(:index) { server.index('foo') }
|
8
8
|
let(:corpus) {
|
9
9
|
[
|
10
|
-
{text
|
11
|
-
{text
|
12
|
-
{text
|
10
|
+
{:text => "Foo", "_type" => 'tweet', "_id" => 'fooid'},
|
11
|
+
{:text => "Bar", "_type" => 'tweet', "_id" => 'barid'},
|
12
|
+
{:text => "Baz", "_type" => 'tweet', "id" => 'bazid'} # Note we support both _id and id
|
13
13
|
]
|
14
14
|
}
|
15
15
|
|
16
16
|
def create_tweet_mapping
|
17
|
-
mdata = {tweet:
|
17
|
+
mdata = {:tweet => {:properties => {:text => {:type => :string}}}}
|
18
18
|
index.type('tweet').put_mapping(mdata)
|
19
19
|
end
|
20
20
|
|
@@ -22,7 +22,7 @@ describe Stretcher::Index do
|
|
22
22
|
create_tweet_mapping
|
23
23
|
index.bulk_index(corpus)
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
it "should work on an existential level" do
|
27
27
|
index.delete rescue nil
|
28
28
|
index.exists?.should be_false
|
@@ -67,26 +67,26 @@ describe Stretcher::Index do
|
|
67
67
|
seed_corpus
|
68
68
|
match_text = corpus.first[:text]
|
69
69
|
sleep 1 # ES needs time to update!
|
70
|
-
res = index.search({}, {query
|
70
|
+
res = index.search({}, {:query => {:match => {:text => match_text}}})
|
71
71
|
res.results.first.text.should == match_text
|
72
72
|
end
|
73
73
|
|
74
74
|
# TODO: Actually use two indexes
|
75
75
|
it "should msearch across the index returning all docs" do
|
76
76
|
seed_corpus
|
77
|
-
res = index.msearch([{query
|
77
|
+
res = index.msearch([{:query => {:match_all => {}}}])
|
78
78
|
res.length.should == 1
|
79
79
|
res[0].class.should == Stretcher::SearchResults
|
80
80
|
end
|
81
81
|
|
82
82
|
it "execute the analysis API and return an expected result" do
|
83
|
-
analyzed = index.analyze("Candles", analyzer
|
83
|
+
analyzed = index.analyze("Candles", :analyzer => :snowball)
|
84
84
|
analyzed.tokens.first.token.should == 'candl'
|
85
85
|
end
|
86
86
|
|
87
87
|
it "should raise an exception when msearching a non-existant index" do
|
88
88
|
lambda {
|
89
|
-
res = server.index(:does_not_exist).msearch([{query
|
89
|
+
res = server.index(:does_not_exist).msearch([{:query => {:match_all => {}}}])
|
90
90
|
}.should raise_exception(Stretcher::RequestError)
|
91
91
|
end
|
92
92
|
end
|
@@ -16,27 +16,32 @@ describe Stretcher::Index do
|
|
16
16
|
|
17
17
|
describe "searching" do
|
18
18
|
before do
|
19
|
-
@doc = {message
|
19
|
+
@doc = {:message => "hello"}
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should search and find the right doc" do
|
23
23
|
match_text = 'hello'
|
24
24
|
type.put(123123, @doc)
|
25
25
|
sleep 1
|
26
|
-
res = type.search({}, {query
|
26
|
+
res = type.search({}, {:query => {:match => {:message => match_text}}})
|
27
|
+
res.results.first.message.should == @doc[:message]
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should build results when _source is not included in loaded fields" do
|
31
|
+
res = type.search({}, {query: {match_all: {}}, fields: ['message']})
|
27
32
|
res.results.first.message.should == @doc[:message]
|
28
33
|
end
|
29
34
|
end
|
30
35
|
|
31
36
|
describe "put/get" do
|
32
37
|
before do
|
33
|
-
@doc = {message
|
38
|
+
@doc = {:message => "hello!"}
|
34
39
|
end
|
35
|
-
|
40
|
+
|
36
41
|
it "should put correctly" do
|
37
42
|
type.put(987, @doc).should_not be_nil
|
38
43
|
end
|
39
|
-
|
44
|
+
|
40
45
|
it "should get individual documents correctly" do
|
41
46
|
type.get(987).message.should == @doc[:message]
|
42
47
|
end
|
@@ -48,14 +53,14 @@ describe Stretcher::Index do
|
|
48
53
|
end
|
49
54
|
|
50
55
|
it "should update individual docs correctly" do
|
51
|
-
type.update(987, script
|
56
|
+
type.update(987, :script => "ctx._source.message = 'Updated!'")
|
52
57
|
type.get(987).message.should == 'Updated!'
|
53
58
|
end
|
54
|
-
|
59
|
+
|
55
60
|
it "should delete individual docs correctly" do
|
56
61
|
type.exists?(987).should be_true
|
57
62
|
type.delete(987)
|
58
|
-
type.exists?(987).should be_false
|
63
|
+
type.exists?(987).should be_false
|
59
64
|
end
|
60
65
|
end
|
61
66
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Stretcher::Server do
|
4
4
|
let(:server) { Stretcher::Server.new(ES_URL) }
|
5
|
-
|
5
|
+
|
6
6
|
it "should initialize cleanly" do
|
7
7
|
server.class.should == Stretcher::Server
|
8
8
|
end
|
@@ -28,7 +28,7 @@ describe Stretcher::Server do
|
|
28
28
|
it "should check the status w/o error" do
|
29
29
|
server.status.ok.should be_true
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
it "should beget an index object cleanly" do
|
33
33
|
server.index('foo').class.should == Stretcher::Index
|
34
34
|
end
|
@@ -44,7 +44,7 @@ describe Stretcher::Server do
|
|
44
44
|
end
|
45
45
|
|
46
46
|
it "execute the analysis API and return an expected result" do
|
47
|
-
analyzed = server.analyze("Candles", analyzer
|
47
|
+
analyzed = server.analyze("Candles", :analyzer => :snowball)
|
48
48
|
analyzed.tokens.first.token.should == 'candl'
|
49
49
|
end
|
50
50
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stretcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-03-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
@@ -152,6 +152,7 @@ files:
|
|
152
152
|
- README.md
|
153
153
|
- Rakefile
|
154
154
|
- lib/stretcher.rb
|
155
|
+
- lib/stretcher/es_component.rb
|
155
156
|
- lib/stretcher/index.rb
|
156
157
|
- lib/stretcher/index_type.rb
|
157
158
|
- lib/stretcher/request_error.rb
|