Skip to content

rodrigonbarreto/dry_params

Repository files navigation

DryParams

Work in Progress - This gem is under active development and currently used in production with Grape only.

If you use dry-validation extensively, you know the pain of duplicating field definitions between your contracts and your API params. This gem eliminates that repetition by automatically generating Grape params (or Rails strong params) directly from your Dry::Validation contracts.

Installation

gem 'dry_params'

Grape

class UserContract < Dry::Validation::Contract
  params do
    required(:name).filled(:string)
    required(:age).filled(:integer)
    optional(:email).maybe(:string)
  end
end

DryParams.from(UserContract)
# => {
#   name: { type: String, desc: "Name", required: true, documentation: { param_type: "body" } },
#   age: { type: Integer, desc: "Age", required: true, documentation: { param_type: "body" } },
#   email: { type: String, desc: "Email", required: false, documentation: { param_type: "body" } }
# }

Custom Descriptions

Use comment annotations to provide custom descriptions for your params:

class AppointmentCreateContract < Dry::Validation::Contract
  params do
    # @title = Title of the appointment
    required(:title).filled(:string)
    # @start_time = Start time in ISO8601 format
    required(:start_time).filled(:time)
    # @duration_minutes = Duration in minutes (default: 60)
    optional(:duration_minutes).filled(:integer)
  end
end

DryParams.from(AppointmentCreateContract)
# => {
#   title: { type: String, desc: "Title of the appointment", required: true, ... },
#   start_time: { type: Time, desc: "Start time in ISO8601 format", required: true, ... },
#   duration_minutes: { type: Integer, desc: "Duration in minutes (default: 60)", required: false, ... }
# }

The annotation format is # @field_name = Your description here. Without annotations, the field name is humanized (e.g., start_time becomes "Start time").

Usage:

desc "Create user", { params: DryParams.from(UserContract) }

For query params:

desc "List users", { params: DryParams.from(UserFilterContract, param_type: 'query') }

Rails

DryParams.from(UserContract, adapter: :rails)
# => [:name, :age, :email]

With arrays and hashes:

class PostContract < Dry::Validation::Contract
  params do
    required(:title).filled(:string)
    optional(:tags).filled(:array)
    optional(:metadata).filled(:hash)
  end
end

DryParams.from(PostContract, adapter: :rails)
# => [:title, { tags: [], metadata: {} }]

Usage:

def post_params
  params.permit(DryParams.from(PostContract, adapter: :rails))
end

Development

bundle exec bin/console  # interactive console
bundle exec rspec        # run tests

Status

  • Grape adapter (production ready)
  • Rails adapter (experimental)
  • Nested contracts support
  • Custom type mappings

License

MIT

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors