typed-parameter 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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: []