stretchy 0.4.0 → 0.4.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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.ruby-version +1 -0
  4. data/lib/stretchy/boosts/base.rb +2 -3
  5. data/lib/stretchy/boosts/field_decay_boost.rb +23 -19
  6. data/lib/stretchy/boosts/filter_boost.rb +6 -3
  7. data/lib/stretchy/boosts/random_boost.rb +7 -4
  8. data/lib/stretchy/builders/boost_builder.rb +1 -1
  9. data/lib/stretchy/builders/filter_builder.rb +55 -0
  10. data/lib/stretchy/builders/match_builder.rb +41 -43
  11. data/lib/stretchy/builders/query_builder.rb +37 -0
  12. data/lib/stretchy/builders/shell_builder.rb +53 -0
  13. data/lib/stretchy/builders/where_builder.rb +88 -159
  14. data/lib/stretchy/builders.rb +3 -0
  15. data/lib/stretchy/clauses/base.rb +33 -78
  16. data/lib/stretchy/clauses/boost_clause.rb +10 -10
  17. data/lib/stretchy/clauses/boost_match_clause.rb +3 -3
  18. data/lib/stretchy/clauses/boost_where_clause.rb +5 -5
  19. data/lib/stretchy/clauses/match_clause.rb +5 -24
  20. data/lib/stretchy/clauses/where_clause.rb +23 -42
  21. data/lib/stretchy/errors/validation_error.rb +17 -0
  22. data/lib/stretchy/errors.rb +1 -1
  23. data/lib/stretchy/filters/and_filter.rb +5 -1
  24. data/lib/stretchy/filters/base.rb +2 -2
  25. data/lib/stretchy/filters/bool_filter.rb +10 -4
  26. data/lib/stretchy/filters/exists_filter.rb +5 -1
  27. data/lib/stretchy/filters/geo_filter.rb +13 -7
  28. data/lib/stretchy/filters/not_filter.rb +5 -2
  29. data/lib/stretchy/filters/or_filter.rb +4 -1
  30. data/lib/stretchy/filters/query_filter.rb +5 -1
  31. data/lib/stretchy/filters/range_filter.rb +10 -5
  32. data/lib/stretchy/filters/terms_filter.rb +8 -2
  33. data/lib/stretchy/queries/base.rb +2 -2
  34. data/lib/stretchy/queries/bool_query.rb +12 -0
  35. data/lib/stretchy/queries/filtered_query.rb +8 -3
  36. data/lib/stretchy/queries/function_score_query.rb +25 -32
  37. data/lib/stretchy/queries/match_query.rb +10 -3
  38. data/lib/stretchy/results/base.rb +9 -23
  39. data/lib/stretchy/types/base.rb +2 -2
  40. data/lib/stretchy/types/geo_point.rb +15 -6
  41. data/lib/stretchy/types/range.rb +24 -6
  42. data/lib/stretchy/utils/logger.rb +10 -5
  43. data/lib/stretchy/utils/validation.rb +77 -0
  44. data/lib/stretchy/utils.rb +1 -1
  45. data/lib/stretchy/version.rb +1 -1
  46. data/lib/stretchy.rb +3 -0
  47. data/lib/stretchy_validations.rb +10 -0
  48. data/lib/validation/rule/decay.rb +20 -0
  49. data/lib/validation/rule/distance.rb +20 -0
  50. data/lib/validation/rule/field.rb +22 -0
  51. data/lib/validation/rule/inclusion.rb +33 -0
  52. data/lib/validation/rule/latitude.rb +21 -0
  53. data/lib/validation/rule/longitude.rb +22 -0
  54. data/lib/validation/rule/one_of.rb +22 -0
  55. data/lib/validation/rule/required.rb +26 -0
  56. data/lib/validation/rule/responds_to.rb +23 -0
  57. data/lib/validation/rule/type.rb +41 -0
  58. data/stretchy.gemspec +2 -0
  59. metadata +48 -5
  60. data/lib/stretchy/errors/contract_error.rb +0 -5
  61. data/lib/stretchy/utils/contract.rb +0 -120
