From 5a7d27e0c58510458af3894783649d53529753cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johannes=20M=C3=BCller?= Date: Wed, 13 Oct 2021 01:51:53 +0200 Subject: [PATCH] Improve DB::MappingException usage (#129) --- spec/serializable_spec.cr | 6 +++--- src/db/error.cr | 13 +++++++++++++ src/db/mapping.cr | 4 ++-- src/db/serializable.cr | 26 +++++++++++++++----------- 4 files changed, 33 insertions(+), 16 deletions(-) diff --git a/spec/serializable_spec.cr b/spec/serializable_spec.cr index 1a43576..bf2b2d8 100644 --- a/spec/serializable_spec.cr +++ b/spec/serializable_spec.cr @@ -105,19 +105,19 @@ describe "DB::Serializable" do end it "should fail to initialize a simple model if types do not match" do - expect_raises ArgumentError do + expect_raises DB::MappingException, "Invalid Int32: b\n deserializing SimpleModel#c0" do from_dummy("b,a", SimpleModel) end end it "should fail to initialize a simple model if there is a missing column" do - expect_raises DB::MappingException do + expect_raises DB::MappingException, "Missing column c1\n deserializing SimpleModel#c1" do from_dummy("1", SimpleModel) end end it "should fail to initialize a simple model if there is an unexpected column" do - expect_raises DB::MappingException do + expect_raises DB::MappingException, "Unknown column: c2\n deserializing SimpleModel" do from_dummy("1,a,b", SimpleModel) end end diff --git a/src/db/error.cr b/src/db/error.cr index 6e072c9..ad775fc 100644 --- a/src/db/error.cr +++ b/src/db/error.cr @@ -6,6 +6,19 @@ module DB end class MappingException < Error + getter klass + getter property + + def initialize(message, @klass : String, @property : String? = nil, cause : Exception? = nil) + message = String.build do |io| + io << message + io << "\n deserializing " << @klass + if property = @property + io << "#" << property + end + end + super(message, cause: cause) + end end class PoolTimeout < Error diff --git a/src/db/mapping.cr b/src/db/mapping.cr index b6e7ed7..8c07499 100644 --- a/src/db/mapping.cr +++ b/src/db/mapping.cr @@ -117,7 +117,7 @@ module DB {% end %} else {% if strict %} - raise ::DB::MappingException.new("unknown result set attribute: #{col_name}") + raise ::DB::MappingException.new("unknown result set attribute: #{col_name}", self.class.to_s) {% else %} %rs.read {% end %} @@ -127,7 +127,7 @@ module DB {% for key, value in properties %} {% unless value[:nilable] || value[:default] != nil %} if %var{key.id}.is_a?(Nil) && !%found{key.id} - raise ::DB::MappingException.new("missing result set attribute: {{(value[:key] || key).id}}") + raise ::DB::MappingException.new("missing result set attribute: {{(value[:key] || key).id}}", self.class.to_s) end {% end %} {% end %} diff --git a/src/db/serializable.cr b/src/db/serializable.cr index 38c3b88..ce92ca6 100644 --- a/src/db/serializable.cr +++ b/src/db/serializable.cr @@ -129,14 +129,18 @@ module DB {% for name, value in properties %} when {{value[:key]}} %found{name} = true - %var{name} = - {% if value[:converter] %} - {{value[:converter]}}.from_rs(rs) - {% elsif value[:nilable] || value[:default] != nil %} - rs.read(::Union({{value[:type]}} | Nil)) - {% else %} - rs.read({{value[:type]}}) - {% end %} + begin + %var{name} = + {% if value[:converter] %} + {{value[:converter]}}.from_rs(rs) + {% elsif value[:nilable] || value[:default] != nil %} + rs.read(::Union({{value[:type]}} | Nil)) + {% else %} + rs.read({{value[:type]}}) + {% end %} + rescue exc + ::raise ::DB::MappingException.new(exc.message, self.class.to_s, {{name.stringify}}, cause: exc) + end {% end %} else rs.read # Advance set, but discard result @@ -146,8 +150,8 @@ module DB {% for key, value in properties %} {% unless value[:nilable] || value[:default] != nil %} - if %var{key}.is_a?(Nil) && !%found{key} - raise ::DB::MappingException.new("missing result set attribute: {{(value[:key] || key).id}}") + if %var{key}.nil? && !%found{key} + ::raise ::DB::MappingException.new("Missing column {{value[:key].id}}", self.class.to_s, {{key.stringify}}) end {% end %} {% end %} @@ -169,7 +173,7 @@ module DB end protected def on_unknown_db_column(col_name) - raise ::DB::MappingException.new("unknown result set attribute: #{col_name}") + ::raise ::DB::MappingException.new("Unknown column: #{col_name}", self.class.to_s) end module NonStrict