stretchy 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +10 -1
- data/lib/stretchy/boosts/field_decay_boost.rb +1 -1
- data/lib/stretchy/boosts/field_value_boost.rb +2 -2
- data/lib/stretchy/boosts/filter_boost.rb +2 -2
- data/lib/stretchy/builders/match_builder.rb +4 -0
- data/lib/stretchy/builders/query_builder.rb +12 -3
- data/lib/stretchy/builders/shell_builder.rb +5 -0
- data/lib/stretchy/clauses/base.rb +31 -1
- data/lib/stretchy/clauses/boost_clause.rb +1 -2
- data/lib/stretchy/clauses/boost_match_clause.rb +2 -3
- data/lib/stretchy/clauses/match_clause.rb +46 -1
- data/lib/stretchy/filters/base.rb +2 -0
- data/lib/stretchy/filters/exists_filter.rb +1 -1
- data/lib/stretchy/filters/geo_filter.rb +1 -1
- data/lib/stretchy/filters/range_filter.rb +1 -1
- data/lib/stretchy/filters/terms_filter.rb +1 -1
- data/lib/stretchy/queries/filtered_query.rb +2 -2
- data/lib/stretchy/queries/match_query.rb +2 -2
- data/lib/stretchy/queries/more_like_this_query.rb +57 -0
- data/lib/stretchy/queries.rb +1 -0
- data/lib/stretchy/utils/validation.rb +4 -0
- data/lib/stretchy/version.rb +1 -1
- data/lib/stretchy_validations.rb +2 -0
- data/lib/validation/rule/decay.rb +1 -6
- data/lib/validation/rule/distance.rb +1 -6
- data/lib/validation/rule/field.rb +9 -8
- data/lib/validation/rule/inclusion.rb +3 -11
- data/lib/validation/rule/latitude.rb +1 -5
- data/lib/validation/rule/longitude.rb +1 -6
- data/lib/validation/rule/min_should_match.rb +18 -0
- data/lib/validation/rule/required.rb +2 -14
- data/lib/validation/rule/responds_to.rb +1 -10
- data/lib/validation/rule/stretchy_rule.rb +38 -0
- data/lib/validation/rule/type.rb +7 -20
- data/solano.yml +9 -0
- metadata +6 -4
- data/.travis.yml +0 -6
- data/lib/validation/rule/one_of.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0bc5fc45426e803f3fe65879afb93ed01e654e32
|
4
|
+
data.tar.gz: a5edc4764c1e5760b7fcd5458de681085ee2397d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1a9fbf2f0ca614fd6e6049acf79cdc63309395ba97d44cae7c4b9a2c284744c3f523871453e525655cddf81e96909b0ce429712c8cebad5a83d8ae01952864ee
|
7
|
+
data.tar.gz: 6a7404a23251bdbf7b728c9d33c0a72b455a93ac0c16fb014fcbcc328ee918b01a75603ba5b308f7b2df3974c161fbc2efa0499051e5ce747b43ef117ad224bf
|
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# Stretchy
|
2
|
-
[![Build Status](https://travis-ci.org/hired/stretchy.svg?branch=master)](https://travis-ci.org/hired/stretchy)
|
3
2
|
|
4
3
|
Stretchy is a query builder for [Elasticsearch](https://www.elastic.co/products/elasticsearch). It helps you quickly construct the JSON to send to Elastic, which can get [rather complicated](http://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html).
|
5
4
|
|
@@ -81,6 +80,16 @@ query = query.match('welcome to my web site')
|
|
81
80
|
|
82
81
|
Performs a match query for the given string. If given a hash, it will use a match query on the specified fields, otherwise it will default to `'_all'`. By default, a match query searches for any of the analyzed terms in the document, and scores them using Lucene's [practical scoring formula](https://www.elastic.co/guide/en/elasticsearch/guide/current/practical-scoring-function.html), which combines TF/IDF, the vector space model, and a few other niceties.
|
83
82
|
|
83
|
+
### More Like
|
84
|
+
|
85
|
+
```ruby
|
86
|
+
query = query.more_like(ids: [1, 2, 3])
|
87
|
+
.more_like(docs: other_search.results)
|
88
|
+
.more_like(like_text: 'puppies and kittens are great', fields: :about_me)
|
89
|
+
```
|
90
|
+
|
91
|
+
Finds documents similar to a list of input documents. You must pass in one of the `:ids`, `:docs` or `:like_text` parameters, but everything else is optional. This method accepts any of the params available in the [Elasticsearch more_like_this query](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html). It can also be chained with `.not` and `.should`.
|
92
|
+
|
84
93
|
### Where
|
85
94
|
|
86
95
|
```ruby
|
@@ -16,7 +16,7 @@ module Stretchy
|
|
16
16
|
attribute :weight
|
17
17
|
|
18
18
|
validations do
|
19
|
-
rule :field,
|
19
|
+
rule :field, field: { required: true }
|
20
20
|
rule :origin, type: {classes: [Numeric, Time, Date, Stretchy::Types::GeoPoint], required: true}
|
21
21
|
rule :scale, :required
|
22
22
|
rule :decay, :decay
|
@@ -9,9 +9,9 @@ module Stretchy
|
|
9
9
|
attribute :factor
|
10
10
|
|
11
11
|
validations do
|
12
|
-
rule :field, :
|
12
|
+
rule :field, field: { required: true }
|
13
13
|
rule :modifier, inclusion: {in: MODIFIERS}
|
14
|
-
rule :factor,
|
14
|
+
rule :factor, type: {classes: Numeric}
|
15
15
|
end
|
16
16
|
|
17
17
|
def initialize(field, options = {})
|
@@ -9,8 +9,8 @@ module Stretchy
|
|
9
9
|
attribute :weight, Numeric, default: DEFAULT_WEIGHT
|
10
10
|
|
11
11
|
validations do
|
12
|
-
rule :filter, type:
|
13
|
-
rule :weight, type:
|
12
|
+
rule :filter, type: Filters::Base
|
13
|
+
rule :weight, type: Numeric
|
14
14
|
end
|
15
15
|
|
16
16
|
def initialize(options = {})
|
@@ -15,6 +15,10 @@ module Stretchy
|
|
15
15
|
must.any? || must_not.any? || should.any? || should_not.any?
|
16
16
|
end
|
17
17
|
|
18
|
+
def add_query(query, options = {})
|
19
|
+
builder_from_options(options).add_query(query)
|
20
|
+
end
|
21
|
+
|
18
22
|
def add_matches(field, matches, options = {})
|
19
23
|
builder_from_options(options).add_matches(field, matches, options)
|
20
24
|
end
|
@@ -4,15 +4,20 @@ module Stretchy
|
|
4
4
|
|
5
5
|
extend Forwardable
|
6
6
|
|
7
|
-
delegate [:any?, :count, :length] => :
|
7
|
+
delegate [:any?, :count, :length] => :to_enum
|
8
8
|
|
9
|
-
attr_reader :matches, :query_opts
|
9
|
+
attr_reader :queries, :matches, :query_opts
|
10
10
|
|
11
11
|
def initialize
|
12
|
+
@queries = []
|
12
13
|
@matches = Hash.new { [] }
|
13
14
|
@query_opts = Hash.new { {} }
|
14
15
|
end
|
15
16
|
|
17
|
+
def add_query(query)
|
18
|
+
@queries << query
|
19
|
+
end
|
20
|
+
|
16
21
|
def add_matches(field, new_matches, options = {})
|
17
22
|
@matches[field] += Array(new_matches)
|
18
23
|
opts = {}
|
@@ -22,8 +27,12 @@ module Stretchy
|
|
22
27
|
@query_opts[field] = opts
|
23
28
|
end
|
24
29
|
|
30
|
+
def to_enum
|
31
|
+
queries + matches.values
|
32
|
+
end
|
33
|
+
|
25
34
|
def to_queries
|
26
|
-
matches.map do |field, phrases|
|
35
|
+
queries + matches.map do |field, phrases|
|
27
36
|
opts = query_opts[field].merge(
|
28
37
|
field: field,
|
29
38
|
string: phrases.flatten.join(' ')
|
@@ -2,6 +2,8 @@ module Stretchy
|
|
2
2
|
module Builders
|
3
3
|
class ShellBuilder
|
4
4
|
|
5
|
+
extend Forwardable
|
6
|
+
|
5
7
|
DEFAULT_LIMIT = 30
|
6
8
|
DEFAULT_OFFSET = 0
|
7
9
|
|
@@ -9,6 +11,9 @@ module Stretchy
|
|
9
11
|
:match_builder, :where_builder, :boost_builder,
|
10
12
|
:aggregate_builder, :fields
|
11
13
|
|
14
|
+
delegate [:add_matches, :add_query] => :match_builder
|
15
|
+
delegate [:add_param, :add_geo, :add_range] => :where_builder
|
16
|
+
|
12
17
|
def initialize(options = {})
|
13
18
|
@index = options[:index] || Stretchy.index_name
|
14
19
|
@match_builder = Stretchy::Builders::MatchBuilder.new
|
@@ -22,7 +22,7 @@ module Stretchy
|
|
22
22
|
:took, :shards, :total, :max_score, :total_pages] => :query_results
|
23
23
|
delegate [:to_search] => :base
|
24
24
|
delegate [:where, :range, :geo, :terms, :not] => :build_where
|
25
|
-
delegate [:match, :fulltext] => :build_match
|
25
|
+
delegate [:match, :fulltext, :more_like] => :build_match
|
26
26
|
|
27
27
|
#
|
28
28
|
# Generates a chainable query. The only required option for the
|
@@ -49,6 +49,23 @@ module Stretchy
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
|
52
|
+
#
|
53
|
+
# Exits any state the query is in (boost, inverse, should, etc)
|
54
|
+
# and returns to the root query state. You can use this before
|
55
|
+
# calling `.where` or other overridden methods to ensure they
|
56
|
+
# are being processed from the base state.
|
57
|
+
#
|
58
|
+
# If you have to call this method, please file an issue.
|
59
|
+
# End-of-chain methods (such as `.boost.where.not()`) should
|
60
|
+
# always return to the root state, and state is not
|
61
|
+
# something you should have to think about.
|
62
|
+
#
|
63
|
+
# @return [Base] Continue the query chain from the root state
|
64
|
+
#
|
65
|
+
def root
|
66
|
+
Base.new(base)
|
67
|
+
end
|
68
|
+
|
52
69
|
#
|
53
70
|
# Sets how many results to return, similar to
|
54
71
|
# ActiveRecord's limit method.
|
@@ -160,6 +177,19 @@ module Stretchy
|
|
160
177
|
!!base.explain
|
161
178
|
end
|
162
179
|
|
180
|
+
#
|
181
|
+
# Filter for documents that do not match the specified fields and values
|
182
|
+
#
|
183
|
+
# @overload not(params)
|
184
|
+
# @param [String] A string that must not be matched anywhere in the document
|
185
|
+
# @overload not(params)
|
186
|
+
# @param [Hash] A hash of fields and strings or terms that must not be matched in those fields
|
187
|
+
#
|
188
|
+
# @return [MatchClause, WhereClause] inverted query state with match filters applied
|
189
|
+
#
|
190
|
+
# @see {MatchClause#not}
|
191
|
+
# @see {WhereClause#not}
|
192
|
+
#
|
163
193
|
def not(params = {}, options = {})
|
164
194
|
if params.is_a?(String)
|
165
195
|
build_match.not(params, options)
|
@@ -76,10 +76,9 @@ module Stretchy
|
|
76
76
|
def field(*args)
|
77
77
|
options = args.last.is_a?(Hash) ? args.pop : {}
|
78
78
|
args.each do |field|
|
79
|
-
pp
|
80
79
|
base.boost_builder.add_boost(Boosts::FieldValueBoost.new(field, options))
|
81
80
|
end
|
82
|
-
|
81
|
+
Base.new(base)
|
83
82
|
end
|
84
83
|
|
85
84
|
def not(*args)
|
@@ -30,12 +30,10 @@ module Stretchy
|
|
30
30
|
def not(params = {})
|
31
31
|
@inverse = true
|
32
32
|
match_function(hashify_params(params))
|
33
|
-
self
|
34
33
|
end
|
35
34
|
|
36
35
|
def boost_match(params = {}, options = {})
|
37
36
|
match_function(hashify_params(params), options)
|
38
|
-
self
|
39
37
|
end
|
40
38
|
|
41
39
|
def fulltext(params = {}, options = {})
|
@@ -45,7 +43,7 @@ module Stretchy
|
|
45
43
|
clause = MatchClause.new.match(params, options)
|
46
44
|
boost = clause.to_boost(weight)
|
47
45
|
base.boost_builder.add_boost(boost) if boost
|
48
|
-
|
46
|
+
Base.new(base)
|
49
47
|
end
|
50
48
|
|
51
49
|
#
|
@@ -89,6 +87,7 @@ module Stretchy
|
|
89
87
|
clause = MatchClause.new.match(params, options)
|
90
88
|
boost = clause.to_boost(weight)
|
91
89
|
base.boost_builder.add_boost(boost) if boost
|
90
|
+
self
|
92
91
|
end
|
93
92
|
|
94
93
|
end
|
@@ -54,11 +54,56 @@ module Stretchy
|
|
54
54
|
#
|
55
55
|
# @see https://www.elastic.co/guide/en/elasticsearch/guide/current/proximity-relevance.html Elasticsearch guide: proximity for relevance
|
56
56
|
def fulltext(params = {})
|
57
|
-
add_params(params
|
57
|
+
add_params(params)
|
58
58
|
add_params(params, should: true, slop: FULLTEXT_SLOP)
|
59
59
|
self
|
60
60
|
end
|
61
61
|
|
62
|
+
#
|
63
|
+
# Adds a MoreLikeThis query to the chain. Pass in document ids,
|
64
|
+
# an array of index/name/ids, or a string to get documents that
|
65
|
+
# have similar terms.
|
66
|
+
#
|
67
|
+
# This method accepts all the options in the Elasticsearch
|
68
|
+
# `more_like_this` query, which are pretty extensive. See the
|
69
|
+
# documentation (link below) to get an idea of what is available.
|
70
|
+
#
|
71
|
+
# Only one of `:docs`, `:ids`, or `:like_text` is required, and
|
72
|
+
# one of those three must be present.
|
73
|
+
#
|
74
|
+
# @param params = {} [Hash] Params used to build the `more_like_this` query
|
75
|
+
# @option params [Array] :like_text A string to compare documents do
|
76
|
+
# @option params [Array] :ids A list of document ids to compare documents to
|
77
|
+
# @option params [Array] :docs An array of document hashes. You can pass the
|
78
|
+
# results of another query here, or a hash with fields '_index', '_type'
|
79
|
+
# and '_id'
|
80
|
+
# @option params [Array] :fields A list of fields to use in the comparison.
|
81
|
+
# Defaults to '_all'
|
82
|
+
# @option params [Array] :include Whether the source documents should be
|
83
|
+
# included in the result set. Defaults to `false`
|
84
|
+
#
|
85
|
+
# @return [MatchClause] allows continuing the query chain
|
86
|
+
#
|
87
|
+
# @example Getting more like a document by id
|
88
|
+
# query.more_like(ids: other_result_id)
|
89
|
+
#
|
90
|
+
# @example Getting more like a document from another query
|
91
|
+
# query.more_like(docs: other_query.results)
|
92
|
+
#
|
93
|
+
# @example Getting more like a document from a string
|
94
|
+
# query.more_like(like_text: 'puppies and kittens are great')
|
95
|
+
#
|
96
|
+
# @see https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-mlt-query.html Elasticsearch more-like-this query documentation
|
97
|
+
#
|
98
|
+
def more_like(params = {}, options = {})
|
99
|
+
query = Queries::MoreLikeThisQuery.new(params)
|
100
|
+
options[:inverse] = true if inverse?
|
101
|
+
options[:should] = true if should?
|
102
|
+
|
103
|
+
base.add_query(query, options)
|
104
|
+
self
|
105
|
+
end
|
106
|
+
|
62
107
|
#
|
63
108
|
# Switches to inverted context. Matches applied here work the same way as
|
64
109
|
# {#initialize}, but returned documents must **not** match these filters.
|
@@ -22,8 +22,8 @@ module Stretchy
|
|
22
22
|
|
23
23
|
def to_search
|
24
24
|
json = {}
|
25
|
-
json[:query] = @query.to_search if
|
26
|
-
json[:filter] = @filter.to_search if
|
25
|
+
json[:query] = @query.to_search if query
|
26
|
+
json[:filter] = @filter.to_search if filter
|
27
27
|
{ filtered: json }
|
28
28
|
end
|
29
29
|
end
|
@@ -16,13 +16,13 @@ module Stretchy
|
|
16
16
|
attribute :max, Float
|
17
17
|
|
18
18
|
validations do
|
19
|
-
rule :field,
|
19
|
+
rule :field, field: { required: true }
|
20
20
|
rule :string, type: String
|
21
21
|
rule :string, :required
|
22
22
|
rule :operator, inclusion: {in: OPERATORS}
|
23
23
|
rule :type, inclusion: {in: MATCH_TYPES}
|
24
24
|
rule :slop, type: Numeric
|
25
|
-
rule :min,
|
25
|
+
rule :min, :min_should_match
|
26
26
|
rule :max, type: Numeric
|
27
27
|
end
|
28
28
|
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Stretchy
|
2
|
+
module Queries
|
3
|
+
class MoreLikeThisQuery < Base
|
4
|
+
|
5
|
+
attribute :fields, Array[String]
|
6
|
+
attribute :like_text, String
|
7
|
+
attribute :ids, Array[Integer]
|
8
|
+
attribute :docs, Array
|
9
|
+
attribute :max_query_terms, Integer
|
10
|
+
attribute :min_term_freq, Integer
|
11
|
+
attribute :min_doc_freq, Integer
|
12
|
+
attribute :max_doc_freq, Integer
|
13
|
+
attribute :min_word_length, Integer
|
14
|
+
attribute :max_word_length, Integer
|
15
|
+
attribute :stop_words, Array[String]
|
16
|
+
attribute :analyzer, String
|
17
|
+
attribute :boost_terms, Integer
|
18
|
+
attribute :include, Axiom::Types::Boolean
|
19
|
+
attribute :boost, Float
|
20
|
+
|
21
|
+
validations do
|
22
|
+
rule :fields, field: { array: true }
|
23
|
+
end
|
24
|
+
|
25
|
+
def after_initialize(params = {})
|
26
|
+
if params[:docs]
|
27
|
+
@docs = coerce_docs(Array(params[:docs]))
|
28
|
+
end
|
29
|
+
|
30
|
+
require_one!(:like_text, :docs, :ids)
|
31
|
+
end
|
32
|
+
|
33
|
+
def coerce_docs(docs)
|
34
|
+
docs.map do |doc|
|
35
|
+
coerced = {
|
36
|
+
'_index' => doc['_index'] || doc[:_index],
|
37
|
+
'_type' => doc['_type'] || doc[:_type],
|
38
|
+
}
|
39
|
+
|
40
|
+
source = doc[:doc] || doc['']
|
41
|
+
if source
|
42
|
+
coerced['doc'] = source
|
43
|
+
else
|
44
|
+
coerced['_id'] = doc['_id'] || doc[:_id]
|
45
|
+
end
|
46
|
+
coerced
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_search
|
51
|
+
{
|
52
|
+
more_like_this: json_attributes
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/stretchy/queries.rb
CHANGED
data/lib/stretchy/version.rb
CHANGED
data/lib/stretchy_validations.rb
CHANGED
@@ -3,6 +3,8 @@ require 'validation/rule/not_empty'
|
|
3
3
|
require 'validation/rule/regular_expression'
|
4
4
|
|
5
5
|
# custom for Stretchy
|
6
|
+
require 'validation/rule/stretchy_rule'
|
7
|
+
require 'validation/rule/min_should_match'
|
6
8
|
require 'validation/rule/required'
|
7
9
|
require 'validation/rule/responds_to'
|
8
10
|
require 'validation/rule/decay'
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Decay
|
3
|
+
class Decay < StretchyRule
|
4
4
|
DECAY_FUNCTIONS = [:gauss, :linear, :exp]
|
5
5
|
|
6
6
|
def error_key
|
@@ -10,11 +10,6 @@ module Validation
|
|
10
10
|
def valid_value?(value)
|
11
11
|
DECAY_FUNCTIONS.any?{|f| f == value || f.to_s == value }
|
12
12
|
end
|
13
|
-
|
14
|
-
def params
|
15
|
-
{}
|
16
|
-
end
|
17
|
-
|
18
13
|
end
|
19
14
|
end
|
20
15
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Distance
|
3
|
+
class Distance < StretchyRule
|
4
4
|
DISTANCE_FORMAT = /^(\d+)(km|mi)$/
|
5
5
|
|
6
6
|
def error_key
|
@@ -10,11 +10,6 @@ module Validation
|
|
10
10
|
def valid_value?(value)
|
11
11
|
!!(value.to_s =~ DISTANCE_FORMAT)
|
12
12
|
end
|
13
|
-
|
14
|
-
def params
|
15
|
-
{}
|
16
|
-
end
|
17
|
-
|
18
13
|
end
|
19
14
|
end
|
20
15
|
end
|
@@ -1,22 +1,23 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Field
|
3
|
+
class Field < StretchyRule
|
4
4
|
|
5
5
|
def error_key
|
6
6
|
:field
|
7
7
|
end
|
8
8
|
|
9
9
|
def valid_value?(value)
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
return true if empty_ok?(value)
|
11
|
+
if params[:array]
|
12
|
+
value.all? {|v| valid_class?(v) && !is_empty?(v) }
|
13
|
+
else
|
14
|
+
valid_class?(value) && !is_empty?(value)
|
15
|
+
end
|
14
16
|
end
|
15
17
|
|
16
|
-
def
|
17
|
-
{}
|
18
|
+
def valid_class?(value)
|
19
|
+
[String, Symbol, Numeric].any?{|c| value.is_a?(c) }
|
18
20
|
end
|
19
|
-
|
20
21
|
end
|
21
22
|
end
|
22
23
|
end
|
@@ -1,17 +1,13 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Inclusion
|
4
|
-
|
5
|
-
def initialize(params = {})
|
6
|
-
@params = params
|
7
|
-
end
|
3
|
+
class Inclusion < StretchyRule
|
8
4
|
|
9
5
|
def error_key
|
10
6
|
:inclusion
|
11
7
|
end
|
12
8
|
|
13
9
|
def valid_value?(value)
|
14
|
-
return true if value
|
10
|
+
return true if empty_ok?(value)
|
15
11
|
within.any? do |allowed_value|
|
16
12
|
if value.respond_to?(:eql?)
|
17
13
|
value.eql?(allowed_value)
|
@@ -22,11 +18,7 @@ module Validation
|
|
22
18
|
end
|
23
19
|
|
24
20
|
def within
|
25
|
-
|
26
|
-
end
|
27
|
-
|
28
|
-
def params
|
29
|
-
@params
|
21
|
+
params[:in] || params[:within]
|
30
22
|
end
|
31
23
|
end
|
32
24
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Latitude
|
3
|
+
class Latitude < StretchyRule
|
4
4
|
|
5
5
|
def error_key
|
6
6
|
:latitude
|
@@ -12,10 +12,6 @@ module Validation
|
|
12
12
|
valid = false unless value && value.to_f <= 90 && value.to_f >= -90
|
13
13
|
valid
|
14
14
|
end
|
15
|
-
|
16
|
-
def params
|
17
|
-
{}
|
18
|
-
end
|
19
15
|
end
|
20
16
|
end
|
21
17
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Longitude
|
3
|
+
class Longitude < StretchyRule
|
4
4
|
|
5
5
|
def error_key
|
6
6
|
:longitude
|
@@ -12,11 +12,6 @@ module Validation
|
|
12
12
|
valid = false unless value && value <= 180 && value >= -180
|
13
13
|
valid
|
14
14
|
end
|
15
|
-
|
16
|
-
def params
|
17
|
-
{}
|
18
|
-
end
|
19
|
-
|
20
15
|
end
|
21
16
|
end
|
22
17
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Validation
|
2
|
+
module Rule
|
3
|
+
class MinShouldMatch < StretchyRule
|
4
|
+
|
5
|
+
FORMAT_REGEX = /^-?\d+([<>]-?\d+)?%?$/
|
6
|
+
|
7
|
+
def error_key
|
8
|
+
:field
|
9
|
+
end
|
10
|
+
|
11
|
+
def valid_value?(value)
|
12
|
+
return true if empty_ok?(value)
|
13
|
+
value.to_s =~ FORMAT_REGEX
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -1,26 +1,14 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Required
|
3
|
+
class Required < StretchyRule
|
4
4
|
|
5
5
|
def error_key
|
6
6
|
:required
|
7
7
|
end
|
8
8
|
|
9
9
|
def valid_value?(value)
|
10
|
-
|
11
|
-
when nil
|
12
|
-
false
|
13
|
-
when String, Array, Hash
|
14
|
-
!value.empty?
|
15
|
-
else
|
16
|
-
true
|
17
|
-
end
|
10
|
+
!is_empty?(value)
|
18
11
|
end
|
19
|
-
|
20
|
-
def params
|
21
|
-
{}
|
22
|
-
end
|
23
|
-
|
24
12
|
end
|
25
13
|
end
|
26
14
|
end
|
@@ -1,10 +1,6 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class RespondsTo
|
4
|
-
|
5
|
-
def initialize(params)
|
6
|
-
@params = params
|
7
|
-
end
|
3
|
+
class RespondsTo < StretchyRule
|
8
4
|
|
9
5
|
def error_key
|
10
6
|
:responds_to
|
@@ -13,11 +9,6 @@ module Validation
|
|
13
9
|
def valid_value?(value)
|
14
10
|
value.respond_to?(params[:method])
|
15
11
|
end
|
16
|
-
|
17
|
-
def params
|
18
|
-
@params
|
19
|
-
end
|
20
|
-
|
21
12
|
end
|
22
13
|
end
|
23
14
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Validation
|
2
|
+
module Rule
|
3
|
+
class StretchyRule
|
4
|
+
|
5
|
+
def initialize(params = {})
|
6
|
+
@params = params
|
7
|
+
end
|
8
|
+
|
9
|
+
def error_key
|
10
|
+
raise "Override in subclass"
|
11
|
+
end
|
12
|
+
|
13
|
+
def valid_value?(value)
|
14
|
+
raise "Override in subclass"
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty_ok?(value)
|
18
|
+
!required? && is_empty?(value)
|
19
|
+
end
|
20
|
+
|
21
|
+
def invalid_empty?(value)
|
22
|
+
required? && is_empty?(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def is_empty?(value)
|
26
|
+
value.nil? || (value.respond_to?(:empty?) && value.empty?)
|
27
|
+
end
|
28
|
+
|
29
|
+
def required?
|
30
|
+
!!(params.is_a?(Hash) && params[:required])
|
31
|
+
end
|
32
|
+
|
33
|
+
def params
|
34
|
+
@params
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/validation/rule/type.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
module Validation
|
2
2
|
module Rule
|
3
|
-
class Type
|
3
|
+
class Type < StretchyRule
|
4
4
|
|
5
5
|
def initialize(params = {})
|
6
6
|
if params.is_a?(Hash)
|
7
7
|
@params = params
|
8
|
+
@params[:classes] = Array(params[:classes])
|
8
9
|
else
|
9
|
-
@params = { classes: params }
|
10
|
+
@params = { classes: Array(params) }
|
10
11
|
end
|
11
12
|
end
|
12
13
|
|
@@ -16,29 +17,15 @@ module Validation
|
|
16
17
|
|
17
18
|
def valid_value?(value)
|
18
19
|
return true if value.nil? && !params[:required]
|
19
|
-
|
20
|
-
valid = true
|
21
20
|
if params[:array]
|
22
|
-
|
21
|
+
value.all? {|v| valid_type?(v) }
|
23
22
|
else
|
24
|
-
|
23
|
+
valid_type?(value)
|
25
24
|
end
|
26
|
-
valid
|
27
25
|
end
|
28
26
|
|
29
|
-
def
|
30
|
-
|
31
|
-
case params[:classes]
|
32
|
-
when Array
|
33
|
-
valid = false unless params[:classes].any? {|type| value.is_a?(type) }
|
34
|
-
else
|
35
|
-
valid = false unless value.is_a?(params[:classes])
|
36
|
-
end
|
37
|
-
valid
|
38
|
-
end
|
39
|
-
|
40
|
-
def params
|
41
|
-
@params
|
27
|
+
def valid_type?(value)
|
28
|
+
params[:classes].any? {|type| value.is_a?(type) }
|
42
29
|
end
|
43
30
|
end
|
44
31
|
end
|
data/solano.yml
ADDED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: stretchy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- agius
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: elasticsearch
|
@@ -173,7 +173,6 @@ extra_rdoc_files: []
|
|
173
173
|
files:
|
174
174
|
- ".gitignore"
|
175
175
|
- ".ruby-version"
|
176
|
-
- ".travis.yml"
|
177
176
|
- ".yardopts"
|
178
177
|
- Gemfile
|
179
178
|
- README.md
|
@@ -222,6 +221,7 @@ files:
|
|
222
221
|
- lib/stretchy/queries/function_score_query.rb
|
223
222
|
- lib/stretchy/queries/match_all_query.rb
|
224
223
|
- lib/stretchy/queries/match_query.rb
|
224
|
+
- lib/stretchy/queries/more_like_this_query.rb
|
225
225
|
- lib/stretchy/results.rb
|
226
226
|
- lib/stretchy/results/base.rb
|
227
227
|
- lib/stretchy/results/null_results.rb
|
@@ -244,10 +244,12 @@ files:
|
|
244
244
|
- lib/validation/rule/inclusion.rb
|
245
245
|
- lib/validation/rule/latitude.rb
|
246
246
|
- lib/validation/rule/longitude.rb
|
247
|
-
- lib/validation/rule/
|
247
|
+
- lib/validation/rule/min_should_match.rb
|
248
248
|
- lib/validation/rule/required.rb
|
249
249
|
- lib/validation/rule/responds_to.rb
|
250
|
+
- lib/validation/rule/stretchy_rule.rb
|
250
251
|
- lib/validation/rule/type.rb
|
252
|
+
- solano.yml
|
251
253
|
- stretchy.gemspec
|
252
254
|
homepage: https://github.com/hired/stretchy
|
253
255
|
licenses:
|
data/.travis.yml
DELETED