typed-parameter 0.1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 8e0f46ef3693b82ba2c85964aba75468b69971855dbe6cff28e8b6c7c66d2f74
4
+ data.tar.gz: 2a3d91c2d8d229bb89336bd891db8169494619d996f6ec2553a14ffc213733b6
5
+ SHA512:
6
+ metadata.gz: 798e72cc8eefdd41e684ab5e9df6c0513a4bdaed0559136e8c0839a51113e2c696f229d751dbae83f664d7a642e5cb6d1df7ab3fa5a9bae00ac4dbc976d11a1b
7
+ data.tar.gz: a1d9565b84129234acf6cb683c10762751b62b2de77e4dc15842c71e413881e0d4c5e6d3ddaef9d4f3cd8a877de8a68cb3deb677079f54af838796d2c62aa17d
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ *.gem
2
+ coverage/*
3
+ Gemfile.lock
4
+ *~
5
+ .bundle
6
+ .rvmrc
7
+ log/*
8
+ measurement/*
9
+ pkg/*
10
+ .DS_Store
11
+ .env
12
+ spec/dummy/tmp/*
13
+ spec/dummy/log/*.log
data/.rubocop.yml ADDED
@@ -0,0 +1,53 @@
1
+ # inherit_from: .rubocop_todo.yml
2
+
3
+ AllCops:
4
+ NewCops: enable
5
+ SuggestExtensions: false
6
+ Layout/SpaceBeforeBrackets: # (new in 1.7)
7
+ Enabled: true
8
+ Layout/HashAlignment:
9
+ Enabled: true
10
+ EnforcedColonStyle: table
11
+ Lint/AmbiguousAssignment: # (new in 1.7)
12
+ Enabled: true
13
+ Lint/DuplicateBranch: # (new in 1.3)
14
+ Enabled: true
15
+ Lint/DuplicateRegexpCharacterClassElement: # (new in 1.1)
16
+ Enabled: true
17
+ Lint/EmptyBlock: # (new in 1.1)
18
+ Enabled: true
19
+ Lint/EmptyClass: # (new in 1.3)
20
+ Enabled: true
21
+ Lint/NoReturnInBeginEndBlocks: # (new in 1.2)
22
+ Enabled: true
23
+ Lint/ToEnumArguments: # (new in 1.1)
24
+ Enabled: true
25
+ Lint/UnexpectedBlockArity: # (new in 1.5)
26
+ Enabled: true
27
+ Lint/UnmodifiedReduceAccumulator: # (new in 1.1)
28
+ Enabled: true
29
+ Style/ArgumentsForwarding: # (new in 1.1)
30
+ Enabled: true
31
+ Style/CollectionCompact: # (new in 1.2)
32
+ Enabled: true
33
+ Style/DocumentDynamicEvalDefinition: # (new in 1.1)
34
+ Enabled: true
35
+ Style/HashExcept: # (new in 1.7)
36
+ Enabled: true
37
+ Style/NegatedIfElseCondition: # (new in 1.2)
38
+ Enabled: true
39
+ Style/NilLambda: # (new in 1.3)
40
+ Enabled: true
41
+ Style/RedundantArgument: # (new in 1.4)
42
+ Enabled: true
43
+ Style/SwapValues: # (new in 1.1)
44
+ Enabled: true
45
+ Style/StringLiterals:
46
+ Enabled: true
47
+ Style/AsciiComments:
48
+ Enabled: false
49
+ Style/Documentation:
50
+ Enabled: false
51
+ Style/FrozenStringLiteralComment:
52
+ Enabled: true
53
+ EnforcedStyle: always_true
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.0.0
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in typed_parameter.gemspec
4
+ gemspec
5
+
6
+ gem 'rake', '~> 12.0'
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ # TypedParameter
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/typed-parameter`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'typed-parameter'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle install
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install typed-parameter
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/typed-parameter.
36
+
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+ task :default => :spec
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "typed_parameter"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,17 @@
1
+ require 'typed_parameter/boolean' # For Booelan Class Define
2
+
3
+ require 'typed_parameter/version'
4
+ require 'typed_parameter/parameter_types'
5
+ require 'typed_parameter/constraints'
6
+ require 'typed_parameter/enum_constraint'
7
+ require 'typed_parameter/type_constraint'
8
+ require 'typed_parameter/permit_field_generator'
9
+ require 'typed_parameter/base'
10
+
11
+ require 'typed_parameter/swagger/types'
12
+ require 'typed_parameter/swagger/type_generator'
13
+ require 'typed_parameter/swagger/property_generator'
14
+ require 'typed_parameter/swagger/component_generator'
15
+ module TypedParameter
16
+ class Error < StandardError; end
17
+ end
@@ -0,0 +1,74 @@
1
+ module TypedParameter
2
+ class Base
3
+ class << self
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
9
+
10
+ def permit(params)
11
+ raise ArgumentError unless params.class <= ActionController::Parameters
12
+
13
+ use_constraints params.permit(fields)
14
+ end
15
+
16
+ def fields
17
+ __fields.freeze
18
+ end
19
+
20
+ def swagger_properties
21
+ __swagger_properties.freeze
22
+ end
23
+
24
+ alias key name
25
+
26
+ def ref
27
+ "#/components/schemas/#{key}"
28
+ end
29
+
30
+ private
31
+
32
+ def initialize_swagger_properties(name, type, kargs)
33
+ swagger_type = TypedParameter::Swagger::TypeGenerator.generate(type)
34
+ swagger_options = swagger_type.merge(kargs)
35
+ __swagger_properties[name] = swagger_options
36
+ end
37
+
38
+ def initialize_permitted_fields(name, type)
39
+ __fields << PermitFieldGenerator.generate(name, type)
40
+ end
41
+
42
+ def initialize_constraints(name, type, kargs)
43
+ options = kargs.slice(:enum, :required)
44
+
45
+ __constraints << [name, type, options]
46
+ end
47
+
48
+ def use_constraints(params)
49
+ __constraints.each do |name, type, options|
50
+ value = params[name]
51
+ raise ArgumentError, "(#{self.name}) #{name} is required" if options[:required] && !value.present?
52
+ next unless value.present?
53
+
54
+ params[name] = TypeConstraint.value(type, value)
55
+ params[name] = EnumConstraint.value(value, options[:enum]) if options[:enum]
56
+ end
57
+
58
+ params
59
+ end
60
+
61
+ def __fields
62
+ @__fields ||= []
63
+ end
64
+
65
+ def __constraints
66
+ @__constraints ||= []
67
+ end
68
+
69
+ def __swagger_properties
70
+ @__swagger_properties ||= {}
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,19 @@
1
+ return if defined? Boolean
2
+
3
+ class Boolean; end
4
+
5
+ class TrueClass
6
+ def is_a?(type)
7
+ return true if type == Boolean
8
+
9
+ super(type)
10
+ end
11
+ end
12
+
13
+ class FalseClass
14
+ def is_a?(type)
15
+ return true if type == Boolean
16
+
17
+ super(type)
18
+ end
19
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TypedParameter
4
+ class Constraints
5
+ def self.value(_v)
6
+ nil
7
+ end
8
+
9
+ class IntegerConstraint < self
10
+ def self.value(value)
11
+ value.to_i
12
+ end
13
+ end
14
+
15
+ class FloatConstraint < self
16
+ def self.value(value)
17
+ value.to_f
18
+ end
19
+ end
20
+
21
+ class StringConstraint < self
22
+ def self.value(value)
23
+ value.to_s
24
+ end
25
+ end
26
+
27
+ class BooleanConstraint < self
28
+ TRUE_VALUES = [true, 'true', '1', 1].freeze
29
+ FALSE_VALUES = [false, 'false', '0', 0].freeze
30
+
31
+ def self.value(value)
32
+ return true if TRUE_VALUES.include?(value)
33
+ return false if FALSE_VALUES.include?(value)
34
+ end
35
+ end
36
+
37
+ class DateConstraint < self
38
+ def self.value(value)
39
+ value.to_date
40
+ end
41
+ end
42
+
43
+ class DateTimeConstraint < self
44
+ def self.value(value)
45
+ value.to_datetime
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,10 @@
1
+ module TypedParameter
2
+ module EnumConstraint
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
6
+
7
+ value
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ module TypedParameter
2
+ module ParameterTypes
3
+ BASE_TYPES = [Integer, Float, String, Date, DateTime, Boolean].freeze
4
+ CUSTOM_TYPES = [].freeze
5
+ end
6
+ end
@@ -0,0 +1,24 @@
1
+ module TypedParameter
2
+ module PermitFieldGenerator
3
+ class << self
4
+ BASE_TYPES = TypedParameter::ParameterTypes::BASE_TYPES
5
+
6
+ def generate(name, type)
7
+ props = generate_properties(type)
8
+
9
+ props = [] if type.is_a?(Array) && type[0].in?(BASE_TYPES)
10
+ return name unless props
11
+
12
+ [[name, props]].to_h
13
+ end
14
+
15
+ def generate_properties(type)
16
+ return if type.in? BASE_TYPES
17
+ return generate_properties(type[0]) if type.is_a? Array
18
+ return type.keys if type.is_a? Hash
19
+
20
+ type.fields
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,14 @@
1
+ module TypedParameter
2
+ module Swagger
3
+ module ComponentGenerator
4
+ class << self
5
+ def generate(parameter_class)
6
+ key = parameter_class.key
7
+ properties = Swagger::PropertyGenerator.generate(parameter_class.swagger_properties)
8
+
9
+ { "#{key}": { type: :object, properties: properties } }
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,28 @@
1
+ module TypedParameter
2
+ module Swagger
3
+ module PropertyGenerator
4
+ class << self
5
+ def generate(swagger_properties)
6
+ swagger_properties.transform_values do |options|
7
+ next { "$ref": ref(options[:ref]) } if options[:ref].present?
8
+
9
+ if options[:type] == :array
10
+ items = options[:items].dup
11
+ if items[:ref].present?
12
+ ref = items.delete(:ref)
13
+ items['$ref'] = ref(ref)
14
+ options[:items] = items
15
+ end
16
+ end
17
+
18
+ options
19
+ end
20
+ end
21
+
22
+ def ref(ref_component)
23
+ "#/components/schemas/#{ref_component.key}"
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ module TypedParameter
2
+ module Swagger
3
+ module TypeGenerator
4
+ class << self
5
+ BASE_TYPES = TypedParameter::ParameterTypes::BASE_TYPES
6
+ CUSTOM_TYPES = TypedParameter::ParameterTypes::CUSTOM_TYPES
7
+
8
+ def generate(type)
9
+ return array_generate(type) if type.is_a? Array
10
+ return hash_generate(type) if type.is_a? Hash
11
+
12
+ swagger_type = "TypedParameter::Swagger::Types::#{type.name}Type".safe_constantize
13
+ swagger_type&.value || { ref: type }
14
+ end
15
+
16
+ def hash_generate(hash)
17
+ h = hash.transform_values { |value| generate(value) }
18
+
19
+ { type: :object, properties: h }
20
+ end
21
+
22
+ def array_generate(type)
23
+ { type: :array, items: generate(type[0]) }
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,45 @@
1
+ module TypedParameter
2
+ module Swagger
3
+ class Types
4
+ def self.value
5
+ raise NotImplementedError, 'You need to implement this method'
6
+ end
7
+
8
+ class IntegerType
9
+ def self.value
10
+ { type: :integer }
11
+ end
12
+ end
13
+
14
+ class FloatType
15
+ def self.value
16
+ { type: :number, format: :float }
17
+ end
18
+ end
19
+
20
+ class StringType
21
+ def self.value
22
+ { type: :string }
23
+ end
24
+ end
25
+
26
+ class BooleanType
27
+ def self.value
28
+ { type: :boolean }
29
+ end
30
+ end
31
+
32
+ class DateTimeType
33
+ def self.value
34
+ { type: :string, format: :datetime }
35
+ end
36
+ end
37
+
38
+ class DateType
39
+ def self.value
40
+ { type: :string, format: :date }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,28 @@
1
+ module TypedParameter
2
+ module TypeConstraint
3
+ class << self
4
+ def value(type, value)
5
+ type_class = [type].flatten.first
6
+ array_type = type.is_a?(Array)
7
+ parameter_type = type_class < TypedParameter::Base
8
+
9
+ if parameter_type
10
+ array_type ? parameter_array(type_class, value) : type.permit(value)
11
+ else
12
+ constraint = "TypedParameter::Constraints::#{type_class}Constraint".safe_constantize
13
+ constraint ||= TypedParameter::Constraints::StringConstraint # Default
14
+
15
+ array_type ? constraint_array(constraint, value) : constraint.value(value)
16
+ end
17
+ end
18
+
19
+ def parameter_array(parameter_class, values)
20
+ values.map { |value| parameter_class.permit(value) }
21
+ end
22
+
23
+ def constraint_array(constraint, values)
24
+ values.map { |value| constraint.value(value) }
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,3 @@
1
+ module TypedParameter
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path('lib/typed_parameter/version', __dir__)
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'typed-parameter'
5
+ spec.version = TypedParameter::VERSION
6
+ spec.authors = ['Minwoo Jo']
7
+ spec.email = ['tranquilthink@example.com']
8
+ spec.summary = 'Typed Paramter For Rails'
9
+ spec.description = 'Create typed parameter class using strong paramter in rails'
10
+ spec.homepage = 'https://github.com/tranquilthink/typed-parameter'
11
+ spec.license = 'MIT'
12
+ spec.platform = Gem::Platform::RUBY
13
+ spec.required_ruby_version = '>= 3.0.0'
14
+
15
+ # spec.metadata['allowed_push_host'] = "https://github.com/tranquilthink/typed-parameter"
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = 'https://github.com/tranquilthink/typed-parameter'
18
+ spec.metadata['changelog_uri'] = 'https://github.com/tranquilthink/typed-parameter/blob/master/CHANGELOG.md'
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = 'exe'
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ['lib']
28
+
29
+ # Dependencies
30
+ spec.add_dependency 'rails', '~> 6.1'
31
+
32
+ # Test Dependencies
33
+ spec.add_development_dependency 'rspec'
34
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: typed-parameter
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Minwoo Jo
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2021-03-06 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
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
+ description: Create typed parameter class using strong paramter in rails
42
+ email:
43
+ - tranquilthink@example.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".rubocop.yml"
50
+ - ".ruby-version"
51
+ - Gemfile
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - lib/typed_parameter.rb
57
+ - lib/typed_parameter/base.rb
58
+ - lib/typed_parameter/boolean.rb
59
+ - lib/typed_parameter/constraints.rb
60
+ - lib/typed_parameter/enum_constraint.rb
61
+ - lib/typed_parameter/parameter_types.rb
62
+ - lib/typed_parameter/permit_field_generator.rb
63
+ - lib/typed_parameter/swagger/component_generator.rb
64
+ - lib/typed_parameter/swagger/property_generator.rb
65
+ - lib/typed_parameter/swagger/type_generator.rb
66
+ - lib/typed_parameter/swagger/types.rb
67
+ - lib/typed_parameter/type_constraint.rb
68
+ - lib/typed_parameter/version.rb
69
+ - typed_parameter.gemspec
70
+ homepage: https://github.com/tranquilthink/typed-parameter
71
+ licenses:
72
+ - MIT
73
+ metadata:
74
+ homepage_uri: https://github.com/tranquilthink/typed-parameter
75
+ source_code_uri: https://github.com/tranquilthink/typed-parameter
76
+ changelog_uri: https://github.com/tranquilthink/typed-parameter/blob/master/CHANGELOG.md
77
+ post_install_message:
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: 3.0.0
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubygems_version: 3.2.3
93
+ signing_key:
94
+ specification_version: 4
95
+ summary: Typed Paramter For Rails
96
+ test_files: []