fern-parameters 0.0.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 +7 -0
- data/lib/fern/parameters/dsl.rb +28 -0
- data/lib/fern/parameters/errors.rb +22 -0
- data/lib/fern/parameters/invalid.rb +11 -0
- data/lib/fern/parameters/parameters.rb +40 -0
- data/lib/fern/parameters/validator.rb +141 -0
- data/lib/fern/parameters/version.rb +5 -0
- data/lib/fern/parameters.rb +22 -0
- data/lib/fern-parameters.rb +1 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4dff3f8750786b2ca71fff701a73504323362f86
|
4
|
+
data.tar.gz: be2919d7d59d2106ff61abe724902365d46429d2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fdec1c3fd8f503383ce2b39571817198b16cda1a55d7ce2f179355331b750e34441b7218696ba465c6c33bce0751ca28c4c4230e7b0aa1c2a58e2b256a144459
|
7
|
+
data.tar.gz: 201b1b355ba20c24082b98a355db68b2555ea1282b3d088f52bc4a54f59c24349b5be72b0dfd3243d30ca3bf377358fe7fd644584710bd27ad15a343c1fe7d7a
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'fern/api'
|
2
|
+
|
3
|
+
module Fern
|
4
|
+
module Parameters
|
5
|
+
module Dsl
|
6
|
+
def self.included(receiver)
|
7
|
+
receiver.extend(ClassMethods)
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
end
|
12
|
+
|
13
|
+
def params(&block)
|
14
|
+
@controller.fern[@name][:params] = {}
|
15
|
+
instance_eval(&block)
|
16
|
+
end
|
17
|
+
|
18
|
+
def param(name, type = :string, **opts)
|
19
|
+
@controller.fern[@name][:params][name] = {
|
20
|
+
type: type,
|
21
|
+
constraints: opts
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Fern::Api::Endpoint.class_eval { include Fern::Parameters::Dsl }
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Fern
|
2
|
+
module Parameters
|
3
|
+
class Errors
|
4
|
+
def initialize
|
5
|
+
@errors = {}
|
6
|
+
end
|
7
|
+
|
8
|
+
def add(param, message)
|
9
|
+
@errors[param] ||= []
|
10
|
+
@errors[param] << message
|
11
|
+
end
|
12
|
+
|
13
|
+
def any?
|
14
|
+
@errors.any?
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](param)
|
18
|
+
@errors[param]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'active_support/core_ext/module'
|
2
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
3
|
+
|
4
|
+
require 'fern/parameters/invalid'
|
5
|
+
require 'fern/parameters/validator'
|
6
|
+
|
7
|
+
module Fern
|
8
|
+
module Parameters
|
9
|
+
class Parameters
|
10
|
+
delegate :keys,
|
11
|
+
:key?,
|
12
|
+
:has_key?,
|
13
|
+
:values,
|
14
|
+
:has_value?,
|
15
|
+
:value?,
|
16
|
+
:empty?,
|
17
|
+
:include?,
|
18
|
+
:as_json,
|
19
|
+
:[],
|
20
|
+
:to_h,
|
21
|
+
to: :@parameters
|
22
|
+
|
23
|
+
def initialize(parameters, config)
|
24
|
+
@parameters = parameters.with_indifferent_access
|
25
|
+
@config = config.deep_symbolize_keys!
|
26
|
+
end
|
27
|
+
|
28
|
+
def validated
|
29
|
+
validator = Validator.new(@config)
|
30
|
+
validator.validate(@parameters)
|
31
|
+
|
32
|
+
if validator.errors.any?
|
33
|
+
raise Invalid.new(validator.errors), 'invalid parameters'
|
34
|
+
end
|
35
|
+
|
36
|
+
self.class.new(validator.declared, @config)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'active_support/core_ext/module'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
require 'fern/parameters/invalid'
|
5
|
+
require 'fern/parameters/errors'
|
6
|
+
|
7
|
+
module Fern
|
8
|
+
module Parameters
|
9
|
+
class Validator
|
10
|
+
attr_accessor :errors
|
11
|
+
attr_accessor :declared
|
12
|
+
|
13
|
+
def initialize(config)
|
14
|
+
@config = config
|
15
|
+
@errors = Errors.new
|
16
|
+
@declared = {}
|
17
|
+
end
|
18
|
+
|
19
|
+
def validate(params)
|
20
|
+
@config.each do |name, config|
|
21
|
+
if params.key?(name)
|
22
|
+
@declared[name] = validate_constraints(
|
23
|
+
name,
|
24
|
+
params[name],
|
25
|
+
config
|
26
|
+
)
|
27
|
+
else
|
28
|
+
@declared[name] = config[:default] if config.key?(:default)
|
29
|
+
if config[:required] && @declared[name].nil?
|
30
|
+
@errors.add(name, 'is required')
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def validate_constraints(name, raw_val, config)
|
39
|
+
val = validate_type(name, raw_val, config[:type], config)
|
40
|
+
|
41
|
+
return if val.nil?
|
42
|
+
|
43
|
+
validate_numeric_constraints(name, val, config)
|
44
|
+
validate_inclusion(name, val, config)
|
45
|
+
|
46
|
+
val
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse_type(val, type, array = false)
|
50
|
+
meth = "validate_#{type}"
|
51
|
+
if array
|
52
|
+
parsed = val.map { |el| send(meth, el) }
|
53
|
+
return nil unless parsed.all? { |el| !el.nil? } && parsed
|
54
|
+
parsed
|
55
|
+
else
|
56
|
+
send(meth, val)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def validate_boolean(val)
|
61
|
+
if val.casecmp('true').zero?
|
62
|
+
true
|
63
|
+
elsif val.casecmp('false').zero?
|
64
|
+
false
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def validate_date(val)
|
69
|
+
Date.parse(val)
|
70
|
+
rescue ArgumentError
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_datetime(val)
|
74
|
+
Time.parse(val)
|
75
|
+
rescue ArgumentError
|
76
|
+
end
|
77
|
+
|
78
|
+
def validate_float(val)
|
79
|
+
Float(val)
|
80
|
+
rescue ArgumentError
|
81
|
+
end
|
82
|
+
|
83
|
+
def validate_inclusion(name, val, constraints)
|
84
|
+
return unless constraints.key?(:values)
|
85
|
+
return if constraints[:values].include?(val)
|
86
|
+
@errors.add(name, "must be one of #{constraints[:values]}")
|
87
|
+
end
|
88
|
+
|
89
|
+
def validate_integer(val)
|
90
|
+
Integer(val)
|
91
|
+
rescue ArgumentError
|
92
|
+
rescue TypeError
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_max(name, val, max)
|
96
|
+
return unless val > max
|
97
|
+
@errors.add(name, "must be less than or equal to #{max}")
|
98
|
+
end
|
99
|
+
|
100
|
+
def validate_min(name, val, min)
|
101
|
+
return unless val < min
|
102
|
+
@errors.add(name, "must be greater than or equal to #{min}")
|
103
|
+
end
|
104
|
+
|
105
|
+
def validate_numeric(name, val)
|
106
|
+
validate_float(val) || @errors.add(name, 'must be a number')
|
107
|
+
end
|
108
|
+
|
109
|
+
def validate_numeric_constraints(name, val, constraints)
|
110
|
+
return unless constraints.key?(:min) || constraints.key?(:max)
|
111
|
+
validate_numeric(name, val)
|
112
|
+
validate_min(name, val, constraints[:min]) if constraints.key?(:min)
|
113
|
+
validate_max(name, val, constraints[:max]) if constraints.key?(:max)
|
114
|
+
end
|
115
|
+
|
116
|
+
def validate_string(val)
|
117
|
+
val
|
118
|
+
end
|
119
|
+
|
120
|
+
def validate_type(name, val, type, config)
|
121
|
+
parsed = parse_type(val, type, config[:constraints][:array])
|
122
|
+
if parsed.nil?
|
123
|
+
if config[:constraints][:array]
|
124
|
+
@errors.add(name, "is not an array of #{pluralize(type)}")
|
125
|
+
else
|
126
|
+
@errors.add(name, "is not #{indefinite_articlerize(type)}")
|
127
|
+
end
|
128
|
+
end
|
129
|
+
parsed
|
130
|
+
end
|
131
|
+
|
132
|
+
def pluralize(word)
|
133
|
+
ActiveSupport::Inflector.pluralize(word)
|
134
|
+
end
|
135
|
+
|
136
|
+
def indefinite_articlerize(word)
|
137
|
+
%w[a e i o u].include?(word[0].downcase) ? "an #{word}" : "a #{word}"
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'fern/parameters/dsl'
|
2
|
+
require 'fern/parameters/invalid'
|
3
|
+
require 'fern/parameters/parameters'
|
4
|
+
|
5
|
+
module Fern
|
6
|
+
module Parameters
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
def params
|
11
|
+
config = fern[action_name.to_sym][:params]
|
12
|
+
@_params ||= Parameters.new(request.parameters, config)
|
13
|
+
end
|
14
|
+
|
15
|
+
def params=(val)
|
16
|
+
@_params = Parameters.new(val.to_hash)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
ActiveSupport.on_load(:action_controller) { include Fern::Parameters }
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'fern/parameters'
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: fern-parameters
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kyle Kestell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-03-11 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.15'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.15'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: fern-api
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: actionpack
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: activesupport
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '5.0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '5.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: fern-api
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Typed parameters for Fern.
|
112
|
+
email: kyle@kestell.org
|
113
|
+
executables: []
|
114
|
+
extensions: []
|
115
|
+
extra_rdoc_files: []
|
116
|
+
files:
|
117
|
+
- lib/fern-parameters.rb
|
118
|
+
- lib/fern/parameters.rb
|
119
|
+
- lib/fern/parameters/dsl.rb
|
120
|
+
- lib/fern/parameters/errors.rb
|
121
|
+
- lib/fern/parameters/invalid.rb
|
122
|
+
- lib/fern/parameters/parameters.rb
|
123
|
+
- lib/fern/parameters/validator.rb
|
124
|
+
- lib/fern/parameters/version.rb
|
125
|
+
homepage: https://github.com/kkestell/fern-parameters
|
126
|
+
licenses:
|
127
|
+
- MIT
|
128
|
+
metadata: {}
|
129
|
+
post_install_message:
|
130
|
+
rdoc_options: []
|
131
|
+
require_paths:
|
132
|
+
- lib
|
133
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: 2.3.0
|
138
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ">="
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
requirements: []
|
144
|
+
rubyforge_project:
|
145
|
+
rubygems_version: 2.6.14
|
146
|
+
signing_key:
|
147
|
+
specification_version: 4
|
148
|
+
summary: Fern Parameters
|
149
|
+
test_files: []
|