Class: ActiveFedora::MetadataDatastream
- Inherits:
-
NokogiriDatastream
- Object
- Rubydora::Datastream
- Datastream
- NokogiriDatastream
- ActiveFedora::MetadataDatastream
- Includes:
- MetadataDatastreamHelper
- Defined in:
- lib/active_fedora/metadata_datastream.rb
Overview
A legacy class that creates and updates simple xml documents For much greater flexibility, use NokogiriDatastream instead.
Instance Attribute Summary
Attributes included from MetadataDatastreamHelper
Attributes inherited from NokogiriDatastream
Attributes inherited from Datastream
#digital_object, #dirty, #fields, #last_modified
Class Method Summary collapse
-
.from_xml(xml, tmpl) ⇒ Object
Populate a MetadataDatastream object based on the “datastream” node from a FOXML file.
Instance Method Summary collapse
-
#field(name, tupe, opts = {}) ⇒ Object
This method generates the various accessor and mutator methods on self for the datastream metadata attributes.
-
#from_solr(solr_doc) ⇒ Object
** EXPERIMENTAL **.
- #get_values(field_name, default = []) ⇒ Object
-
#initialize(digital_object, dsid) ⇒ MetadataDatastream
constructor
A new instance of MetadataDatastream.
- #set_value(field_name, values) ⇒ Object
-
#to_solr(solr_doc = Hash.new) ⇒ Object
:nodoc:.
-
#to_xml(xml = Nokogiri::XML::Document.parse("<fields />")) ⇒ Object
:nodoc:.
- #update_attributes(params = {}, opts = {}) ⇒ Object
-
#update_indexed_attributes(params = {}, opts = {}) ⇒ Object
An ActiveRecord-ism to udpate metadata values.
Methods included from MetadataDatastreamHelper
#ensure_xml_loaded, included, #serialize!
Methods inherited from NokogiriDatastream
#content=, #find_by_terms, #generate_solr_symbol, #get_values_from_solr, #has_solr_name?, #is_hierarchical_term_pointer?, #ng_xml, #ng_xml=, #om_term_values, #om_update_values, #term_values, #update_values, xml_template
Methods inherited from Datastream
#add_ds_location, #add_mime_type, #create, #dirty?, #inspect, #new_object?, #profile_from_hash, #save, #serialize!, #size, #solrize_profile, #to_param, #validate_content_present
Constructor Details
#initialize(digital_object, dsid) ⇒ MetadataDatastream
Returns a new instance of MetadataDatastream.
14 15 16 17 |
# File 'lib/active_fedora/metadata_datastream.rb', line 14 def initialize(digital_object, dsid) ActiveSupport::Deprecation.warn("MetadataDatastream is deprecated and will be removed in a future release. Create a NokogiriDatastream to structure your data") super end |
Class Method Details
.from_xml(xml, tmpl) ⇒ Object
Populate a MetadataDatastream object based on the “datastream” node from a FOXML file
189 190 191 192 193 194 195 196 |
# File 'lib/active_fedora/metadata_datastream.rb', line 189 def self.from_xml(xml, tmpl) # :nodoc: node = Nokogiri::XML::Document.parse(xml) node.xpath("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.
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/active_fedora/metadata_datastream.rb', line 248 def field(name, tupe, opts={}) #TODO add term to terminology @fields[name.to_s.to_sym]={:type=>tupe, :values=>[]}.merge(opts) #eval <<-EOS (class << self; self; end).class_eval do define_method "#{name}_values=".to_sym do |arg| ensure_xml_loaded @fields["#{name.to_s}".to_sym][:values]=[arg].flatten self.dirty=true end define_method "#{name}_values".to_sym do ensure_xml_loaded @fields["#{name}".to_sym][:values] end define_method "#{name}_append".to_sym do |arg| ensure_xml_loaded @fields["#{name}".to_sym][:values] << arg self.dirty =true end end end |
#from_solr(solr_doc) ⇒ Object
** EXPERIMENTAL **
This is utilized by ActiveFedora::Base.load_instance_from_solr to set metadata values in this object using the Solr document passed in. Any keys in the solr document that map to a metadata field key within a MetadataDatastream object are set to the corresponding value. Any others are ignored. ActiveFedora::SolrService.solr_name is used to map solr key to field key name.
Warning
Solr must be synchronized with data in Fedora.
@content is initialized to the empty document template to satisfy #ensure_xml_loaded
(called from #update_attributes and #update_indexed_attributes)
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
# File 'lib/active_fedora/metadata_datastream.rb', line 46 def from_solr(solr_doc) @content = self.to_xml self.xml_loaded = true fields.each do |field_key, field_info| field_symbol = ActiveFedora::SolrService.solr_name(field_key, field_info[:type]) value = (solr_doc[field_symbol].nil? ? solr_doc[field_symbol.to_s]: solr_doc[field_symbol]) unless value.nil? if value.is_a? Array update_attributes({field_key=>value}) else update_indexed_attributes({field_key=>{0=>value}}) end end end end |
#get_values(field_name, default = []) ⇒ Object
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/active_fedora/metadata_datastream.rb', line 158 def get_values(field_name, default=[]) ensure_xml_loaded 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
177 178 179 180 181 182 183 184 |
# File 'lib/active_fedora/metadata_datastream.rb', line 177 def set_value(field_name, values) ensure_xml_loaded 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 |
#to_solr(solr_doc = Hash.new) ⇒ Object
:nodoc:
19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# File 'lib/active_fedora/metadata_datastream.rb', line 19 def to_solr(solr_doc = Hash.new) # :nodoc: fields.each do |field_key, field_info| if field_info.has_key?(:values) && !field_info[:values].nil? field_symbol = ActiveFedora::SolrService.solr_name(field_key, field_info[:type]) values = field_info[:values] values = [values] unless values.respond_to? :each values.each do |val| ::Solrizer::Extractor.insert_solr_field_value(solr_doc, field_symbol, val ) end end end return solr_doc end |
#to_xml(xml = Nokogiri::XML::Document.parse("<fields />")) ⇒ Object
:nodoc:
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 |
# File 'lib/active_fedora/metadata_datastream.rb', line 198 def to_xml(xml = Nokogiri::XML::Document.parse("<fields />")) #:nodoc: if xml.instance_of?(Nokogiri::XML::Builder) xml_insertion_point = xml.doc.root elsif xml.instance_of?(Nokogiri::XML::Document) xml_insertion_point = xml.root else xml_insertion_point = xml end builder = Nokogiri::XML::Builder.with(xml_insertion_point) do |xml| fields.each do |field,field_info| element_attrs = field_info[:element_attrs].nil? ? {} : field_info[:element_attrs] values = field_info[:values] values = [values] unless values.respond_to? :each values.each do |val| builder_arg = "xml.#{field}(val, element_attrs)" eval(builder_arg) end end end return builder.to_xml end |
#update_attributes(params = {}, opts = {}) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# File 'lib/active_fedora/metadata_datastream.rb', line 65 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”})
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/active_fedora/metadata_datastream.rb', line 99 def update_indexed_attributes(params={}, opts={}) ensure_xml_loaded ##FIX this bug, it should delete it from a copy of params in case passed to another datastream for update since this will modify params ##for subsequent calls if updating more than one datastream in a single update_indexed_attributes call current_params = params.clone # remove any fields from params that this datastream doesn't recognize current_params.delete_if do |field_name,new_values| if field_name.kind_of?(Array) then field_name = field_name.first end !self.fields.include?(field_name.to_sym) end result = current_params.dup current_params.each do |field_name,new_values| if field_name.kind_of?(Array) then field_name = field_name.first end ##FIX this bug, it should delete it from a copy of params in case passed to another datastream for update #if field does not exist just skip it next if !self.fields.include?(field_name.to_sym) 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.keys.sort { |a,b| a.to_i <=> b.to_i }.each do |y| z = new_values[y] 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 self.dirty = true end return result end |