blob: d8145b6f478b1f024f9f02781aea2dcb36901424 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
|
# frozen_string_literal: true
module Scim
module Kit
module V2
# Represents a dynamic attribute that corresponds to a SCIM type
module Attributable
include Enumerable
# Returns a hash of the generated dynamic attributes
# @return [Hash] the dynamic attributes keys by their name
def dynamic_attributes
@dynamic_attributes ||= {}.with_indifferent_access
end
# Defines dynamic attributes on the resource for the types provided
# @param resource [Scim::Kit::V2::Resource] the resource to attach dynamic attributes to.
# @param types [Array<Scim::Kit::V2::AttributeType>] the array of types
def define_attributes_for(resource, types)
types.each { |x| attribute(x, resource) }
end
# Assigns attribute values via the provided hash.
# @param attributes [Hash] The name/values to assign.
def assign_attributes(attributes = {})
attributes.each do |key, value|
next if key.to_sym == :schemas
if key.to_s.start_with?(Schemas::EXTENSION)
assign_attributes(value)
else
write_attribute(key, value)
end
end
end
# Returns the attribute identified by the name.
# @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] ||
dynamic_attributes[name] ||
UnknownAttribute.new(name)
end
# Returns the value associated with the attribute name
# @param name [String] the name of the attribute
# @return [Object] the value assigned to the attribute
def read_attribute(name)
attribute = attribute_for(name)
return attribute._value if attribute._type.multi_valued
attribute._type.complex? ? attribute : attribute._value
end
# Assigns the value to the attribute with the given name
# @param name [String] the name of the attribute
# @param value [Object] the value to assign to the attribute
def write_attribute(name, value)
if value.is_a?(Hash)
attribute_for(name)&.assign_attributes(value)
else
attribute_for(name)._value = value
end
end
# yields each attribute to the provided block
# @param [Block] the block to yield each attribute to.
def each(&block)
dynamic_attributes.each_value(&block)
end
private
def create_module_for(type)
name = type.name.to_sym
Module.new do
define_method(name) do |*_args|
read_attribute(name)
end
define_method("#{name}=") do |*args|
write_attribute(name, args[0])
end
end
end
def attribute(type, resource)
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
end
end
|