From 847de6430b142a66c03712b6fad9ff11d2ebb95d Mon Sep 17 00:00:00 2001 From: Celso Fernandes Date: Thu, 18 Oct 2018 19:32:07 +0200 Subject: [PATCH 1/2] Draft of indexed errors implementation TODO: do not use class variable for configuration --- lib/reform/errors.rb | 37 ++++++++++++++++++++++++++++++++++--- test/errors_test.rb | 23 +++++++++++++++++++++++ 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/lib/reform/errors.rb b/lib/reform/errors.rb index 678f5d44..227bdd11 100644 --- a/lib/reform/errors.rb +++ b/lib/reform/errors.rb @@ -1,6 +1,8 @@ # Provides the old API for Rails and friends. # Note that this might become an optional "deprecation" gem in Reform 3. class Reform::Contract::Result::Errors + @@index_errors = false + def initialize(result, form) @result = result # DISCUSS: we don't use this ATM? @form = form @@ -10,19 +12,48 @@ def initialize(result, form) end # PROTOTYPING. THIS WILL GO TO A SEPARATE GEM IN REFORM 2.4/3.0. - DottedErrors = ->(form, prefix, hash) do + DottedErrors = ->(form, prefix, hash, i = nil) do result = form.to_result - result.messages.collect { |k,v| hash[ [*prefix, k].join(".").to_sym] = v } + if indexed_errors? + result.messages.collect do |k,v| + indexed_errors(prefix, hash, k, v, i) + end + else + result.messages.collect { |k,v| hash[ [*prefix, k].join(".").to_sym] = v } + end form.schema.each(twin: true) { |dfn| Disposable::Twin::PropertyProcessor.new(dfn, form).() do |frm, i| # DottedErrors.(form.send(dfn[:name])[i], [*prefix, dfn[:name], i], hash) and next if i - DottedErrors.(form.send(dfn[:name])[i], [*prefix, dfn[:name]], hash) and next if i + DottedErrors.(form.send(dfn[:name])[i], [*prefix, dfn[:name]], hash, i) and next if i DottedErrors.(form.send(dfn[:name]), [*prefix, dfn[:name]], hash) end } end + def self.indexed_errors? + @@index_errors + end + + def self.index_errors=(value) + @@index_errors = value + end + + def self.indexed_errors(prefix, hash, k, v, i = nil) + # if no index, means not collection, show the error + if i.nil? + hash[ [*prefix, k].join(".").to_sym] = v + # if it's a collection, index the errors + else + # create an array for collection key + hash[ [*prefix].join(".").to_sym] ||= Array.new + # create hash for index position + hash[ [*prefix].join(".").to_sym][i] ||= Hash.new + # add error for attribute key + hash[ [*prefix].join(".").to_sym][i][k] = v + end + end + def messages(*args) @dotted_errors end diff --git a/test/errors_test.rb b/test/errors_test.rb index 8f4f799d..b9da079f 100644 --- a/test/errors_test.rb +++ b/test/errors_test.rb @@ -104,6 +104,29 @@ def good_musical_taste?(value) end end + describe "indexed errors" do + before { form.validate( + "hit" =>{"title" => ""}, + "title" => "", + "songs" => [{"title" => ""}, {"title" => ""}]) } # FIXME: what happens if item must be filled? + + after { Reform::Contract::Result::Errors.index_errors = false } + + it do + Reform::Contract::Result::Errors.index_errors = true + form.errors.messages.must_equal({ + :title => ["must be filled"], + :"hit.title" => ["must be filled"], + :"songs"=> [ + { title: ["must be filled"] }, + { title: ["must be filled"] } + ], + :"band.label.name"=>["must be filled"] + }) + form.errors.size.must_equal(4) + end + end + describe "#validate with main form invalid" do it do From 51b9be20254ef5d810a6e790f799619e1fb1599b Mon Sep 17 00:00:00 2001 From: Celso Fernandes Date: Thu, 18 Oct 2018 19:48:15 +0200 Subject: [PATCH 2/2] Make implementation compatible with rails 5 --- lib/reform/errors.rb | 10 ++++------ test/errors_test.rb | 8 +++----- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lib/reform/errors.rb b/lib/reform/errors.rb index 227bdd11..8ec55d93 100644 --- a/lib/reform/errors.rb +++ b/lib/reform/errors.rb @@ -45,12 +45,10 @@ def self.indexed_errors(prefix, hash, k, v, i = nil) hash[ [*prefix, k].join(".").to_sym] = v # if it's a collection, index the errors else - # create an array for collection key - hash[ [*prefix].join(".").to_sym] ||= Array.new - # create hash for index position - hash[ [*prefix].join(".").to_sym][i] ||= Hash.new - # add error for attribute key - hash[ [*prefix].join(".").to_sym][i][k] = v + # create attribute prefix with all attributes joined + attribute_prefix = [ *prefix ].join(".") + # then join with index and it's attribute name + hash[ ["#{attribute_prefix}[#{i}]", k].join(".").to_sym] = v end end diff --git a/test/errors_test.rb b/test/errors_test.rb index b9da079f..4e5db01b 100644 --- a/test/errors_test.rb +++ b/test/errors_test.rb @@ -117,13 +117,11 @@ def good_musical_taste?(value) form.errors.messages.must_equal({ :title => ["must be filled"], :"hit.title" => ["must be filled"], - :"songs"=> [ - { title: ["must be filled"] }, - { title: ["must be filled"] } - ], + :"songs[0].title"=> ["must be filled"], + :"songs[1].title"=> ["must be filled"], :"band.label.name"=>["must be filled"] }) - form.errors.size.must_equal(4) + form.errors.size.must_equal(5) end end