@@ -1,120 +0,0 @@
1
- module Stretchy
2
- module Utils
3
- module Contract
4
-
5
- ASSERTIONS = [:type, :responds_to, :in, :matches, :required]
6
- DISTANCE_FORMAT = /^(\d+)(km|mi)$/
7
- DECAY_FUNCTIONS = [:gauss, :linear, :exp]
8
-
9
- def self.included(base)
10
- base.send(:extend, ClassMethods)
11
- end
12
-
13
- def validate!
14
- self.class.contracts.each do |name, options|
15
- value = instance_variable_get("@#{name}")
16
- next if value.nil? && !options[:required]
17
-
18
- if options[:array]
19
- self.class.assert_type(name, value, type: Array)
20
- self.class.assert_required(name, value, {}) if options[:required]
21
- end
22
-
23
- ASSERTIONS.each do |assertion|
24
- assertion_method = "assert_#{assertion}"
25
- if options[:array]
26
- value.each {|v| self.class.send(assertion_method, name, v, options) } unless options[assertion].nil?
27
- else
28
- self.class.send(assertion_method, name, value, options) unless options[assertion].nil?
29
- end
30
- end
31
- end
32
- end
33
-
34
- def require_one(options = {})
35
- if options.values.all?{|v| self.class.is_empty?(v) }
36
- raise Stretchy::Errors::ContractError.new("One of #{options.keys.join(', ')} must be present, found: #{options}")
37
- end
38
- end
39
-
40
- module ClassMethods
41
-
42
- attr_reader :contracts
43
-
44
- def is_empty?(value)
45
- value.nil? ||
46
- (value.respond_to?(:any?) && !value.any?) ||
47
- (value.respond_to?(:length) && value.length == 0)
48
- end
49
-
50
- def contract(var, options = {})
51
- @contracts ||= {}
52
- if var.is_a?(Hash)
53
- var.each {|k,v| @contracts[k] = v }
54
- else
55
- @contracts[var] = options
56
- end
57
- end
58
-
59
- def fail_assertion(msg)
60
- raise Stretchy::Errors::ContractError.new(msg)
61
- end
62
-
63
- def assert_required(name, value, options)
64
- msg = "Expected to have param #{name}, but got an #{value.inspect}"
65
- fail_assertion(msg) if is_empty?(value)
66
- end
67
-
68
- def assert_type(name, value, options)
69
- type = options[:type]
70
- case type
71
- when :distance
72
- msg = "Expected #{name} to be a distance measure, but #{value} is not a valid distance"
73
- fail_assertion(msg) unless String(value).match(DISTANCE_FORMAT)
74
- when :lat
75
- msg = "Expected #{name} to be between 90 and -90, but was #{value}"
76
- value = Float(value) rescue nil
77
- fail_assertion(msg) unless value && value <= 90 && value >= -90
78
- when :lng
79
- msg = "Expected #{name} to be between 180 and -180, but was #{value}"
80
- value = Float(value) rescue nil
81
- fail_assertion(msg) unless value && value.to_f <= 180 && value.to_f >= -180
82
- when :field
83
- msg = "Expected #{name} to be a string, symbol, or number, but got #{value.class.name}"
84
- fail_assertion(msg) unless value.is_a?(String) || value.is_a?(Symbol) || value.is_a?(Numeric)
85
-
86
- msg = "Expected #{name} to be a string, symbol, or number, but was blank"
87
- fail_assertion(msg) if value.is_a?(String) && value.empty?
88
- when :decay
89
- msg = "Expected #{name} to be one of #{DECAY_FUNCTIONS.join(', ')}, but got #{value}"
90
- fail_assertion(msg) unless DECAY_FUNCTIONS.any?{|f| f == value || f.to_s == value }
91
- when Array
92
- msg = "Expected #{name} to be one of #{type.map{|t| t.name}}, but got #{value.class.name}"
93
- fail_assertion(msg) unless type.any?{|t| value.is_a?(t)}
94
- else
95
- msg = "Expected #{name} to be of type #{type}, but found #{value.class.name}"
96
- fail_assertion(msg) unless value.is_a?(type)
97
- end
98
- end
99
-
100
- def assert_responds_to(name, value, options)
101
- method = options[:responds_to]
102
- msg = "Expected #{name} to respond_to #{method}, but #{value.class.name} does not"
103
- fail_assertion(msg) unless value.respond_to?(method)
104
- end
105
-
106
- def assert_in(name, value, options)
107
- collection = options[:in]
108
- msg = "Expected #{name} to be one of #{collection}, but got #{value}"
109
- fail_assertion(msg) unless collection.include?(value)
110
- end
111
-
112
- def assert_matches(name, value, options)
113
- matcher = options[:matches]
114
- msg = "Expected #{name} to match #{matcher}, but #{value} does not"
115
- fail_assertion(msg) unless matcher.match(value)
116
- end
117
- end
118
- end
119
- end
120
- end