Comparing changes

v0.7.0 v0.7.1
20 commits 8 files changed

Commits

8fbcb1e chore: update publish date mo khan 2022-12-12 17:02:40
6c0c4c4 chore(deps-dev): bump rspec from 3.11.0 to 3.12.0 dependabot[bot] 2022-12-09 18:33:32
7e268d9 refactor: remove schema attr mo khan 2022-12-09 18:26:22
673edf2 chore: bump version mo khan 2022-12-09 18:20:22
a0ae126 style: fix linter errors mo khan 2022-12-09 17:50:32
0a7918b style: fix linter errors mo khan 2022-12-09 17:49:53
9a08d3c chore: update nokogiri to 1.13.10 mo khan 2022-12-09 17:45:52
78a9afe refactor: remove duplication mo khan 2022-12-09 17:30:17
d665835 fix: check for duplicate attribute name mo khan 2022-12-09 17:27:00
e72e7ea style fix Kamal Mahyuddin 2022-11-16 23:30:02
07b4ca4 Add support for "duplicate" attribute names Kamal Mahyuddin 2022-11-16 23:16:32
lib/scim/kit/v2/templates/resource.json.jbuilder
@@ -18,7 +18,8 @@ schemas.each do |schema|
   else
     json.set! schema.id do
       schema.attributes.each do |type|
-        attribute = dynamic_attributes[type.name]
+        attribute = dynamic_attributes[type.fully_qualified_name] ||
+                    dynamic_attributes[type.name]
         render attribute, json: json
       end
     end
lib/scim/kit/v2/attributable.rb
@@ -38,7 +38,9 @@ module Scim
         # @param name [String] the name of the attribute to return
         # @return [Scim::Kit::V2::Attribute] the attribute or {Scim::Kit::V2::UnknownAttribute}
         def attribute_for(name)
-          dynamic_attributes[name.to_s.underscore] || UnknownAttribute.new(name)
+          dynamic_attributes[name.to_s.underscore] ||
+            dynamic_attributes[name] ||
+            UnknownAttribute.new(name)
         end
 
         # Returns the value associated with the attribute name
@@ -86,11 +88,10 @@ module Scim
         end
 
         def attribute(type, resource)
-          dynamic_attributes[type.name] = Attribute.new(
-            type: type,
-            resource: resource
-          )
-          extend(create_module_for(type))
+          previously_defined = dynamic_attributes.key?(type.name)
+          dynamic_attributes[previously_defined ? type.fully_qualified_name : type.name] =
+            Attribute.new(type: type, resource: resource)
+          extend(create_module_for(type)) unless previously_defined
         end
       end
     end
lib/scim/kit/v2/attribute_type.rb
@@ -8,16 +8,15 @@ module Scim
         include Templatable
         attr_accessor :canonical_values, :case_exact, :description
         attr_accessor :multi_valued, :required
-        attr_reader :mutability, :name, :type, :attributes
+        attr_reader :mutability, :name, :fully_qualified_name, :type, :attributes
         attr_reader :reference_types, :returned, :uniqueness
 
-        def initialize(name:, type: :string)
+        def initialize(name:, type: :string, schema: nil)
           @name = name.to_s.underscore
+          @fully_qualified_name = [schema&.id, @name].compact.join('#')
           @type = DATATYPES[type.to_sym] ? type.to_sym : (raise TYPE_ERROR)
           @description = name.to_s.camelize(:lower)
-          @multi_valued = false
-          @required = false
-          @case_exact = false
+          @multi_valued = @required = @case_exact = false
           @mutability = Mutability::READ_WRITE
           @returned = Returned::DEFAULT
           @uniqueness = Uniqueness::NONE
lib/scim/kit/v2/schema.rb
@@ -21,7 +21,7 @@ module Scim
         end
 
         def add_attribute(name:, type: :string)
-          attribute = AttributeType.new(name: name, type: type)
+          attribute = AttributeType.new(name: name, type: type, schema: self)
           yield attribute if block_given?
           attributes << attribute
         end
lib/scim/kit/version.rb
@@ -2,6 +2,6 @@
 
 module Scim
   module Kit
-    VERSION = '0.7.0'
+    VERSION = '0.7.1'
   end
 end
spec/scim/kit/v2/resource_spec.rb
@@ -176,14 +176,33 @@ RSpec.describe Scim::Kit::V2::Resource do
     before do
       schema.add_attribute(name: :country)
       extension.add_attribute(name: :province)
-      subject.country = 'canada'
-      subject.province = 'alberta'
     end
 
