Class: ActiveFedora::MetadataDatastream

Inherits:
Datastream show all
Includes:
MetadataDatastreamHelper
Defined in:
lib/active_fedora/metadata_datastream.rb

Overview

this class represents a MetadataDatastream, a special case of ActiveFedora::Datastream

Direct Known Subclasses

QualifiedDublinCoreDatastream

Instance Attribute Summary

Attributes included from MetadataDatastreamHelper

#fields

Attributes inherited from Datastream

#dirty, #fields, #last_modified

Attributes inherited from Fedora::Datastream

#mime_type

Attributes inherited from Fedora::BaseObject

#attributes, #blob, #errors, #new_object, #uri

Class Method Summary collapse

Instance Method Summary collapse

Methods included from MetadataDatastreamHelper

included, #initialize, #save, #set_blob_for_save, #to_solr, #to_xml

Methods inherited from Datastream

#after_save, #before_save, #check_concurrency, #content, #content=, delete, #delete, #dirty?, #dsid=, #initialize, #last_modified_in_repository, #pid, #pid=, #save, #to_param

Methods inherited from Fedora::Datastream

#control_group, #control_group=, #dsid, #initialize, #label, #label=, #pid, #uri, #url

Methods inherited from Fedora::BaseObject

#[], #initialize, #new_object?

Class Method Details

.from_xml(tmpl, node) ⇒ Object



115
116
117
118
119
120
121
# File 'lib/active_fedora/metadata_datastream.rb', line 115

def self.from_xml(tmpl, node) # :nodoc:
  node.xpath("./foxml:datastreamVersion[last()]/foxml:xmlContent/fields/node()").each do |f|
      tmpl.send("#{f.name}_append", f.text) unless f.class == Nokogiri::XML::Text
  end
  tmpl.send(:dirty=, false)
  tmpl
end

Instance Method Details

#field(name, tupe, opts = {}) ⇒ Object

This method generates the various accessor and mutator methods on self for the datastream metadata attributes. each field will have the 3 magic methods:

name_values=(arg) 
name_values 
name_append(arg)

Calling any of the generated methods marks self as dirty.

‘tupe’ is a datatype, currently :string, :text and :date are supported.

opts is an options hash, which will affect the generation of the xml representation of this datastream.

Currently supported modifiers: For QualifiedDublinCorDatastreams:

:element_attrs =>{:foo=>:bar} -  hash of xml element attributes
:xml_node => :nodename  - The xml node to be used to represent this object (in dcterms namespace)
:encoding=>foo, or encodings_scheme  - causes an xsi:type attribute to be set to 'foo'
:multiple=>true -  mark this field as a multivalue field (on by default)

At some point, these modifiers will be ported up to work for any ActiveFedora::MetadataDatastream.

There is quite a good example of this class in use in spec/examples/oral_history.rb

!! Careful: If you declare two fields that correspond to the same xml node without any qualifiers to differentiate them, you will end up replicating the values in the underlying datastream, resulting in mysterious dubling, quadrupling, etc. whenever you edit the field’s values.



150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/active_fedora/metadata_datastream.rb', line 150

def field(name, tupe, opts={})
  @fields[name.to_s.to_sym]={:type=>tupe, :values=>[]}.merge(opts)
  eval <<-EOS
    def #{name}_values=(arg)
      @fields["#{name.to_s}".to_sym][:values]=[arg].flatten
      self.dirty=true
    end
    def #{name}_values
      @fields["#{name}".to_sym][:values]
    end
    def #{name}_append(arg)
      @fields["#{name}".to_sym][:values] << arg
      self.dirty =true
    end
  EOS
end

#get_values(field_name, default = []) ⇒ Object



87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/active_fedora/metadata_datastream.rb', line 87

def get_values(field_name, default=[])
  field_accessor_method = "#{field_name}_values"
  if respond_to? field_accessor_method
    values = self.send(field_accessor_method)
  else
    values = []
  end
  if values.empty?
    if default.nil?
      return default
    else
      return default
    end
  else
    return values
  end
end

#set_value(field_name, values) ⇒ Object



105
106
107
108
109
110
111
# File 'lib/active_fedora/metadata_datastream.rb', line 105

def set_value(field_name, values)
  field_accessor_method = "#{field_name}_values="
  if respond_to? field_accessor_method
    values = self.send(field_accessor_method, values)
    return self.send("#{field_name}_values")
  end
end

#update_attributes(params = {}, opts = {}) ⇒ Object



10
11
12
13
14
15
16
17
18
19
20
21
22
23
# File 'lib/active_fedora/metadata_datastream.rb', line 10

def update_attributes(params={},opts={})
  result = params.dup
  params.each do |k,v|
    if v == :delete || v == "" || v == nil
      v = []
    end
    if self.fields.has_key?(k.to_sym)
      result[k] = set_value(k, v)
    else
      result.delete(k)
    end
  end
  return result
end

#update_indexed_attributes(params = {}, opts = {}) ⇒ Object

An ActiveRecord-ism to udpate metadata values.

The passed in hash must look like this :

{:name=>{"0"=>"a","1"=>"b"}}

This will attempt to set the values for any field named fubar in the datastream. If there is no field by that name, it returns an empty hash and doesn’t change the object at all. If there is a field by that name, it will set the values for field of name :name having the value [a,b] and it returns a hash with the field name, value index, and the value as it was set.

An index of -1 will insert a new value. any existing value at the relevant index will be overwritten.

As in update_attributes, this overwrites all available fields by default.

Example Usage:

ds.update_attributes(:myfield=>{“0”=>“a”,“1”=>“b”,:myotherfield=>“-1”=>“c”})



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
# File 'lib/active_fedora/metadata_datastream.rb', line 44

def update_indexed_attributes(params={}, opts={})
  # remove any fields from params that this datastream doesn't recognize
  params.delete_if {|field_name,new_values| !self.fields.include?(field_name.to_sym) }
  
  result = params.dup
  params.each do |field_name,new_values|
    field_accessor_method = "#{field_name}_values"
    
    if new_values.kind_of?(Hash)
        result[field_name] = new_values.dup
  
        current_values = instance_eval(field_accessor_method)
    
        # current_values = get_values(field_name) # for some reason this leaves current_values unset?
            
        new_values.delete_if do |y,z| 
          if current_values[y.to_i] and y.to_i > -1
            current_values[y.to_i]=z
            true
          else
            false
          end
        end 
    
        new_values.each do |y,z| 
          result[field_name].delete(y)
          current_values<<z #just append everything left
          new_array_index = current_values.length - 1
          result[field_name][new_array_index.to_s] = z
        end
        current_values.delete_if {|x| x == :delete || x == "" || x == nil}
        #set_value(field_name, current_values)
        instance_eval("#{field_accessor_method}=(current_values)") #write it back to the ds
        # result[field_name].delete("-1")
    else
      values = instance_eval("#{field_name}_values=(new_values)")
      result[field_name] = {"0"=>values}           
    end
  end
  return result
end