trailblazer / reform

Form objects decoupled from models.
https://trailblazer.to/2.1/docs/reform.html
MIT License
2.49k stars 184 forks source link

Regression in 2.3 when adding errors in an overridden setter method #509

Open shepmaster opened 4 years ago

shepmaster commented 4 years ago

Complete Description of Issue

This code no longer produces validation failures after upgrading to 2.3

Steps to reproduce

Gemfile

# frozen_string_literal: true

source "https://rubygems.org"

git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }

# Works with this version
gem "reform", '2.2.4'
gem "reform-rails", '~> 0.1', require: false

# Fails with this version
#gem "reform", '2.3.1'
#gem "reform-rails", '~> 0.2', require: false

gem 'dry-types', '~> 0.14.1'

repro.rb

# frozen_string_literal: true

Bundler.require

### BEGIN COPY-PASTE FROM REFORM-RAILS
require "reform"
require "reform/form/active_model/model_validations"
require "reform/form/active_model/form_builder_methods"
require "reform/form/active_model"
require "reform/form/active_model/validations"
require "reform/form/multi_parameter_attributes"

require "reform/active_record" if defined?(ActiveRecord)
require "reform/mongoid" if defined?(Mongoid)

Reform::Form.class_eval do
  include Reform::Form::ActiveModel
  include Reform::Form::ActiveModel::FormBuilderMethods
  include Reform::Form::ActiveRecord if defined?(ActiveRecord)
  include Reform::Form::Mongoid if defined?(Mongoid)
  include Reform::Form::ActiveModel::Validations
end
### END COPY-PASTE

Example = Struct.new(:sorts)

class ExampleForm < Reform::Form
  VALID_SORTS = %w[name date].freeze
  VALID_SORT_DIRECTIONS = %w[asc desc].freeze

  property :sorts, default: [{ by: :name, dir: :desc }]

  def sorts=(sort_strings)
    sorts = sort_strings.split(',').map do |sort|
      by, dir = sort.split(':')

      errors[:sort] << "is not valid" unless VALID_SORTS.include?(by)
      errors[:sort_direction] << "is not valid" unless VALID_SORT_DIRECTIONS.include?(dir)

      { by: by.underscore.to_sym, dir: dir.to_sym }
    end

    super(sorts)
  end
end

model = Example.new
form = ExampleForm.new(model)

res = form.validate({ sorts: 'wutang:asc' })

raise "Should be false" if res
% bundle
% bundle exec ruby repro.rb

# Edit the gemfile to switch to reform 2.3

% bundle update
% bundle exec ruby repro.rb

Expected behavior

The input parameters should be invalid.

Actual behavior

The errors added are lost somewhere and the form is marked as valid.

System configuration

Reform version: Upgrading from 2.2.4 to 2.3.1 Reform-Rails version: Upgrading from 0.1 to 0.2