Commit fb8826d

mo <mo.khan@gmail.com>
2019-01-07 21:23:12
define dynamic modules instead of using method_missing
1 parent a1db51d
Changed files (3)
lib/scim/kit/v2/attributable.rb
@@ -8,27 +8,27 @@ module Scim
         attr_reader :dynamic_attributes
 
         def define_attributes_for(types)
-          @dynamic_attributes = Hash[
-            types.map do |x|
-              [x.name.underscore, Attribute.new(type: x)]
-            end
-          ].with_indifferent_access
+          @dynamic_attributes = {}.with_indifferent_access
+          types.each do |type|
+            dynamic_attributes[type.name.underscore] = Attribute.new(type: type)
+            self.extend(create_module_for(type))
+          end
         end
 
-        def method_missing(method, *args)
-          if method.match?(/=/)
-            target = method.to_s.delete('=')
-            return super unless respond_to_missing?(target)
+        private
 
-            @dynamic_attributes[target].value = args[0]
-          else
-            attribute = @dynamic_attributes[method]
-            attribute.type.complex? ? attribute : attribute.value
-          end
-        end
+        def create_module_for(type)
+          name = type.name.underscore.to_sym
+          Module.new do
+            define_method(name) do |*args, &block|
+              attribute = dynamic_attributes[name]
+              attribute.type.complex? ? attribute : attribute.value
+            end
 
-        def respond_to_missing?(method, _include_private = false)
-          @dynamic_attributes.key?(method) || super
+            define_method("#{name}=") do |*args, &block|
+              dynamic_attributes[name].value = args[0]
+            end
+          end
         end
       end
     end
spec/scim/kit/v2/attribute_spec.rb
@@ -155,7 +155,6 @@ RSpec.describe Scim::Kit::V2::Attribute do
     before do
       subject.family_name = 'Garrett'
       subject.given_name = 'Tsuyoshi'
-      puts subject.as_json
     end
 
     specify { expect(subject.family_name).to eql('Garrett') }
@@ -163,4 +162,24 @@ RSpec.describe Scim::Kit::V2::Attribute do
     specify { expect(subject.as_json[:name][:familyName]).to eql('Garrett') }
     specify { expect(subject.as_json[:name][:givenName]).to eql('Tsuyoshi') }
   end
+
+  context "with multi valued complex type" do
+    let(:type) do
+      x = Scim::Kit::V2::AttributeType.new(name: 'emails', type: :complex)
+      x.multi_valued = true
+      x.add_attribute(name: 'value')
+      x.add_attribute(name: 'primary', type: :boolean)
+      x
+    end
+    let(:email) { FFaker::Internet.email }
+    let(:other_email) { FFaker::Internet.email }
+
+    before do
+      subject.emails << { value: email, primary: true }
+      subject.emails << { value: other_email, primary: false }
+    end
+
+    specify { expect(subject.emails).to match_array([{ value: email, primary: true }, { value: other_email, primary: false }]) }
+    specify { expect(subject.as_json[:emails]).to match_array([{ value: email, primary: true }, { value: other_email, primary: false }]) }
+  end
 end
spec/scim/kit/v2/resource_spec.rb
@@ -69,4 +69,22 @@ RSpec.describe Scim::Kit::V2::Resource do
       specify { expect(subject.as_json[:name][:givenName]).to eql('Tsuyoshi') }
     end
   end
+
+  context "with a complex multi valued attribute" do
+    let(:email) { FFaker::Internet.email }
+    let(:other_email) { FFaker::Internet.email }
+
+    before do
+      schema.add_attribute(name: 'emails') do |x|
+        x.multi_valued = true
+        x.add_attribute(name: 'value')
+        x.add_attribute(name: 'primary', type: :boolean)
+      end
+      subject.emails << { value: email, primary: true }
+      subject.emails << { value: other_email, primary: false }
+    end
+
+    specify { expect(subject.emails).to match_array([{ value: email, primary: true }, { value: other_email, primary: false }]) }
+    specify { expect(subject.as_json[:emails]).to match_array([{ value: email, primary: true }, { value: other_email, primary: false }]) }
+  end
 end