module ActiveFedora
module Delegating
extend ActiveSupport::Concern
module ClassMethods
# Provides a delegate class method to expose methods in metadata streams
# as member of the base object. Pass the target datastream via the
# :to argument. If you want to return a unique result, (e.g. string
# instead of an array) set the :unique argument to true.
#
# The optional :at argument provides a terminology that the delegate will point to.
#
# class Foo < ActiveFedora::Base
# has_metadata :name => "descMetadata", :type => MyDatastream
#
# delegate :field1, :to=>"descMetadata", :unique=>true
# delegate :field2, :to=>"descMetadata", :at=>[:term1, :term2]
# end
#
# foo = Foo.new
# foo.field1 = "My Value"
# foo.field1 # => "My Value"
# foo.field2 # => NoMethodError: undefined method `field2' for #
def delegate(field, args ={})
create_delegate_accessor(field, args)
create_delegate_setter(field, args)
end
# Allows you to delegate multiple terminologies to the same datastream, instead
# having to call the method each time for each term. The target datastream is the
# first argument, followed by an array of the terms that will point to that
# datastream. Terms must be a single value, ie. :field and not [:term1, :term2].
# This is best accomplished by refining your OM terminology using :ref or :proxy
# methods to reduce nested terms down to one.
#
# class Foo < ActiveFedora::Base
# has_metadata :name => "descMetadata", :type => MyDatastream
#
# delegate_to :descMetadata, [:field1, :field2]
# end
#
# foo = Foo.new
# foo.field1 = "My Value"
# foo.field1 # => "My Value"
# foo.field2 # => NoMethodError: undefined method `field2' for #
def delegate_to(datastream,fields,args={})
fields.each do |f|
args.merge!({:to=>datastream})
create_delegate_accessor(f, args)
create_delegate_setter(f, args)
end
end
private
def create_delegate_accessor(field, args)
define_method field do
ds = self.send(args[:to])
val = if ds.kind_of?(ActiveFedora::MetadataDatastream) || ds.kind_of?(ActiveFedora::RDFDatastream)
ds.send(:get_values, field)
else
terminology = args[:at] || [field]
ds.send(:term_values, *terminology)
end
args[:unique] ? val.first : val
end
end
def create_delegate_setter(field, args)
define_method "#{field}=".to_sym do |v|
ds = self.send(args[:to])
if ds.kind_of?(ActiveFedora::MetadataDatastream) || ds.kind_of?(ActiveFedora::RDFDatastream)
ds.send(:set_value, field, v)
else
terminology = args[:at] || [field]
ds.send(:update_indexed_attributes, {terminology => v})
end
end
end
end
end
end