Class: Reference

Inherits:
Object
  • Object
show all
Extended by:
DOIHelpers
Includes:
DOIHelpers
Defined in:
model/referencia.rb

Overview

Reference made on one article to another.

Is the hardest object on the system. All bibliographical system stores references on different ways. So, we store the store the test as-is and use the sha256 digest as an identifier.

If the text contains a DOI, is very easy to assign the reference to a canonical document, but often the reference doesn't have enough information to create it. So, we retrieve information from Crossref to create the canonical document.

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DOIHelpers

a_doi, doi_without_http, find_doi, url_doi

Class Method Details

.get_by_text(text) ⇒ Object

Retrieve a Reference with a specific text If doesn't exist before, create it

Parameters:

  • text

    reference text, as-is

Returns:

  • a Reference



53
54
55
56
# File 'model/referencia.rb', line 53

def self.get_by_text(text)
  dig=Digest::SHA256.hexdigest text
  Reference[dig]
end

.get_by_text_and_doi(text, doi, create = false) ⇒ Object

Retrieve a reference using text and doi If doesn't exists before, and param create is true create it

Parameters:

  • text
  • doi

Returns:

  • Reference or nil



63
64
65
66
67
68
69
70
71
72
73
74
75
76
# File 'model/referencia.rb', line 63

def self.get_by_text_and_doi(text,doi,create=false)
  dig=Digest::SHA256.hexdigest text
  if doi
    doi=doi_without_http(doi)
    ref=Reference.where(:id=>dig,:doi=>doi).first
  else
    ref=Reference[dig]
  end
  if create and !ref
    Reference.insert(:id=>dig,:text=>text,:doi=>doi)
    ref=Reference[dig]
  end
  ref
end

Instance Method Details

#add_doi(doi_n) ⇒ Object

Retrieve information from Crossref, using doi, and create a canonical document



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
156
157
158
159
# File 'model/referencia.rb', line 109

def add_doi(doi_n)
  #$log.info("Agregar #{doi_n} a #{self[:id]}")
  status=Result.new

  crossref_doi=CrossrefDoi.procesar_doi(doi_n)

  unless crossref_doi
    status.error("No puedo procesar DOI #{doi_n}")
    return status
  end

  $db.transaction do
    ##$log.info(co)
    if self[:doi]==doi_n
      status.info("Ya agregado DOI para reference #{self[:id]}")
    else
      self.update(:doi=>doi_without_http(doi_n))
      status.success("Se agrega DOI #{doi_n} para reference #{self[:id]}")
    end

    if self[:canonical_document_id].nil?
      can_doc=CanonicalDocument[:doi=>doi_without_http(doi_n)]
      if can_doc
        self.update(:canonical_document_id=>can_doc[:id])
        status.info("Agregado a documento canónico #{can_doc[:id]} ya existente")
      else # No existe el canónico, lo debo crear
        integrator=CrossrefDoi.reference_integrator_json(doi)
        ##$log.info(integrator)
        fields = [:title,:author,:year,:journal, :volume, :pages, :doi, :journal_abbr,:abstract]
        fields_update=fields.inject({}) {|ac,v|
          ac[v]= integrator.send(v); ac;
        }

        # En casos muy raros no está el año. Tengo que reportar error, no más
        if fields_update[:year].nil?
          status.error("El DOI #{doi} no tiene año. Extraño, pero tengo que cancelar misión")
        else
          can_doc_id=CanonicalDocument.insert(fields_update)
          self.update(:canonical_document_id=>can_doc_id)
          status.success("Agregado un nuevo documento canónico #{can_doc_id}: #{integrator.ref_apa_6}")
        end
      end
      $db.after_rollback {
        status=Result.new
        status.error("Rollback en agregar doi para reference #{self[:id]}")
      }
    end
  end

  status
end

#crossref_queryObject



78
79
80
# File 'model/referencia.rb', line 78

def crossref_query
  CrossrefQuery.generate_query_from_text( self[:text] )
end

#search_similars(d = nil, sin_canonico = true) ⇒ Object



82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'model/referencia.rb', line 82

def search_similars(d=nil, sin_canonico=true)
  begin
    require 'levenshtein-ffi'
  rescue LoadError
    require 'levenshtein'
  end

  canonico_sql= sin_canonico ? " AND canonical_document_id IS NULL ": ""

  distancias=Reference.where(Sequel.lit("id!='#{self[:id]}' #{canonico_sql}")).map {|v|
    {
        :id=>v[:id],
        :canonical_document_id=>v[:canonical_document_id],
        :text=>v[:text],
        :distancia=>Levenshtein.distance(v[:text],self[:text])
    }

  }
  if !d.nil?
    distancias=distancias.find_all {|v| v[:distancia]<=d}
  end
  distancias.sort {|a,b| a[:distancia]<=>b[:distancia]}
end