Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

when using composition, validation fails on aliased properties #438

Open
lastobelus opened this issue May 28, 2017 · 9 comments
Open

when using composition, validation fails on aliased properties #438

lastobelus opened this issue May 28, 2017 · 9 comments
Milestone

Comments

@lastobelus
Copy link

Complete Description of Issue

When using composition, if you define an "aliased" property using on:, from:, required validation does not work on that property.

Steps to reproduce

context 'validate id' do
  Song   = Struct.new(:id, :title)
  Album  = Struct.new(:id, :title)

  class ComposedForm < Reform::Form
    include Composition
    property :album_id, on: :album, from: :id
    property :title, on: :album

    property :song_id, on: :song, from: :id

    validation do
      required(:album_id).filled
      required(:title).filled
    end
  end

  context 'composed form' do
    it "validates id" do
      form = ComposedForm.new(album: Album.new(111, "bob"), song: Song.new)
      form.validate({})
      expect(form.to_result.errors).to be_empty
    end
  end
end

Expected behavior

The above spec should pass. Inspecting the form verifies form.album_id is present.

Actual behavior

Spec fails, form has "album_id: is missing" error:

Failures:

  1) validate id composed form validates id
     Failure/Error: expect(form.to_result.errors).to be_empty
       expected `{:album_id=>["is missing"]}.empty?` to return true, got false
     # ./spec/forms/validate_id_on_composed_model_spec.rb:45:in `block (3 levels) in <top (required)>'
     # ./spec/spec_helper.rb:51:in `block (2 levels) in <top (required)>'

System configuration

Reform version: 2.3.0rc1

@fran-worley
Copy link
Collaborator

From memory, we ignor composition when we pass params to dry-validation purposes.

The idea is to validate your input, not the format of the output (composition).

Happy to discuss changing the behavior but it would have to be configurable.

@adamakhtar
Copy link

Hi @fran-worley.

To clarify your last comment do you mean validating composed forms is not currently possible in Reform? If that is not the case then what is the correct syntax to validate the form in @lastobelus comment?

I'm having the same problem and looked at docs and google but to no avail.

@karouf
Copy link

karouf commented Aug 10, 2017

I hit the same problem trying to use composition.
Well it seems that Reform produces a nested hash from the form according to the composition rules and passes it to dry-validation.
In that example, the following params are passed to the form:

{}

And the following hash is passed to dry-validation:

{:album=>{"id"=>111, "title"=>"bob"}, :song=>{"id"=>nil}}

Therefore it doesn't find any album_id param.

The following example works though:

context "validate id" do
  Song   = Struct.new(:id, :title)
  Album  = Struct.new(:id, :title)

  class ComposedForm < Reform::Form
    include Composition
    property :album_id, on: :album, from: :id
    property :title, on: :album

    property :song_id, on: :song, from: :id

    validation do
      required(:album).schema do
        required(:id).filled
        required(:title).filled
      end
    end
  end

  context "composed form" do
    it "validates id" do
      form = ComposedForm.new(album: Album.new(111, "bob"), song: Song.new)
      form.validate({})
      expect(form.to_result.errors).to be_empty
    end
  end
end

The trick is to validate a nested hash with dry-validation to match the hash that is passed to it by Reform.
Note that the Form#errors hash after validation will reflect the composition and will give you errors in this way: {:album=>[[:id, ["must be an integer"]]]}

@fran-worley
Copy link
Collaborator

This is the bit of code that reform uses to transform the input params for dry validation:
https://github.com/trailblazer/reform/blob/master/lib/reform/form/dry.rb#L74-L78

I'm unsure what your expectation is (confession - I've never needed composition myself).
What format of params should be validated and where should the errors come through?

@karouf
Copy link

karouf commented Aug 10, 2017

Since I was declaring an album_id property in the contract block, I was expecting to reference it the same way in the validation block. It's a bit counter-intuitive but probably nothing that couldn't be fixed just by updating the docs.

@fran-worley
Copy link
Collaborator

@karouf updating the docs is one thing, but if composition users find it counter-intuitive there might be a better way of doing things no?

Can I assume that the reproduction example from @lastobelus is what your expectation is?

@karouf
Copy link

karouf commented Aug 10, 2017

By the way I tested that on 2.2.4 and I see it's a bit different than master. In 2.2.4 #to_nested_hash is called on the form whereas on master #to_hash is called.

Sure I agree that it would benefit from being more intuitive. I was just saying that it's not a show-stopper either, as I was led to believe when I first stumble upon this issue.
As a first step, adding some info about that in the docs would probably save some time to some people.

I would need to have a look at the behavior in master but basically the code @lastobelus posted is the way I expected it to work yes.

@fran-worley
Copy link
Collaborator

@karouf cool, glad we are on the same page. There are no formal composition/dry validation test cases, probably why the implementation has changed between versions. I'll use @lastobelus code to put a test case in for us to work towards.

Thanks everyone 👍

@simonc
Copy link
Contributor

simonc commented Oct 3, 2022

Hi there. From what I'm experiencing today, it's not limited to composition. When creating a simple form that aliases a property with from: you also need to refer to the original name in validations.

❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants