Commit 8948ea8
Changed files (7)
lib
scim
kit
spec
scim
lib/scim/kit/v2/templates/attribute.json.jbuilder
@@ -1,12 +1,12 @@
# frozen_string_literal: true
json.key_format! camelize: :lower
-if type.complex?
+if type.complex? && !type.multi_valued
json.set! type.name do
dynamic_attributes.values.each do |attribute|
render attribute, json: json
end
end
else
- json.set! type.name, value
+ json.set! type.name, _value
end
lib/scim/kit/v2/attributable.rb
@@ -11,22 +11,28 @@ module Scim
@dynamic_attributes = {}.with_indifferent_access
types.each do |type|
dynamic_attributes[type.name.underscore] = Attribute.new(type: type)
- self.extend(create_module_for(type))
+ extend(create_module_for(type))
end
end
private
+ def attribute_for(name)
+ dynamic_attributes[name]
+ 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
+ define_method(name) do |*_args|
+ attribute = attribute_for(name)
+ return attribute._value if attribute.type.multi_valued
+
+ attribute.type.complex? ? attribute : attribute._value
end
- define_method("#{name}=") do |*args, &block|
- dynamic_attributes[name].value = args[0]
+ define_method("#{name}=") do |*args|
+ attribute_for(name)._value = args[0]
end
end
end
lib/scim/kit/v2/attribute.rb
@@ -8,16 +8,16 @@ module Scim
include Attributable
include Templatable
attr_reader :type
- attr_reader :value
+ attr_reader :_value
def initialize(type:, value: nil)
@type = type
- @value = value
+ @_value = value
define_attributes_for(type.attributes)
end
- def value=(new_value)
- @value = type.coerce(new_value)
+ def _value=(new_value)
+ @_value = type.coerce(new_value)
if type.canonical_values &&
!type.canonical_values.empty? &&
lib/scim/kit/v2/attribute_type.rb
@@ -60,9 +60,9 @@ module Scim
end
def add_attribute(name:, type: :string)
- @type = :complex
attribute = AttributeType.new(name: name, type: type)
yield attribute if block_given?
+ @type = :complex
attributes << attribute
end
@@ -83,6 +83,7 @@ module Scim
if type_is?(:boolean) && ![true, false].include?(value)
raise ArgumentError, value
end
+ return value if multi_valued
coercion = COERCION[type]
coercion ? coercion.call(value) : value
lib/scim/kit/v2/schema.rb
@@ -20,7 +20,7 @@ module Scim
def add_attribute(name:, type: :string)
attribute = AttributeType.new(name: name, type: type)
yield attribute if block_given?
- @attributes << attribute
+ attributes << attribute
end
def self.build(*args)
spec/scim/kit/v2/attribute_spec.rb
@@ -9,41 +9,50 @@ RSpec.describe Scim::Kit::V2::Attribute do
context 'when valid' do
let(:user_name) { FFaker::Internet.user_name }
- before { subject.value = user_name }
+ before { subject._value = user_name }
- specify { expect(subject.value).to eql(user_name) }
+ specify { expect(subject._value).to eql(user_name) }
specify { expect(subject.as_json[:userName]).to eql(user_name) }
end
+ context 'when multiple values are allowed' do
+ before do
+ type.multi_valued = true
+ subject._value = %w[superman batman]
+ end
+
+ specify { expect(subject._value).to match_array(%w[superman batman]) }
+ end
+
context 'when integer' do
let(:number) { rand(100) }
- before { subject.value = number }
+ before { subject._value = number }
- specify { expect(subject.value).to eql(number.to_s) }
+ specify { expect(subject._value).to eql(number.to_s) }
end
context 'when datetime' do
let(:datetime) { DateTime.now }
- before { subject.value = datetime }
+ before { subject._value = datetime }
- specify { expect(subject.value).to eql(datetime.to_s) }
+ specify { expect(subject._value).to eql(datetime.to_s) }
end
context 'when not matching a canonical value' do
before { type.canonical_values = %w[batman robin] }
- specify { expect { subject.value = 'spider man' }.to raise_error(ArgumentError) }
+ specify { expect { subject._value = 'spider man' }.to raise_error(ArgumentError) }
end
context 'when canonical value is given' do
before do
type.canonical_values = %w[batman robin]
- subject.value = 'batman'
+ subject._value = 'batman'
end
- specify { expect(subject.value).to eql('batman') }
+ specify { expect(subject._value).to eql('batman') }
end
end
@@ -51,21 +60,21 @@ RSpec.describe Scim::Kit::V2::Attribute do
let(:type) { Scim::Kit::V2::AttributeType.new(name: 'hungry', type: :boolean) }
context 'when true' do
- before { subject.value = true }
+ before { subject._value = true }
- specify { expect(subject.value).to be(true) }
+ specify { expect(subject._value).to be(true) }
specify { expect(subject.as_json[:hungry]).to be(true) }
end
context 'when false' do
- before { subject.value = false }
+ before { subject._value = false }
- specify { expect(subject.value).to be(false) }
+ specify { expect(subject._value).to be(false) }
specify { expect(subject.as_json[:hungry]).to be(false) }
end
context 'when string' do
- specify { expect { subject.value = 'hello' }.to raise_error(ArgumentError) }
+ specify { expect { subject._value = 'hello' }.to raise_error(ArgumentError) }
end
end
@@ -73,16 +82,16 @@ RSpec.describe Scim::Kit::V2::Attribute do
let(:type) { Scim::Kit::V2::AttributeType.new(name: 'measurement', type: :decimal) }
context 'when given float' do
- before { subject.value = Math::PI }
+ before { subject._value = Math::PI }
- specify { expect(subject.value).to eql(Math::PI) }
+ specify { expect(subject._value).to eql(Math::PI) }
specify { expect(subject.as_json[:measurement]).to be(Math::PI) }
end
context 'when given an integer' do
- before { subject.value = 42 }
+ before { subject._value = 42 }
- specify { expect(subject.value).to eql(42.to_f) }
+ specify { expect(subject._value).to eql(42.to_f) }
specify { expect(subject.as_json[:measurement]).to be(42.to_f) }
end
end
@@ -91,16 +100,16 @@ RSpec.describe Scim::Kit::V2::Attribute do
let(:type) { Scim::Kit::V2::AttributeType.new(name: 'age', type: :integer) }
context 'when given integer' do
- before { subject.value = 34 }
+ before { subject._value = 34 }
- specify { expect(subject.value).to be(34) }
+ specify { expect(subject._value).to be(34) }
specify { expect(subject.as_json[:age]).to be(34) }
end
context 'when given float' do
- before { subject.value = Math::PI }
+ before { subject._value = Math::PI }
- specify { expect(subject.value).to eql(Math::PI.to_i) }
+ specify { expect(subject._value).to eql(Math::PI.to_i) }
end
end
@@ -109,16 +118,16 @@ RSpec.describe Scim::Kit::V2::Attribute do
let(:datetime) { DateTime.new(2019, 0o1, 0o6, 12, 35, 0o0) }
context 'when given a date time' do
- before { subject.value = datetime }
+ before { subject._value = datetime }
- specify { expect(subject.value).to eql(datetime) }
+ specify { expect(subject._value).to eql(datetime) }
specify { expect(subject.as_json[:birthdate]).to eql(datetime.iso8601) }
end
context 'when given a string' do
- before { subject.value = datetime.to_s }
+ before { subject._value = datetime.to_s }
- specify { expect(subject.value).to eql(datetime) }
+ specify { expect(subject._value).to eql(datetime) }
end
end
@@ -127,9 +136,9 @@ RSpec.describe Scim::Kit::V2::Attribute do
let(:photo) { IO.read('./spec/fixtures/avatar.png', mode: 'rb') }
context 'when given a .png' do
- before { subject.value = photo }
+ before { subject._value = photo }
- specify { expect(subject.value).to eql(Base64.strict_encode64(photo)) }
+ specify { expect(subject._value).to eql(Base64.strict_encode64(photo)) }
specify { expect(subject.as_json[:photo]).to eql(Base64.strict_encode64(photo)) }
end
end
@@ -138,9 +147,9 @@ RSpec.describe Scim::Kit::V2::Attribute do
let(:type) { Scim::Kit::V2::AttributeType.new(name: 'group', type: :reference) }
let(:uri) { FFaker::Internet.uri('https') }
- before { subject.value = uri }
+ before { subject._value = uri }
- specify { expect(subject.value).to eql(uri) }
+ specify { expect(subject._value).to eql(uri) }
specify { expect(subject.as_json[:group]).to eql(uri) }
end
@@ -163,7 +172,7 @@ RSpec.describe Scim::Kit::V2::Attribute do
specify { expect(subject.as_json[:name][:givenName]).to eql('Tsuyoshi') }
end
- context "with multi valued complex type" do
+ context 'with multi valued complex type' do
let(:type) do
x = Scim::Kit::V2::AttributeType.new(name: 'emails', type: :complex)
x.multi_valued = true
@@ -175,11 +184,13 @@ RSpec.describe Scim::Kit::V2::Attribute do
let(:other_email) { FFaker::Internet.email }
before do
- subject.emails << { value: email, primary: true }
- subject.emails << { value: other_email, primary: false }
+ subject._value = [
+ { value: email, primary: true },
+ { 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._value).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
@@ -70,18 +70,20 @@ RSpec.describe Scim::Kit::V2::Resource do
end
end
- context "with a complex multi valued attribute" do
+ 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|
+ schema.add_attribute(name: 'emails', type: :complex) 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 }
+ subject.emails = [
+ { value: email, primary: true },
+ { value: other_email, primary: false }
+ ]
end
specify { expect(subject.emails).to match_array([{ value: email, primary: true }, { value: other_email, primary: false }]) }