dry-rb / dry-rb/dry-schema

Reusing schema definition and validating Hash

Open
#293 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
Ruby
Stars
492
Forks
123
PR merge metrics
No merged PRs in 30d

Description

Describe the bug

I'm having some schemas defined used in a contract for validating the HTTP params when creating an App, which can contain also an image as attachment (using nested attributes).

# frozen_string_literal: true

module Apps
  module Schemas
    class Base < Dry::Schema::Params
      define do
        required(:name).filled(:string, min_size?: 3)
        optional(:description).maybe(:string)
        optional(:public).filled(:bool)
        optional(:status).filled(:string, included_in?: %w[draft in_review approved published])
        optional(:contact_email).maybe(:string)

        optional(:image_attributes).maybe(:hash) do
          ::Attachments::Schemas::Base.new
        end
      end
    end
  end
end

Since the Attachments can be reused in other models as well, it was extracted into an own schema.

# frozen_string_literal: true

module Attachments
  module Schemas
    class Base < Dry::Schema::Params
      define do
        optional(:id).maybe(:integer)
        optional(:type).maybe(:string)
        optional(:file).maybe(:string)
        optional(:_destroy).maybe(:bool)
      end
    end
  end
end

And this would be the App contract.

# frozen_string_literal: true

module Apps
  module Contracts
    class Base < Dry::Validation::Contract
      params(::Apps::Schemas::Base.new)
    end
  end
end

The problem I'm seeing is that the contract will not extract the image_attributes from the params if I validate the image_attributes to be a hash.

To Reproduce

Set the params to be:

{
  "id": "some_id",
  "name": "test",
  "description": "test",
  "public": false,
  "status": "draft",
  "contact_email": nil,
  "image_attributes":
  {
    "file": "{some payload}}",
    "url": "https://some_url",
    "type": "ImageAttachment"
  }
}

and check the contract:

contract = ::Apps::Contracts::Base.new.call(params)

the result will not have image_attributes set:

 #<Dry::Validation::Result{:name=>"test", :description=>"test", :public=>false, :status=>"draft", :contact_email=>nil, :image_attributes=>{}} errors={}>

Expected behavior

To extract the image_attributes from the params.

IMPORTANT:

I noticed that validating the image_attributes to be a hash works also fine when the attachment attributes are directly defined in the schema (cannot reuse the Attachment::Schema::Base):

optional(:image_attributes).maybe(:hash) do
  optional(:id).maybe(:integer)
  optional(:type).maybe(:string)
  optional(:file).maybe(:string)
  optional(:_destroy).maybe(:bool)
end

Your environment

  • Ruby version: 2.6.6
  • OS: Linux
  • dry-validation: 1.5
  • dry-schema: 1.5

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with Apps::Schemas::Base, Attachments::Schemas::Base, and Apps::Contracts::Base, then reproduce the result from contract.call(params) using the nested image_attributes hash. Trace how the reusable attachment schema is applied under the hash validation and compare it with the inline definition. Done means the validated result preserves the image_attributes values while retaining the existing validation behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
ruby
Domain
backend
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
38/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.