typed-parameter 0.2.0 → 0.6.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d5a39f98f145cc8ca6739aaa4bf0a729264be875ed09ba6308f7f3064870245c
4
- data.tar.gz: 9ada066d064730b375493ead65ba4c594eecd690f2dca4be89bbb12232bcb3fd
3
+ metadata.gz: 8deba22f3280f1a4c5f01b83121402cd83822afb8602504a319faeb20ec10d8d
4
+ data.tar.gz: 9723defcab7d274fd354d00d8d60f0a1c04bd4e3de0750ee932fe4b6237c7456
5
5
  SHA512:
6
- metadata.gz: 4b3165b35201ee612aca228d6ea55ac271bae117333cec8a6b5028b4c5bbc7021964618e6f94b4724b63893afc594906e9d8f135ae0feb5e99edadd61a2e4947
7
- data.tar.gz: 815563901ab5685a3122caf11a280070d63da903cac667784e826721df94c58dabae3f3e115723819082f67ecb67923fd67a57501911060c4a710658aea81e31
6
+ metadata.gz: d8fbe3cfcdfcd1b3c5b30ee074cd958a9a38c3c2fb0b94545e9badd7f1757e7fce0378d6adec90058a70257b218f3b9c3ebc4bcd873900a18e7012837cafbb2c
7
+ data.tar.gz: 0acdee06d0c4458b0f229b8898a72d9ae624328954715de6a2702d281b425f9be88a0d129a7b5616a963e71d7214d5a6a34c241aba9e3d0244e841eda50e9355
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # TypedParameter
1
+ # typed_parameter
2
2
  Create typed parameter class using strong paramter in rails.
3
3
  You can cleanup parameter code for permit in your controller and convert it to the type you want.
4
4
  ## Installation
@@ -145,7 +145,7 @@ example_params = {
145
145
  }
146
146
 
147
147
  def parent_and_childs_params
148
- ParentParams.permit(example_params)
148
+ ParentParameter.permit(example_params)
149
149
  end
150
150
 
151
151
  # Result
@@ -163,10 +163,103 @@ end
163
163
  ~~~
164
164
  Example 4. CustomType
165
165
  ------
166
- ...
166
+ If You want to use your custom type like Email, just create two file.
167
+ - your type file. like "Email"
168
+ - yout type constant. like "EmailConstrant"
169
+
170
+ ~~~ruby
171
+ class Email
172
+ def initialize(value)
173
+ @email = value
174
+ end
175
+ end
167
176
 
168
- Example 5. Swaggerize
177
+ class EmailConstrant
178
+ class << self
179
+ EMAIL_REGREX = //
180
+
181
+ # using convert value to your type
182
+ def value(value)
183
+ raise ArgumentError unless EMAIL_REGREX.match? value
184
+
185
+ Email.new(value)
186
+ end
187
+ end
188
+ end
189
+
190
+ class EmailSwaggerType
191
+ class << self
192
+ def value
193
+ { type: :string }
194
+ end
195
+ end
196
+ end
197
+
198
+ # Register your type to typed-parameter when application initialize.
199
+ TypedParameter::ParameterTypes.register Email
200
+ TypedParameter::Constants.register :Email, EmailConstrant
201
+ TypedParameter::Swagger::Types.register :Email, EmailSwaggerType
202
+ ~~~
203
+
204
+ Example 5. Use Inline Block
169
205
  ------
206
+ You can use parameter class by block
207
+
208
+ ~~~ruby
209
+ class BlockParameter < TypedParameter::Base
210
+ field :some_object, Object do |i|
211
+ i.field :name, String
212
+ i.field :type, String
213
+ end
214
+
215
+ field :other_hash_list, [Hash] do |i|
216
+ i.field :index, Integer
217
+ i.field :value, Float
218
+ end
219
+ end
220
+ ~~~
221
+
222
+ Example 6. Swaggerize
223
+ ------
224
+ With Rswag(https://github.com/rswag/rswag), you can swaggerize your parameter types.
225
+
226
+ ~~~ruby
227
+ class SwaggerParameter < TypedParameter::Base
228
+ field :string, String, enum: ["one", "two"], description: "String Field"
229
+ field :integer, Integer, description: "Integer Field"
230
+ field :ref_field, SwaggerRefParameter
231
+ end
232
+
233
+ class SwaggerRefParameter < TypedParameter::Base
234
+ field :string, String, description: "Ref String Field"
235
+ end
236
+
237
+ SwaggerParameter.swagger_properties
238
+ # =>
239
+ # {
240
+ # string: { type: :string, enum: ["one", "two" ], description: "String Field" },
241
+ # integer: { type: :integer, description: "Integer Field" },
242
+ # ref_field: { "$ref": "#/components/schemas/SwaggerRefParamter" }
243
+ # }
244
+ #
245
+
246
+ # Add Components in your swagger
247
+ # in swagger_helper
248
+ components = TypedParameter::Swagger::ComponentGenerator.generate_all!
249
+
250
+ config.swagger_docs = {
251
+ 'v1/swagger.yaml' => {
252
+ openapi: '3.0.1',
253
+ # ...,
254
+ components: {
255
+ schemas: {
256
+ **components
257
+ }
258
+ }
259
+ #...
260
+ }
261
+ }
262
+ ~~~
170
263
  ...
171
264
 
172
265
 
@@ -2,25 +2,46 @@ module TypedParameter
2
2
  class Base
3
3
  class << self
4
4
  def field(name, type, **kargs)
5
- initialize_permitted_fields(name, type)
6
- initialize_swagger_properties(name, type, kargs)
7
- initialize_constraints(name, type, kargs)
8
- end
5
+ if block_given?
6
+ raise Error::InvalidBlockParameter unless [type].flatten[0].in?([Hash, Object])
7
+
8
+ block_param_name = "#{self.to_s}_Partial_#{name.to_s.camelize}"
9
+ class_eval("class ::#{block_param_name} < ::TypedParameter::Base; end")
10
+ block_param = block_param_name.constantize
11
+ yield(block_param)
12
+
13
+ if type.is_a?(Array)
14
+ target = [block_param]
15
+ else
16
+ target = block_param
17
+ end
18
+ else
19
+ target = type
20
+ end
9
21
 
10
- def permit(params)
11
- raise ArgumentError unless params.class <= ActionController::Parameters
12
22
 
13
- use_constraints params.permit(fields)
23
+ initialize_constraints(name, target, kargs)
24
+ initialize_swagger_properties(name, target, kargs)
14
25
  end
15
26
 
16
- def fields
17
- __fields.freeze
27
+ def permit(params)
28
+ raise Error::ParameterError unless params.class <= ActionController::Parameters
29
+
30
+ use_constraints(params).permit!
18
31
  end
19
32
 
20
33
  def swagger_properties
21
34
  __swagger_properties.freeze
22
35
  end
23
36
 
37
+ def swagger_requirements
38
+ __swagger_requirements.freeze
39
+ end
40
+
41
+ def constraints
42
+ __constraints.freeze
43
+ end
44
+
24
45
  alias key name
25
46
 
26
47
  def ref
@@ -31,41 +52,45 @@ module TypedParameter
31
52
 
32
53
  def initialize_swagger_properties(name, type, kargs)
33
54
  swagger_type = TypedParameter::Swagger::TypeGenerator.generate(type)
34
- swagger_options = swagger_type.merge(kargs)
55
+ swagger_options = swagger_type.merge(kargs.slice(:enum, :description))
35
56
  __swagger_properties[name] = swagger_options
36
- end
37
-
38
- def initialize_permitted_fields(name, type)
39
- __fields << PermitFieldGenerator.generate(name, type)
57
+ __swagger_requirements << name if kargs[:required]
40
58
  end
41
59
 
42
60
  def initialize_constraints(name, type, kargs)
43
61
  options = kargs.slice(:enum, :required)
44
-
62
+ options[:enum] = options[:enum].map(&:to_s) if options[:enum]
45
63
  __constraints << [name, type, options]
46
64
  end
47
65
 
48
66
  def use_constraints(params)
67
+ typed_params = ActionController::Parameters.new
68
+
49
69
  __constraints.each do |name, type, options|
50
70
  value = params[name]
51
- raise ArgumentError, "(#{self.name}) #{name} is required" if options[:required] && !value.present?
71
+ raise Error::RequiredFieldError, "(#{self.name}) #{name} is required" if options[:required] && empty_value?(value)
72
+
52
73
  next unless value.present?
53
74
 
54
- params[name] = TypeConstraint.value(type, value)
55
- params[name] = EnumConstraint.value(value, options[:enum]) if options[:enum]
75
+ typed_params[name] = TypeConstraint.value(type, value)
76
+ typed_params[name] = EnumConstraint.value(value, options[:enum]) if options[:enum]
56
77
  end
57
78
 
58
- params
79
+ typed_params
59
80
  end
60
81
 
61
- def __fields
62
- @__fields ||= []
82
+ def empty_value?(value)
83
+ value.nil? || value == '' || (value.is_a?(Array) && value.empty?)
63
84
  end
64
85
 
65
86
  def __constraints
66
87
  @__constraints ||= []
67
88
  end
68
89
 
90
+ def __swagger_requirements
91
+ @__swagger_requirements ||= []
92
+ end
93
+
69
94
  def __swagger_properties
70
95
  @__swagger_properties ||= {}
71
96
  end
@@ -4,16 +4,12 @@ class Boolean; end
4
4
 
5
5
  class TrueClass
6
6
  def is_a?(type)
7
- return true if type == Boolean
8
-
9
- super(type)
7
+ type == Boolean || super(type)
10
8
  end
11
9
  end
12
10
 
13
11
  class FalseClass
14
12
  def is_a?(type)
15
- return true if type == Boolean
16
-
17
- super(type)
13
+ type == Boolean || super(type)
18
14
  end
19
15
  end
@@ -4,7 +4,7 @@ module TypedParameter
4
4
  module Constraints
5
5
  class DateConstraint < Base
6
6
  def self.value(value)
7
- value.to_date
7
+ value.to_time.to_date
8
8
  end
9
9
  end
10
10
  end
@@ -4,7 +4,7 @@ module TypedParameter
4
4
  module Constraints
5
5
  class DateTimeConstraint < Base
6
6
  def self.value(value)
7
- value.to_datetime
7
+ value.to_time.to_datetime
8
8
  end
9
9
  end
10
10
  end
@@ -3,5 +3,27 @@ require 'typed_parameter/constraints/integer_constraint'
3
3
  require 'typed_parameter/constraints/float_constraint'
4
4
  require 'typed_parameter/constraints/string_constraint'
5
5
  require 'typed_parameter/constraints/date_constraint'
6
- require 'typed_parameter/constraints/datetime_constraint'
6
+ require 'typed_parameter/constraints/date_time_constraint'
7
7
  require 'typed_parameter/constraints/boolean_constraint'
8
+
9
+ module TypedParameter
10
+ module Constraints
11
+ class << self
12
+ def register(key, constraint)
13
+ @constraints ||= {}
14
+ @constraints[key] = constraint
15
+ end
16
+
17
+ def [](name)
18
+ @constraints[name].freeze
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ TypedParameter::Constraints.register :Integer, TypedParameter::Constraints::IntegerConstraint
25
+ TypedParameter::Constraints.register :String, TypedParameter::Constraints::StringConstraint
26
+ TypedParameter::Constraints.register :Float, TypedParameter::Constraints::FloatConstraint
27
+ TypedParameter::Constraints.register :Date, TypedParameter::Constraints::DateConstraint
28
+ TypedParameter::Constraints.register :DateTime, TypedParameter::Constraints::DateTimeConstraint
29
+ TypedParameter::Constraints.register :Boolean, TypedParameter::Constraints::BooleanConstraint
@@ -1,10 +1,20 @@
1
1
  module TypedParameter
2
2
  module EnumConstraint
3
3
  def self.value(value, enums)
4
- enums = enums.map(&:to_s) if value.is_a? String
5
- raise ArgumentError, "#{value} must be in #{enums.join(', ')}" unless value.in? enums
4
+ return array_value(value, enums) if value.is_a? Array
5
+ return value if value.to_s.in? enums
6
6
 
7
- value
7
+ raise EnumFieldError, "#{value} must be in #{enums.join(', ')}"
8
+ end
9
+
10
+ def self.array_value(values, enums)
11
+ values.each do |value|
12
+ next if value.to_s.in? enums
13
+
14
+ raise EnumFieldError, "#{value} must be in #{enums.join(', ')}"
15
+ end
16
+
17
+ values
8
18
  end
9
19
  end
10
20
  end
@@ -0,0 +1,9 @@
1
+ module TypedParameter
2
+ class Error < StandardError; end
3
+
4
+ class RequiredFieldError < Error; end
5
+
6
+ class EnumFieldError < Error; end
7
+
8
+ class InvalidBlockParameter < Error; end
9
+ end
@@ -1,20 +1,20 @@
1
1
  module TypedParameter
2
2
  module PermitFieldGenerator
3
3
  class << self
4
- BASE_TYPES = TypedParameter::ParameterTypes.types
5
-
6
4
  def generate(name, type)
7
- props = generate_properties(type)
5
+ type_class = [type].flatten.first
8
6
 
9
- props = [] if type.is_a?(Array) && type[0].in?(BASE_TYPES)
10
- return name unless props
7
+ props = if type.is_a? Array
8
+ type_class.in?(TypedParameter::ParameterTypes.types) ? [] : generate_properties(type_class)
9
+ else
10
+ generate_properties(type_class)
11
+ end
11
12
 
12
- [[name, props]].to_h
13
+ props ? [[name, props]].to_h : name
13
14
  end
14
15
 
15
16
  def generate_properties(type)
16
- return if type.in? BASE_TYPES
17
- return generate_properties(type[0]) if type.is_a? Array
17
+ return if type.in? TypedParameter::ParameterTypes.types
18
18
  return type.keys if type.is_a? Hash
19
19
 
20
20
  type.fields
@@ -6,7 +6,15 @@ module TypedParameter
6
6
  key = parameter_class.key
7
7
  properties = Swagger::PropertyGenerator.generate(parameter_class.swagger_properties)
8
8
 
9
- { "#{key}": { type: :object, properties: properties } }
9
+ swagger = { type: :object, properties: properties }
10
+ swagger[:required] = parameter_class.swagger_requirements if parameter_class.swagger_requirements.present?
11
+ { "#{key}": swagger }
12
+ end
13
+
14
+ def generate_all!
15
+ parameter_classes = TypedParameter::Base.descendants.reject { |c| c.swagger_properties.empty? }
16
+
17
+ parameter_classes.reduce({}) { |prev, curr| prev.merge(generate(curr)) }
10
18
  end
11
19
  end
12
20
  end
@@ -5,9 +5,9 @@ module TypedParameter
5
5
  def generate(type)
6
6
  return array_generate(type) if type.is_a? Array
7
7
  return hash_generate(type) if type.is_a? Hash
8
+ return { ref: type } if type < TypedParameter::Base
8
9
 
9
- swagger_type = "TypedParameter::Swagger::Types::#{type.name}Type".safe_constantize
10
- swagger_type&.value || { ref: type }
10
+ Swagger::Types[type.name.to_sym]&.value
11
11
  end
12
12
 
13
13
  def hash_generate(hash)
@@ -17,7 +17,7 @@ module TypedParameter
17
17
  end
18
18
 
19
19
  def array_generate(type)
20
- { type: :array, items: generate(type[0]) }
20
+ { type: :array, items: generate(type[0]) }
21
21
  end
22
22
  end
23
23
  end
@@ -3,5 +3,29 @@ require 'typed_parameter/swagger/types/integer_type'
3
3
  require 'typed_parameter/swagger/types/float_type'
4
4
  require 'typed_parameter/swagger/types/string_type'
5
5
  require 'typed_parameter/swagger/types/date_type'
6
- require 'typed_parameter/swagger/types/datetime_type'
6
+ require 'typed_parameter/swagger/types/date_time_type'
7
7
  require 'typed_parameter/swagger/types/boolean_type'
8
+
9
+ module TypedParameter
10
+ module Swagger
11
+ module Types
12
+ class << self
13
+ def register(key, type)
14
+ @swagger_types ||= {}
15
+ @swagger_types[key] = type
16
+ end
17
+
18
+ def [](key)
19
+ @swagger_types[key].freeze
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ TypedParameter::Swagger::Types.register :Integer, TypedParameter::Swagger::Types::IntegerType
27
+ TypedParameter::Swagger::Types.register :String, TypedParameter::Swagger::Types::StringType
28
+ TypedParameter::Swagger::Types.register :Float, TypedParameter::Swagger::Types::FloatType
29
+ TypedParameter::Swagger::Types.register :Date, TypedParameter::Swagger::Types::DateType
30
+ TypedParameter::Swagger::Types.register :DateTime, TypedParameter::Swagger::Types::DateTimeType
31
+ TypedParameter::Swagger::Types.register :Boolean, TypedParameter::Swagger::Types::BooleanType
@@ -3,19 +3,19 @@ module TypedParameter
3
3
  class << self
4
4
  def value(type, value)
5
5
  type_class = [type].flatten.first
6
- array_type = type.is_a?(Array)
7
- parameter_type = type_class < TypedParameter::Base
8
6
 
9
- if parameter_type
10
- array_type ? parameter_array(type_class, value) : type.permit(value)
7
+ if type_class < TypedParameter::Base
8
+ type.is_a?(Array) ? parameter_array(type_class, value) : type.permit(value)
11
9
  else
12
- constraint = "TypedParameter::Constraints::#{type_class}Constraint".safe_constantize
10
+ constraint = TypedParameter::Constraints[type_class.name.to_sym]
13
11
  constraint ||= TypedParameter::Constraints::StringConstraint # Default
14
12
 
15
- array_type ? constraint_array(constraint, value) : constraint.value(value)
13
+ type.is_a?(Array) ? constraint_array(constraint, value) : constraint.value(value)
16
14
  end
17
15
  end
18
16
 
17
+ private
18
+
19
19
  def parameter_array(parameter_class, values)
20
20
  values.map { |value| parameter_class.permit(value) }
21
21
  end
@@ -1,3 +1,3 @@
1
1
  module TypedParameter
2
- VERSION = '0.2.0'.freeze
2
+ VERSION = '0.6.0'.freeze
3
3
  end
@@ -1,4 +1,4 @@
1
- require 'typed_parameter/boolean' # For Booelan Class Define
1
+ require 'typed_parameter/boolean.rb' # For Booelan Class Define
2
2
 
3
3
  require 'typed_parameter/version'
4
4
  require 'typed_parameter/parameter_types'
@@ -13,6 +13,5 @@ require 'typed_parameter/swagger/type_generator'
13
13
  require 'typed_parameter/swagger/property_generator'
14
14
  require 'typed_parameter/swagger/component_generator'
15
15
 
16
- module TypedParameter
17
- class Error < StandardError; end
18
- end
16
+ require 'typed_parameter/errors'
17
+ module TypedParameter; end
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.homepage = 'https://github.com/tranquilthink/typed-parameter'
11
11
  spec.license = 'MIT'
12
12
  spec.platform = Gem::Platform::RUBY
13
- spec.required_ruby_version = '>= 3.0.0'
13
+ spec.required_ruby_version = '>= 2.7.0'
14
14
 
15
15
  # spec.metadata['allowed_push_host'] = "https://github.com/tranquilthink/typed-parameter"
16
16
  spec.metadata['homepage_uri'] = spec.homepage
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.require_paths = ['lib']
28
28
 
29
29
  # Dependencies
30
- spec.add_dependency 'rails', '~> 6.1'
30
+ spec.add_dependency 'rails'
31
31
 
32
32
  # Test Dependencies
33
33
  spec.add_development_dependency 'rspec'
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: typed-parameter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Minwoo Jo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-03-07 00:00:00.000000000 Z
11
+ date: 2022-02-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '6.1'
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '6.1'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -61,11 +61,12 @@ files:
61
61
  - lib/typed_parameter/constraints/base.rb
62
62
  - lib/typed_parameter/constraints/boolean_constraint.rb
63
63
  - lib/typed_parameter/constraints/date_constraint.rb
64
- - lib/typed_parameter/constraints/datetime_constraint.rb
64
+ - lib/typed_parameter/constraints/date_time_constraint.rb
65
65
  - lib/typed_parameter/constraints/float_constraint.rb
66
66
  - lib/typed_parameter/constraints/integer_constraint.rb
67
67
  - lib/typed_parameter/constraints/string_constraint.rb
68
68
  - lib/typed_parameter/enum_constraint.rb
69
+ - lib/typed_parameter/errors.rb
69
70
  - lib/typed_parameter/parameter_types.rb
70
71
  - lib/typed_parameter/permit_field_generator.rb
71
72
  - lib/typed_parameter/swagger/component_generator.rb
@@ -74,8 +75,8 @@ files:
74
75
  - lib/typed_parameter/swagger/types.rb
75
76
  - lib/typed_parameter/swagger/types/base.rb
76
77
  - lib/typed_parameter/swagger/types/boolean_type.rb
78
+ - lib/typed_parameter/swagger/types/date_time_type.rb
77
79
  - lib/typed_parameter/swagger/types/date_type.rb
78
- - lib/typed_parameter/swagger/types/datetime_type.rb
79
80
  - lib/typed_parameter/swagger/types/float_type.rb
80
81
  - lib/typed_parameter/swagger/types/integer_type.rb
81
82
  - lib/typed_parameter/swagger/types/string_type.rb
@@ -97,7 +98,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
98
  requirements:
98
99
  - - ">="
99
100
  - !ruby/object:Gem::Version
100
- version: 3.0.0
101
+ version: 2.7.0
101
102
  required_rubygems_version: !ruby/object:Gem::Requirement
102
103
  requirements:
103
104
  - - ">="