hario 0.3.0 → 0.3.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.
- 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.
|