typed_parameter
Create typed parameter class using strong parameter in rails. You can cleanup parameter code for permit in your controller and convert it to the type you want. You can get your OpenAPI JSON for parameter schemas.
Installation
Add this line to your application's Gemfile:
gem 'typed-parameter'
And then execute:
$ bundle install
Or install it yourself as:
$ gem install typed-parameter
Usage
Example 1. Type convert
class UserCreateParams < TypedParameter::Base
field :name, String
field :age, Integer
field :email, String
end
-----------------------------------------------
############
## before ##
############
# method for params
def user_create_params
params.permit(:name, :age, :email)
end
# in action
def create
raise UserAgeTooYoung if user_create_params[:age].to_i < 20
# You need to convert your parameter type
end
############
## after ###
############
# method for params
def user_create_params
UserCreateParams.permit(params)
end
# in action
def create
raise UserAgeTooYoung if user_create_params[:age] < 20
# paramters are converted as your type
end
Example 2. More Types
class CustomParameter < TypedParameter::Base
field :string_field, String
field :integer_field, Integer
field :float_field, Float
field :date_field, Date
field :datetime_field, DateTime
field :boolean_field, Boolean
end
############
## before ##
############
def custom_params
params.permit(
:string_field, # => is_a? String
:integer_field, # => is_a? String. You need to &:to_i
:fload_field, # => is_a? String. You need to &:to_f
:date_field, # => is_a? String. You need to &:to_date
:datetime_field # => is_a? String. You need to &:to_datetime
:boolean_field # => is_a? Boolean. If paramter is string (like "false") then String
)
end
############
## after ##
############
def custom_params
CustomParamter.permit(params)
end
custom_params[:string_field] # => is_a? String
custom_params[:integer_field] # => is_a? Integer
custom_params[:float_field] # => is_a? Float
custom_params[:date_field] # => is_a? Date
custom_params[:datetime_field] # => is_a? DateTime
custom_params[:boolean] # => is_a? Boolean, If parameter is string (like "false", "true" "False", "True") then convert true or false
Example 3. Enum & Required
class EnumAndRequiredParameter < TypedParameter::base
field :enum_field, Integer, enum: [10, 20, 30, 40]
field :required_field, String, required: true
end
def enum_and_required_params
EnumAndRequiredParameter.permit(params)
end
# If params[:enum_field] has 25 ( not in 10, 20, 30, 40)
# => ArgumentError, "enum_field must be in 10, 20, 30, 40"
# if params[:required_field] is Nil
# => ArgumentError, "required_field is required"
Example 4. array & nested parameters
class ParentParameter < TypedParameter::Base
field :name, String
field :integers, [Integer]
field :child, ChildParameter
field :childs, [ChildParamter]
end
class ChildParameter < TypedParameter::Base
field :name, String
end
example_params = {
name: "Name",
integers: ['1','2','3','4'],
child: { name: "child" },
childs: [
{ name: "child1", age: "10" },
{ name: "child2", age: "12" },
{ name: "child3", age: "15" }
]
}
def parent_and_childs_params
ParentParameter.permit(example_params)
end
# Result
{
name: "Name",
integers: [1,2,3,4],
child: { name: "child" },
childs: [
{ name: "child1" },
{ name: "child2" },
{ name: "child3" }
]
}
Example 4. CustomType
If You want to use your custom type like Email, just create two file.
- your type file. like "Email"
- yout type constant. like "EmailConstrant"
class Email
def initialize(value)
@email = value
end
end
class EmailConstrant
class << self
EMAIL_REGREX = //
# using convert value to your type
def value(value)
raise ArgumentError unless EMAIL_REGREX.match? value
Email.new(value)
end
end
end
class EmailSwaggerType
class << self
def value
{ type: :string }
end
end
end
# Register your type to typed-parameter when application initialize.
TypedParameter::ParameterTypes.register Email
TypedParameter::Constants.register :Email, EmailConstrant
TypedParameter::Swagger::Types.register :Email, EmailSwaggerType
Example 5. Use Inline Block
You can use parameter class by block
class BlockParameter < TypedParameter::Base
field :some_object, Object do |i|
i.field :name, String
i.field :type, String
end
field :other_hash_list, [Hash] do |i|
i.field :index, Integer
i.field :value, Float
end
end
Example 6. Swaggerize
With Rswag(https://github.com/rswag/rswag), you can swaggerize your parameter types.
class SwaggerParameter < TypedParameter::Base
field :string, String, enum: ["one", "two"], description: "String Field"
field :integer, Integer, description: "Integer Field"
field :ref_field, SwaggerRefParameter
end
class SwaggerRefParameter < TypedParameter::Base
field :string, String, description: "Ref String Field"
end
SwaggerParameter.swagger_properties
# =>
# {
# string: { type: :string, enum: ["one", "two" ], description: "String Field" },
# integer: { type: :integer, description: "Integer Field" },
# ref_field: { "$ref": "#/components/schemas/SwaggerRefParamter" }
# }
#
# Add Components in your swagger
# in swagger_helper
components = TypedParameter::Swagger::ComponentGenerator.generate_all!
config.swagger_docs = {
'v1/swagger.yaml' => {
openapi: '3.0.1',
# ...,
components: {
schemas: {
**components
}
}
#...
}
}
...
Development
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.
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.
Contributing
Bug reports and pull requests are welcome on GitHub at https://github.com/tranquilthink/typed-parameter.