hario 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hario.rb +25 -2
- data/lib/hario/behaviours/filter.rb +16 -2
- data/lib/hario/behaviours/pluck.rb +7 -1
- data/lib/hario/behaviours/utils.rb +14 -0
- data/lib/hario/version.rb +1 -1
- data/test/filter_test.rb +43 -1
- data/test/fixtures.rb +4 -1
- data/test/models.rb +2 -0
- data/test/pluck_test.rb +20 -1
- data/test/schema.rb +1 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 136e0b28f2d3f6bc51ba637b83c31f48fcdda3ca
|
4
|
+
data.tar.gz: a8b61b6290486260fe75361a503513b98ca689d6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f96e37359a8f64548d93c65c2ca1421cfa99551f236dc5ae465da78bd978e1704ce81a87bf07271e9bdc5cb0ace2d854d3c99f39046bf0a75c554ff14413f6b
|
7
|
+
data.tar.gz: eb7059a076117f97f07e20681af33d67c43d12d028fe28781bb99b9b9aff371a79ebaac29ffec4195e4ce584da75680142f87a842e61203c75f5a67651a3b3ac
|
data/lib/hario.rb
CHANGED
@@ -4,10 +4,16 @@ require "hario/behaviours/pluck"
|
|
4
4
|
|
5
5
|
module Hario
|
6
6
|
module Filterable
|
7
|
-
|
7
|
+
HARIO_APPLY_TYPES = %w( filters pluck ).map(&:to_sym)
|
8
|
+
|
9
|
+
attr_reader :hario_attributes_list
|
10
|
+
|
11
|
+
def search(filters, pluck = [])
|
12
|
+
pluck = pluck.reject{ |p| p.nil? || p.empty? }
|
13
|
+
|
8
14
|
s = all
|
9
15
|
s = s.apply_filters(filters) if filters
|
10
|
-
s = s.apply_pluck(pluck) if pluck
|
16
|
+
s = s.apply_pluck(pluck) if pluck.any?
|
11
17
|
s
|
12
18
|
end
|
13
19
|
|
@@ -32,5 +38,22 @@ module Hario
|
|
32
38
|
def hash_pluck(*keys)
|
33
39
|
pluck(*keys).map{ |vals| Hash[keys.zip(Array(vals))] }
|
34
40
|
end
|
41
|
+
|
42
|
+
def hario_attributes(types, only: nil, except: nil)
|
43
|
+
@hario_attributes_list ||= {}
|
44
|
+
Array.wrap(types).each do |t|
|
45
|
+
raise_if_not_hario_type!(t)
|
46
|
+
@hario_attributes_list[t] =
|
47
|
+
{ only: Array.wrap(only), except: Array.wrap(except) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def raise_if_not_hario_type!(type)
|
53
|
+
unless HARIO_APPLY_TYPES.include?(type)
|
54
|
+
raise ArgumentError, "#{type} is not one of " \
|
55
|
+
"#{HARIO_APPLY_TYPES.map(&:inspect).join(', ')}"
|
56
|
+
end
|
57
|
+
end
|
35
58
|
end
|
36
59
|
end
|
@@ -4,7 +4,8 @@ module Hario
|
|
4
4
|
class FilterParser
|
5
5
|
include ParserUtils
|
6
6
|
|
7
|
-
OPERATORS = { lt: '<', gt: '>', lte: '<=', gte: '>=', like: 'like', equals: '=' }
|
7
|
+
OPERATORS = { lt: '<', gt: '>', lte: '<=', gte: '>=', like: 'like', equals: '=', is: 'is' }
|
8
|
+
IS_VALUES = { null: 'NULL', not_null: 'NOT NULL' }
|
8
9
|
|
9
10
|
attr_accessor :join_clause, :where_clauses
|
10
11
|
|
@@ -15,7 +16,7 @@ module Hario
|
|
15
16
|
parse_filters
|
16
17
|
end
|
17
18
|
|
18
|
-
|
19
|
+
InvalidValueError = Class.new(RuntimeError)
|
19
20
|
|
20
21
|
private
|
21
22
|
def parse_filters
|
@@ -47,12 +48,18 @@ module Hario
|
|
47
48
|
end_model = @klass
|
48
49
|
end
|
49
50
|
|
51
|
+
raise_if_unlisted_attribute!(:filters, end_model, attribute)
|
50
52
|
raise_if_invalid_attribute!(attribute, end_model)
|
51
53
|
|
52
54
|
case operator
|
53
55
|
when :equals
|
54
56
|
condition = { attribute => value }
|
55
57
|
condition = { attribute_table => condition } if attribute_table
|
58
|
+
when :is
|
59
|
+
value = value.to_sym
|
60
|
+
raise_if_invalid_is_value!(value)
|
61
|
+
condition = ["#{attribute} #{operator} #{IS_VALUES[value]}"]
|
62
|
+
condition[0].prepend("#{attribute_table || @klass.table_name}.")
|
56
63
|
else
|
57
64
|
operator = OPERATORS[operator]
|
58
65
|
condition = ["#{attribute} #{operator} ?", value]
|
@@ -62,6 +69,13 @@ module Hario
|
|
62
69
|
condition
|
63
70
|
end
|
64
71
|
|
72
|
+
def raise_if_invalid_is_value!(value)
|
73
|
+
unless IS_VALUES[value]
|
74
|
+
raise InvalidValueError,
|
75
|
+
"When using 'is', value must be one of #{IS_VALUES.keys.join(', ')}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
65
79
|
def raise_if_invalid_attribute!(attribute, end_model)
|
66
80
|
unless end_model.column_names.include?(attribute)
|
67
81
|
raise InvalidAttributeError,
|
@@ -20,11 +20,17 @@ module Hario
|
|
20
20
|
|
21
21
|
ns, no_ns = @pluck.partition{ |p| p.include?('.') }
|
22
22
|
|
23
|
-
no_ns.each
|
23
|
+
no_ns.each do |p|
|
24
|
+
raise_if_unlisted_attribute!(:pluck, @klass, p)
|
25
|
+
@pluck_clause << [@klass.table_name, p].join('.')
|
26
|
+
end
|
24
27
|
|
25
28
|
ns.each do |p|
|
26
29
|
association_chain, attribute = parse_namespace(p)
|
27
30
|
|
31
|
+
end_model = end_model_from_association_chain(association_chain)
|
32
|
+
raise_if_unlisted_attribute!(:pluck, end_model, attribute)
|
33
|
+
|
28
34
|
nested_associations = (association_chain.dup << {}).reverse.inject { |v, key| { key => v } }
|
29
35
|
@join_clause.deep_merge!(nested_associations)
|
30
36
|
|
@@ -1,4 +1,6 @@
|
|
1
1
|
module ParserUtils
|
2
|
+
InvalidAttributeError = Class.new(RuntimeError)
|
3
|
+
|
2
4
|
def table_name_from_association_chain(association_chain)
|
3
5
|
end_model_from_association_chain(association_chain).table_name
|
4
6
|
end
|
@@ -12,4 +14,16 @@ module ParserUtils
|
|
12
14
|
|
13
15
|
head
|
14
16
|
end
|
17
|
+
|
18
|
+
def raise_if_unlisted_attribute!(type, model_class, attribute)
|
19
|
+
return unless model_class.respond_to?(:hario_attributes_list)
|
20
|
+
return unless model_class.hario_attributes_list
|
21
|
+
lists = model_class.hario_attributes_list[type]
|
22
|
+
return unless lists
|
23
|
+
attribute = attribute.to_sym
|
24
|
+
if (lists[:except].present? && lists[:except].include?(attribute)) ||
|
25
|
+
(lists[:only ].present? && !lists[:only ].include?(attribute))
|
26
|
+
raise InvalidAttributeError, "#{attribute} is forbidden"
|
27
|
+
end
|
28
|
+
end
|
15
29
|
end
|
data/lib/hario/version.rb
CHANGED
data/test/filter_test.rb
CHANGED
@@ -38,7 +38,7 @@ class FilterTest < Hario::Test
|
|
38
38
|
filters = { 'created_at.gt' => (DateTime.now - 5).iso8601 }
|
39
39
|
products = Product.search(filters)
|
40
40
|
|
41
|
-
assert_equal
|
41
|
+
assert_equal 3, products.count
|
42
42
|
end
|
43
43
|
|
44
44
|
def test_invalid_attribute_raises
|
@@ -48,4 +48,46 @@ class FilterTest < Hario::Test
|
|
48
48
|
Product.search(filters)
|
49
49
|
end
|
50
50
|
end
|
51
|
+
|
52
|
+
def test_is_null
|
53
|
+
filters = { 'brand_id.is' => "null" }
|
54
|
+
|
55
|
+
products = Product.search(filters)
|
56
|
+
assert_equal 1, products.count
|
57
|
+
assert_equal 'Nil product', products.first.name
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_is_not_null
|
61
|
+
filters = { 'brand_id.is' => "not_null" }
|
62
|
+
|
63
|
+
products = Product.search(filters)
|
64
|
+
assert_equal 3, products.count
|
65
|
+
products.each do |p|
|
66
|
+
refute_equal 'Nil product', p.name
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def test_is_value_must_be_correct
|
71
|
+
filters = { 'brand_id.is' => "meh" }
|
72
|
+
|
73
|
+
assert_raises Hario::FilterParser::InvalidValueError do
|
74
|
+
Product.search(filters)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def test_hidden_column_filter
|
79
|
+
filters = { 'hidden_column.equals' => 5 }
|
80
|
+
|
81
|
+
assert_raises Hario::FilterParser::InvalidAttributeError do
|
82
|
+
Product.search(filters)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_hidden_column_filter_with_join
|
87
|
+
filters = { 'products.hidden_column.equals' => 5 }
|
88
|
+
|
89
|
+
assert_raises Hario::FilterParser::InvalidAttributeError do
|
90
|
+
Brand.search(filters)
|
91
|
+
end
|
92
|
+
end
|
51
93
|
end
|
data/test/fixtures.rb
CHANGED
data/test/models.rb
CHANGED
data/test/pluck_test.rb
CHANGED
@@ -16,4 +16,23 @@ class PluckTest < Hario::Test
|
|
16
16
|
assert_equal ["id", "name", "brands.name"], products.flat_map(&:keys).uniq,
|
17
17
|
"Pluck not returning correct attributes with association pluck"
|
18
18
|
end
|
19
|
-
|
19
|
+
|
20
|
+
def test_hidden_column_pluck
|
21
|
+
assert_raises Hario::PluckParser::InvalidAttributeError do
|
22
|
+
Product.search(nil, %w( hidden_column ))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_hidden_column_pluck_with_join
|
27
|
+
assert_raises Hario::PluckParser::InvalidAttributeError do
|
28
|
+
Brand.search(nil, %w( products.hidden_column ))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_empty_string_ignored
|
33
|
+
Product.search(nil, [""])
|
34
|
+
|
35
|
+
# no exception
|
36
|
+
assert true
|
37
|
+
end
|
38
|
+
end
|
data/test/schema.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hario
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Campbell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-05-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -126,7 +126,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
126
|
version: '0'
|
127
127
|
requirements: []
|
128
128
|
rubyforge_project:
|
129
|
-
rubygems_version: 2.
|
129
|
+
rubygems_version: 2.5.1
|
130
130
|
signing_key:
|
131
131
|
specification_version: 4
|
132
132
|
summary: Hario provides ActiveRecord filtering for Rails APIs.
|