app/models/referent.rb in umlaut-3.3.1 vs app/models/referent.rb in umlaut-4.0.0.beta1

- old
+ new

@@ -1,5 +1,7 @@ +require 'i18n' + # Note: There are a few actual attributes stored as Columns in referent -- # these were originally used for identifying a Referent identifying the # 'same thing' as an incoming OpenURL, to re-use it. But we don't re-use # cached referents anymore. So these attributes are NOT USED -- actual # values are over in ReferentValues. But the attributes are left for now @@ -13,13 +15,13 @@ has_many :requests has_many :referent_values has_many :permalinks - # Does call save! on referent created. - # :permalink => false if you already have a permalink and don't - # need to create one. Caller should attach that permalink to this referent! + # Pass in :permalink => :force to force creation of a permalink, otherwise + # no permalink is created by this method, one can be lazily created when + # needed. def self.create_by_context_object(co, options = {}) self.clean_up_context_object(co) rft = Referent.new @@ -38,14 +40,14 @@ # Add shortcuts. rft.referent_values.each do | val | rft.atitle = val.normalized_value if val.key_name == 'atitle' and val.metadata? rft.title = val.normalized_value if val.key_name.match(/^[bj]?title$/) and val.metadata? - rft.issn = val.normalized_value if val.key_name == 'issn' and val.metadata? - rft.isbn = val.normalized_value if val.key_name == 'isbn' and val.metadata? + rft.issn = val.normalized_value.gsub(/[^\d]/, '')[0,8] if val.key_name == 'issn' and val.metadata? + rft.isbn = val.normalized_value.gsub(/[^\d]/, '')[0,13] if val.key_name == 'isbn' and val.metadata? rft.volume = val.normalized_value if val.key_name == 'volume' and val.metadata? - rft.year = val.normalized_value if val.key_name == 'date' and val.metadata? + rft.year = val.normalized_value.gsub(/[^\d]/, '')[0,4] if val.key_name == 'date' and val.metadata? end rft.save! # Apply referent filters rfr_id = "" @@ -105,65 +107,48 @@ end - # Find or create a ReferentValue object hanging off this - # Referent, with given key name and value. key_name can - # be 'identifier', 'format', or any metadata key. - def ensure_value!(key_name, value) - normalized_value = ReferentValue.normalize(value) - - rv = ReferentValue.find(:first, - :conditions => { :referent_id => self.id, - :key_name => key_name, - :normalized_value => normalized_value }) - unless (rv) - rv = ReferentValue.new - rv.referent = self - - rv.key_name = key_name - rv.value = value - rv.normalized_value = normalized_value - - if key_name == "private_data" - rv.private_data = true - elsif key_name != "identifier" && key_name != "format" - rv.metadata = true - end - - rv.save! - end - return rv + # private use. Adds a referent_value and returns it, does NOT persist + # it to db. referent_value is constructed with ActiveRecord build, and + # will be saved when Referent (self) is saved, works on persisted or + # unpersisted Referent. + def build_referent_value(key_name, value) + return self.referent_values.build( + :key_name => key_name, + :value => value, + :normalized_value => ReferentValue.normalize(value), + :private_data => (key_name == "private_data"), + :metadata => (key_name != "identifier" && key_name != "format") + ) end + # Populate the referent_values table with a ropenurl contextobject object + # Note, does NOT save self, self may still be unsaved. def set_values_from_context_object(co) - rft = co.referent - # Multiple identifiers are possible! rft.identifiers.each do |id_string| - ensure_value!('identifier', id_string) + build_referent_value('identifier', id_string) end if rft.format - ensure_value!('format', rft.format) + build_referent_value('format', rft.format) end if rft.private_data # this comes in as "pid" or "rft_dat", we store it in # our database as "private_data", sorry, easiest way to # fit this in at the moment. - ensure_value!("private_data", rft.private_data) + build_referent_value("private_data", rft.private_data) end rft.metadata.each { | key, value | - next unless value - ensure_value!( key, value) - } - - + next unless value.present? + build_referent_value( key, value) + } end # pass in a Referent, or a ropenurl ContextObjectEntity that has a metadata # method. Or really anything with a #metadata method returning openurl-style # keys and values. @@ -217,21 +202,18 @@ return identifiers end def add_identifier(id) unless ( identifiers.find{|i| i == id} ) - self.referent_values.create(:key_name => 'identifier', :value => id, :normalized_value => ReferentValue.normalize(id), :metadata => false, :private_data => false).save! + Referent.with_connection do + self.referent_values.create(:key_name => 'identifier', :value => id, :normalized_value => ReferentValue.normalize(id), :metadata => false, :private_data => false).save! + end end end def format - self.referent_values - self.referent_values.each { | val | - if val.key_name == 'format' - return val.value - end - } + self.referent_values.to_a.find { | val | val.key_name == 'format'}.try(:value) end # Some shortcuts for pulling out/manipulating specific especially # useful data elements. @@ -279,56 +261,38 @@ return co end # Creates a hash for use in View code to display a citation # - # Crazy if/else tree logic, should be refactored, needs more tests first prob. + # TODO, move to_citation, type_of_thing, and container_type_of_thing OUT + # of Refernet, to helper module or own class. def to_citation citation = {} # call self.metadata once and use the array for efficiency, don't # keep calling it. profiling shows it DOES make a difference. my_metadata = self.metadata if my_metadata['atitle'].present? citation[:title] = my_metadata['atitle'] - citation[:title_label], citation[:container_label] = - case my_metadata['genre'] - when /article|journal|issue/ then ['Article Title', 'Journal'] - when /bookitem|book/ then ['Chapter/Part Title', 'book'] - when /proceeding|conference/ then ['Proceeding Title', 'conference'] - when 'report' then ['Report Title','report'] - else - if self.format == 'book' - ['Chapter/Part Title', 'book'] - elsif self.format == 'journal' - ['Article Title', 'Journal'] - else # default fall through, use much what SFX uses. - ['Title', ''] - end - end ['title','btitle','jtitle'].each do | t_type | - if ! my_metadata[t_type].blank? - citation[:subtitle] = my_metadata[t_type] - citation[:container_title] = my_metadata[t_type] + if my_metadata[t_type].present? + citation[:container_title] = my_metadata[t_type] break end end - else - citation[:title_label] = case my_metadata["genre"] - when /article|journal|issue/i then 'Journal' - when /bookitem|book/i then 'Book' - when /proceeding|conference/i then 'Conference' - when 'report' then 'Report' - else nil - end + else # only top-level thing, no sub-thing ['title','btitle','jtitle'].each do | t_type | - if ! my_metadata[t_type].blank? + if my_metadata[t_type].present? citation[:title] = my_metadata[t_type] break end end end + + citation[:title_label] = I18n.t("umlaut.citation.title_of_x", :x => self.type_of_thing, :default => "umlaut.citation.title_label") + citation[:container_label] = self.container_type_of_thing + # add publisher for books if (my_metadata['genre'] =~ /book/i) citation[:pub] = my_metadata['pub'] unless my_metadata['pub'].blank? end @@ -370,29 +334,43 @@ end return citation end def type_of_thing - genre = self.metadata["genre"] - genre = nil if genre =~ /^unknown$/i - genre = "book section" if genre =~ /^bookitem$/i + metadata = self.metadata - return genre + key = metadata["genre"] + key = self.format if key.blank? + key = key.downcase + + if key == "journal" && metadata['atitle'].present? + key = 'article' + end + + label = I18n.t(key, :scope => "umlaut.citation.genre", :default => "") + label = nil if label.blank? + + return label end # Like type_of_thing, but if it's a contained item, give container name instead. - # TODO: All of this should be I18n'd. def container_type_of_thing - case self.metadata["genre"] - when 'article' then 'journal' - when 'bookitem' then 'book' - else self.metadata['genre'] || self.format + i18n_key = case self.metadata['genre'] + when 'article' then 'journal' + when 'bookitem' then 'book' + else self.metadata['genre'] || self.format end + + label = I18n.t(i18n_key, :scope => "umlaut.citation.genre", :default => "") + label = nil if label.blank? + + return label end def remove_value(key) - referent_values.find(:all, :conditions=> ['key_name =?', key]).each do |rv| + referent_values.where(:key_name => key).to_a.each do |rv| + rv.delete referent_values.delete(rv) end end # options => { :overwrite => false } to only enhance if not already there