Module: Essential::Resource::AttrRelations
- Included in:
- Essential::Resource::AttrMethods::ClassMethods
- Defined in:
- lib/essential/resource/attr_relations.rb
Instance Method Summary collapse
-
#attr_relation(pairs) ⇒ Object
Method for defining a mapping between a ‘sid` property and a Class.
Instance Method Details
#attr_relation(pairs) ⇒ Object
Method for defining a mapping between a ‘sid` property and a Class.
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 |
# File 'lib/essential/resource/attr_relations.rb', line 7 def attr_relation(pairs) pairs.each do |method, resource| sid_method = method.to_sym # Enforces that we're dealing with a `sid` property. if method =~ /\A(.+)_sid\Z/ method = $1.to_sym else raise ArgumentError, 'attribute must end in _sid' end unless method_defined?(sid_method) # perhaps we didn't explicitly define access to the sid - do so now. attr_property sid_method end # Avoid circular load dependencies: # # `resource` might be a Class, or it might be a String. # # If it is a String, we'll attempt to turn it into a CLass. # This will be done once - the first time it is accessed - # to allow both classes to load completely before constantizing # the String. my_lazy_resource = format('lazy_%s_resource', method).to_sym my_lazy_variable = format('@%s', my_lazy_resource).to_sym define_singleton_method(my_lazy_resource) do # only resolve this resource once lazy_resource = instance_variable_get(my_lazy_variable) unless lazy_resource lazy_resource = resource case lazy_resource when String if lazy_resource.include?('::') # this appears to be a fully-namespaced Resource lazy_resource = lazy_resource.split('::') else # no namespace - assume it's part of the current class. namespace = self.name.split('::') namespace.pop namespace << lazy_resource lazy_resource = namespace end # fetch each module in turn lazy_resource = lazy_resource.reduce(Object) {|o,c| o.const_get c} end # now that we have a class, ensure it is *actually* a Resource! unless lazy_resource < Essential::Resource raise ArgumentError, format('mapping must be an %s', Essential::Resource.name) end # cache it. instance_variable_set(my_lazy_variable, lazy_resource) end lazy_resource end define_method(method) do sid = send(sid_method) if sid.nil? nil else self.class.send(my_lazy_resource).new(sid: sid, headers: @headers) end end end end |