diff --git a/Changelog.md b/Changelog.md index 8594a7c..4d6061c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +## [1.1.1] - 2024-05-21 +### Fixed +- Fixed Definition::Model inheritance + ## [1.1.0] - 2023-11-22 ### Changes - Improved performance diff --git a/Gemfile.lock b/Gemfile.lock index 9eb0e27..d209a7d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - definition (1.1.0) + definition (1.1.1) activesupport i18n diff --git a/lib/definition/model.rb b/lib/definition/model.rb index 5f8a8ef..b92b862 100644 --- a/lib/definition/model.rb +++ b/lib/definition/model.rb @@ -37,7 +37,12 @@ def _define_attr_accessor(key) end def _definition - @_definition ||= ::Definition.Keys {} + @_definition ||= if superclass == ::Definition::Model + ::Definition.Keys {} + else + # Create a deep copy of parent's definition + Marshal.load(Marshal.dump(superclass._definition)) + end end end diff --git a/lib/definition/version.rb b/lib/definition/version.rb index e2c8e4d..50ccecb 100644 --- a/lib/definition/version.rb +++ b/lib/definition/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Definition - VERSION = "1.1.0" + VERSION = "1.1.1" end diff --git a/spec/lib/definition/model_spec.rb b/spec/lib/definition/model_spec.rb index 5d628b7..bade42c 100644 --- a/spec/lib/definition/model_spec.rb +++ b/spec/lib/definition/model_spec.rb @@ -131,6 +131,61 @@ end.to raise_error(Definition::InvalidModelError, /bar/) end end + + context "with inheritance" do + subject(:new) { child_test_model_class.new(**kwargs) } + + let(:child_test_model_class) do + ParentModel = test_model_class + Class.new(ParentModel) do + required :age, Definition.Type(Integer) + optional :phone, Definition.Type(String) + end + end + + context "with required keywords only" do + let(:kwargs) { { name: "John", age: 24 } } + + it "instantiates the model" do + expect(new.name).to eq("John") + expect(new.email).to be_nil + expect(new.age).to eq(24) + expect(new.phone).to be_nil + end + end + + context "with required and optional keywords" do + let(:kwargs) { { name: "John", email: "test@test.com", age: 24, phone: "+4312345" } } + + it "instantiates the model" do + expect(new.name).to eq("John") + expect(new.email).to eq("test@test.com") + expect(new.age).to eq(24) + expect(new.phone).to eq("+4312345") + end + end + + it "throws error when parent's required attributes are missing" do + expect do + child_test_model_class.new(age: 24) + end.to raise_error(Definition::InvalidModelError, /name/) + end + + it "throws error when child's required attributes are missing" do + expect do + child_test_model_class.new(name: "John") + end.to raise_error(Definition::InvalidModelError, /age/) + end + + it "doesn't change parent's defintion" do + expect do + Class.new(test_model_class) do + required :required_child_attribute, Definition.Type(Integer) + optional :optional_child_attribute, Definition.Type(String) + end + end.not_to(change { test_model_class._definition.keys }) + end + end end describe ".to_h" do