-    specify { expect(subject.country).to eql('canada') }
-    specify { expect(subject.province).to eql('alberta') }
-    specify { expect(subject.as_json[:country]).to eql('canada') }
-    specify { expect(subject.as_json[extension_id][:province]).to eql('alberta') }
+    context 'without any collisions' do
+      before do
+        subject.country = 'canada'
+        subject.province = 'alberta'
+      end
+
+      specify { expect(subject.country).to eql('canada') }
+      specify { expect(subject.province).to eql('alberta') }
+      specify { expect(subject.as_json[:country]).to eql('canada') }
+      specify { expect(subject.as_json[extension_id][:province]).to eql('alberta') }
+    end
+
+    context 'with an extension attribute with the same name as a core attribute' do
+      before do
+        extension.add_attribute(name: :country)
+
+        subject.country = 'canada'
+        subject.write_attribute("#{extension_id}#country", 'usa')
+      end
+
+      specify { expect(subject.country).to eql('canada') }
+      specify { expect(subject.read_attribute("#{extension_id}#country")).to eql('usa') }
+      specify { expect(subject.as_json[:country]).to eql('canada') }
+      specify { expect(subject.as_json[extension_id][:country]).to eql('usa') }
+    end
   end
 
   describe '#valid?' do
CHANGELOG.md
@@ -1,4 +1,4 @@
-Version 0.7.0
+Version 0.7.1
 
 # Changelog
 All notable changes to this project will be documented in this file.
@@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ## [Unreleased]
 
+## [0.7.1] - 2022-12-12
+### Fixed
+- Add support for duplicate attribute names
+
 ## [0.7.0] - 2022-09-28
 ### Added
 - Add constant for 'urn:ietf:params:scim:api:messages:2.0:BulkRequest' [RFC-7644](https://www.rfc-editor.org/rfc/rfc7644.html#section-3.7)
@@ -15,7 +19,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - Add constant for 'urn:ietf:params:scim:api:messages:2.0:PatchOp' [RFC-7644](https://www.rfc-editor.org/rfc/rfc7644.html#section-3.5.2)
 - Add constant for 'urn:ietf:params:scim:schemas:core:2.0:Schema' [RFC-7643](https://www.rfc-editor.org/rfc/rfc7643.html#section-7)
 
-
 ## [0.6.0] - 2022-05-23
 ### Added
 - Add support for Ruby 3.1
@@ -82,7 +85,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 - \_assign does not coerce values by default.
 - errors are merged together instead of overwritten during attribute validation.
 
-[Unreleased]: https://github.com/xlgmokha/scim-kit/compare/v0.7.0...HEAD
+[Unreleased]: https://github.com/xlgmokha/scim-kit/compare/v0.7.1...HEAD
+[0.7.1]: https://github.com/xlgmokha/scim-kit/compare/v0.7.0...v0.7.1
 [0.7.0]: https://github.com/xlgmokha/scim-kit/compare/v0.6.0...v0.7.0
 [0.6.0]: https://github.com/xlgmokha/scim-kit/compare/v0.5.3...v0.6.0
 [0.5.3]: https://github.com/xlgmokha/scim-kit/compare/v0.5.2...v0.5.3
Gemfile.lock
@@ -1,7 +1,7 @@
 PATH
   remote: .
   specs:
-    scim-kit (0.7.0)
+    scim-kit (0.7.1)
       activemodel (>= 6.1, < 8.0)
       net-hippie (~> 1.0)
       parslet (~> 2.0)
@@ -50,10 +50,10 @@ GEM
     mini_portile2 (2.8.0)
     minitest (5.16.3)
     net-hippie (1.1.1)
-    nokogiri (1.13.8)
+    nokogiri (1.13.10)
       mini_portile2 (~> 2.8.0)
       racc (~> 1.4)
-    nokogiri (1.13.8-x86_64-linux)
+    nokogiri (1.13.10-x86_64-linux)
       racc (~> 1.4)
     parallel (1.21.0)
     parser (3.1.0.0)
@@ -70,19 +70,19 @@ GEM
     rake (13.0.6)
     regexp_parser (2.2.0)
     rexml (3.2.5)
-    rspec (3.11.0)
-      rspec-core (~> 3.11.0)
-      rspec-expectations (~> 3.11.0)
-      rspec-mocks (~> 3.11.0)
-    rspec-core (3.11.0)
-      rspec-support (~> 3.11.0)
-    rspec-expectations (3.11.0)
+    rspec (3.12.0)
+      rspec-core (~> 3.12.0)
+      rspec-expectations (~> 3.12.0)
+      rspec-mocks (~> 3.12.0)
+    rspec-core (3.12.0)
+      rspec-support (~> 3.12.0)
+    rspec-expectations (3.12.0)
       diff-lcs (>= 1.2.0, < 2.0)
-      rspec-support (~> 3.11.0)
-    rspec-mocks (3.11.0)
+      rspec-support (~> 3.12.0)
+    rspec-mocks (3.12.0)
       diff-lcs (>= 1.2.0, < 2.0)
-      rspec-support (~> 3.11.0)
-    rspec-support (3.11.0)
+      rspec-support (~> 3.12.0)
+    rspec-support (3.12.0)
     rubocop (0.93.1)
       parallel (~> 1.10)
       parser (>= 2.7.1.5)