reform-rails icon indicating copy to clipboard operation
reform-rails copied to clipboard

calling form.validate throws error stack level too deep

Open kmsheng opened this issue 2 years ago • 4 comments

This error occurs when using collection and Disposable::Twin::Parent together For example

require "reform"
require "reform/rails"
require "disposable"
require "disposable/twin/parent"

class SampleForm < Reform::Form
  feature Disposable::Twin::Parent
  property :name
  validates :name, presence: true

  collection :tags, virtual: true, default: [], populator: :populate_tags! do
      property :name
      validates :name, presence: true

      validate :validate_form_name

      def validate_form_name
        if name == parent.name
          errors.add(:name, "tag name duplicates")
        end
      end
    end

   def populate_tags!(fragment:, **)
      existed_tag = tags.find { |tag| tag.name == fragment[:name] }
      return existed_tag if existed_tag
      tags.append(OpenStruct.new(name: fragment[:name]))
   end
end

form = SampleForm.new
form.save(tags: [ { name: "" } ]) 
form.errors.full_messages # SystemStackError: stack level too deep is thrown right here

Any clues would be truly appreciated, thank you

kmsheng avatar Jul 07 '22 04:07 kmsheng

trace before validate

$enable_tracing = false
$trace_out = open('trace.txt', 'w')
set_trace_func proc { |event, file, line, id, binding, classname|
  if $enable_tracing && event == 'call'
     $trace_out.puts "#{file}:#{line} #{classname}##{id}"
  end
}
$enable_tracing = true
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-2.6.2/lib/reform/form/validate.rb:25 Reform::Form::Validate#validate
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-2.6.2/lib/reform/form/validate.rb:34 Reform::Form::Validate#deserialize
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-rails-0.2.3/lib/reform/form/active_model/form_builder_methods.rb:27 Reform::Form::ActiveModel::FormBuilderMethods#deserialize!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/twin.rb:27 Disposable::Twin#schema
<internal:kernel>:18 Kernel#class
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:38 Declarative::Schema::DSL#definitions
/Users/kmsheng/.rbenv/versions/3.0.4/lib/ruby/3.0.0/delegate.rb:75 Delegator#initialize
/Users/kmsheng/.rbenv/versions/3.0.4/lib/ruby/3.0.0/delegate.rb:340 SimpleDelegator#__setobj__
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/twin/definitions.rb:24 Disposable::Twin::Definition::Each#each
/Users/kmsheng/.rbenv/versions/3.0.4/lib/ruby/3.0.0/delegate.rb:318 SimpleDelegator#__getobj__
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:29 Declarative::Definitions#each
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-rails-0.2.3/lib/reform/form/active_model/form_builder_methods.rb:37 Reform::Form::ActiveModel::FormBuilderMethods#rename_nested_param_for!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:9 Declarative::Definitions::Definition#[]
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-rails-0.2.3/lib/reform/form/active_model/form_builder_methods.rb:37 Reform::Form::ActiveModel::FormBuilderMethods#rename_nested_param_for!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:9 Declarative::Definitions::Definition#[]
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-rails-0.2.3/lib/reform/form/active_model/form_builder_methods.rb:37 Reform::Form::ActiveModel::FormBuilderMethods#rename_nested_param_for!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:9 Declarative::Definitions::Definition#[]
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-2.6.2/lib/reform/form/validate.rb:42 Reform::Form::Validate#deserialize!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-2.6.2/lib/reform/form/validate.rb:67 Reform::Form::Validate#deserializer
<internal:kernel>:18 Kernel#class
<internal:kernel>:18 Kernel#class
<internal:kernel>:18 Kernel#class
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/reform-2.6.2/lib/reform/form/validate.rb:52 Reform::Form::Validate#deserializer!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/rescheme.rb:11 Disposable::Rescheme#from
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/rescheme.rb:16 Disposable::Rescheme#from
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/rescheme.rb:32 Disposable::Rescheme#build_representer
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:24 Declarative::Heritage::Inherited#inherited
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:17 Declarative::Heritage::DSL#heritage
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:12 Declarative::Heritage#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/representable-3.2.0/lib/representable/hash.rb:12 Representable::Hash#included
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/representable-3.2.0/lib/representable.rb:32 Representable#included
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:96 Declarative::Schema::Feature#register_feature
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:17 Declarative::Heritage::DSL#heritage
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:6 Declarative::Heritage#record
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:28 Declarative::Schema::DSL#defaults
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:17 Declarative::Heritage::DSL#heritage
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:6 Declarative::Heritage#record
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:38 Declarative::Defaults#wrap_arrays
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:59 Declarative::Schema::DSL#_defaults
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:5 Declarative::Defaults#initialize
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:12 Declarative::Defaults#merge!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:28 Declarative::Defaults#handle_array_and_deprecate
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:38 Declarative::Defaults#wrap_arrays
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/variables.rb:12 Declarative::Variables#merge
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/variables.rb:32 Declarative::Variables#Append
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:12 Declarative::Defaults#merge!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:28 Declarative::Defaults#handle_array_and_deprecate
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:38 Declarative::Defaults#wrap_arrays
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/variables.rb:12 Declarative::Variables#merge
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:38 Declarative::Schema::DSL#definitions
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:29 Declarative::Definitions#each
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:9 Declarative::Definitions::Definition#[]
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/rescheme.rb:36 Disposable::Rescheme#build_definition!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:9 Declarative::Definitions::Definition#[]
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/rescheme.rb:48 Disposable::Rescheme#exclude!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:9 Declarative::Definitions::Definition#[]
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/disposable-0.6.3/lib/disposable/rescheme.rb:54 Disposable::Rescheme#from_scalar!
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:9 Declarative::Definitions::Definition#[]
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:22 Declarative::Schema::DSL#property
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:17 Declarative::Heritage::DSL#heritage
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/heritage.rb:6 Declarative::Heritage#record
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:17 Declarative::DeepDup#dup_items
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/deep_dup.rb:5 Declarative::DeepDup#call
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/representable-3.2.0/lib/representable/cached.rb:5 Representable::Cached::BuildDefinition#build_definition
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:47 Declarative::Schema::DSL#build_definition
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/representable-3.2.0/lib/representable/decorator.rb:14 Representable::Decorator#default_nested_class
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/schema.rb:59 Declarative::Schema::DSL#_defaults
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/representable-3.2.0/lib/representable/declarative.rb:66 Representable::Declarative#definitions
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/representable-3.2.0/lib/representable/config.rb:12 Representable::Config#initialize
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:24 Declarative::Definitions#initialize
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/definitions.rb:39 Declarative::Definitions#add
/Users/kmsheng/work/super_tools/vendor/bundle/ruby/3.0.0/gems/declarative-0.0.20/lib/declarative/defaults.rb:20 Declarative::Defaults#call

kmsheng avatar Jul 07 '22 06:07 kmsheng

looks like https://github.com/trailblazer/reform-rails/blob/master/lib/reform/form/active_model/validations.rb#L172 would cause infinite loop

kmsheng avatar Jul 07 '22 06:07 kmsheng

          def full_messages_for_nested_fields(form_fields)
            form_fields
              .to_a
              .reject { |field| field[0] == "parent" }
              .map { |field| full_messages_for_twin(field[1]) }
          end

kmsheng avatar Jul 07 '22 08:07 kmsheng

https://github.com/trailblazer/reform-rails/pull/95 If anything that needs to update, please let me know : )

kmsheng avatar Jul 07 '22 09:07 kmsheng