ref2bibtex 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d7757e8fcfbfeccc415e91c00e4f2302b0ce37c4
4
- data.tar.gz: 1bf31207bbc840f4ac1cd0617eb06713d47b1340
3
+ metadata.gz: 5f7108348cfed966bb638c38ff3b1056bc418ed6
4
+ data.tar.gz: b6553afe9e23c6a65d5c78a7fdc2d493379fc6ea
5
5
  SHA512:
6
- metadata.gz: 09316afcae92969335e4c421860aa5a2ac56f816039b58e581ba1afd34169b4f1b57cfc317db1e178ea2be35446955b6c46e35d59717bf02dbc5eecef1c82258
7
- data.tar.gz: 4dcafb5dca149065d4c9e71921fff3f26dc0a8f004609fd25ca31ae4e11f9464b926a78bcf5e84c60f0edbff7974e19b0d3c3e2878c07030b2553faf7fd495b7
6
+ metadata.gz: a14d2e3ee16b6fb7e04cc5c6b7900e0734aceb7548bfd0641f644bcba7e73c364b536c264dedd0df33d221d89ba1dabd36eb345ce1ba7c430c139086a0604811
7
+ data.tar.gz: d20b75b7ca8d76ffacb1eacb99c037ea99d98d284ceaf86347c530016c263c81dbc887e81020da1ed91c6c8e2d6748bf589a4af7d2f78139c9ac8a6ac7e2d601
data/Gemfile.lock CHANGED
@@ -1,20 +1,14 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ref2bibtex (0.0.3)
4
+ ref2bibtex (0.1.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
8
8
  specs:
9
- awesome_print (1.2.0)
10
- byebug (3.4.0)
11
- columnize (~> 0.8)
12
- debugger-linecache (~> 1.2)
13
- slop (~> 3.6)
14
- columnize (0.8.9)
15
- debugger-linecache (1.2.0)
16
- rake (10.3.2)
17
- slop (3.6.0)
9
+ awesome_print (1.7.0)
10
+ byebug (9.0.6)
11
+ rake (12.0.0)
18
12
 
19
13
  PLATFORMS
20
14
  ruby
@@ -22,6 +16,9 @@ PLATFORMS
22
16
  DEPENDENCIES
23
17
  awesome_print
24
18
  bundler (~> 1.6)
25
- byebug
26
- rake
19
+ byebug (~> 9.0)
20
+ rake (~> 12.0)
27
21
  ref2bibtex!
22
+
23
+ BUNDLED WITH
24
+ 1.14.6
data/README.md CHANGED
@@ -1,10 +1,10 @@
1
- ref2bibtex
2
- ==========
1
+ [![Build Status](https://travis-ci.org/SpeciesFileGroup/ref2bibtex.svg?branch=master)](https://travis-ci.org/SpeciesFileGroup/ref2bibtex)
3
2
 
4
- A single purpose gem wrapping Crossref's API. Pass it a full reference string, get back bibtex.
3
+ # ref2bibtex
5
4
 
6
- usage
7
- =====
5
+ An (almost) single purpose gem wrapping Crossref's API. Pass it a full reference string, get back bibtex.
6
+
7
+ # usage
8
8
 
9
9
  Use citation2bibtex (aliased _get_):
10
10
 
@@ -34,20 +34,24 @@ If you have the doi:
34
34
 
35
35
  ```
36
36
 
37
- faq
38
- ===
37
+ If you want a score:
38
+
39
+ ```ruby
40
+
41
+ Ref2bibtex.get_score('E. Ven. 1337. Fake articles. Journal Get Scores. Hm:mm') # => 23.688715
42
+
43
+ ```
44
+
45
+ # faq
39
46
 
40
- What if there are multiple results?
41
- -----------------------------------
47
+ ## What if there are multiple results?
42
48
  The code is dumb, it takes the first.
43
49
 
44
- acknowledgements
45
- ================
50
+ # acknowledgements
46
51
 
47
- The Crossref API, and Jon Hill, University of York, for his Python version and bringing up the approach.
52
+ The Crossref API. Jon Hill, University of York, for his Python version and bringing up the approach.
48
53
 
49
- license
50
- =======
54
+ # license
51
55
 
52
56
  NCSA, UI flavor. [http://opensource.org/licenses/NCSA]
53
57
 
@@ -1,3 +1,3 @@
1
1
  module Ref2bibtex
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/ref2bibtex.rb CHANGED
@@ -7,8 +7,25 @@ require 'net/http'
7
7
 
8
8
  module Ref2bibtex
9
9
 
10
+ # By default sorts by score
10
11
  CROSSREF_URI = URI('http://search.crossref.org/links')
11
12
 
13
+ DEFAULT_CUTOFF = 50
14
+
15
+ @@cutoff = DEFAULT_CUTOFF
16
+
17
+ def self.cutoff
18
+ @@cutoff
19
+ end
20
+
21
+ def self.cutoff=(value)
22
+ @@cutoff = value
23
+ end
24
+
25
+ def self.reset_cutoff
26
+ @@cutoff = DEFAULT_CUTOFF
27
+ end
28
+
12
29
  # Parse the response into json
13
30
  def self.parse_json(string)
14
31
  begin
@@ -26,26 +43,36 @@ module Ref2bibtex
26
43
  return false if uri.class == URI::Generic
27
44
  response = Ref2bibtex.request(uri, headers: {'Accept' => 'application/x-bibtex' }, protocol: 'GET', process_response_as: 'text')
28
45
  end
29
-
30
- # Pass a String citation, get a doi back
46
+
47
+ # Pass a String citation, get a DOI back
31
48
  def self.get_doi(citation)
32
- if citation.class == String
33
- citation = [citation]
34
- elsif citation.class != Array
35
- raise
36
- end
37
-
49
+ citation = validate_query(citation)
38
50
  response = Ref2bibtex.request(payload: citation)
39
- if response['results'][0]['match']
40
- response['results'].first['doi']
41
- else
42
- false
43
- end
51
+
52
+ return false if !response['results'][0]['match']
53
+ return false if response['results'][0]['score'] < @@cutoff
54
+
55
+ response['results'][0]['doi']
56
+ end
57
+
58
+ # Pass a String citation, get a score back
59
+ def self.get_score(citation)
60
+ citation = validate_query(citation)
61
+ response = Ref2bibtex.request(payload: citation)
62
+ return false if !response['results'][0]['match']
63
+ response['results'][0]['score']
64
+ end
65
+
66
+ def self.validate_query(citation)
67
+ return [citation] if citation.kind_of?(String) && citation.length > 0
68
+ raise 'citation is not String or Array' if !citation.kind_of?(Array)
69
+ raise 'citation in array is empty' if citation.empty? || citation.select{|a| a.length == 0}.size > 0
70
+ citation
44
71
  end
45
72
 
46
- # Pass a citation, get a String in bibtex back
73
+ # Pass a citation, get a String in BibTeX back
47
74
  def self.citation2bibtex(citation)
48
- get_bibtex( get_doi(citation) )
75
+ get_bibtex(get_doi(citation) )
49
76
  end
50
77
 
51
78
  class << self
@@ -54,47 +81,66 @@ module Ref2bibtex
54
81
 
55
82
  def self.request(url = CROSSREF_URI, payload: nil, headers: {'content-type' => 'application/json' }, protocol: 'POST', process_response_as: 'json', redirect_limit: 10)
56
83
  raise 'Infinite redirect?' if redirect_limit == 0
57
- data = nil
58
- if protocol == 'POST'
59
- if payload.nil?
60
- payload = {}
61
- end
62
- data = JSON.generate(payload) # Json.new(payload) # utf-8 encoding?
63
- else
64
- data = nil
65
- end
66
84
 
67
- if protocol == 'POST'
68
- request = Net::HTTP::Post.new(url, initheader = headers)
69
- elsif protocol == 'GET'
70
- request = Net::HTTP::Get.new(url, initheader = headers)
71
- end
85
+ body = request_body(protocol, payload)
86
+ request = new_request(protocol, url, headers)
72
87
 
73
- response = Net::HTTP.start(request.uri.hostname, request.uri.port) do |http|
74
- request.body = data
88
+ response = Net::HTTP.start(request.uri.hostname, request.uri.port, use_ssl: request.uri.scheme == 'https') do |http|
89
+ request.body = body
75
90
  http.request(request)
76
91
  end
77
92
 
78
93
  case response
79
- when Net::HTTPSuccess then
94
+ when Net::HTTPSuccess
80
95
  response = response
81
- when Net::HTTPRedirection then
96
+ when Net::HTTPRedirection
97
+
82
98
  url = URI(response['location'])
83
99
  request = Net::HTTP::Get.new(url, initheader = {'Accept' => 'application/x-bibtex'})
84
- response = Net::HTTP.start(request.uri.hostname, request.uri.port) do |http|
100
+
101
+ response = Net::HTTP.start(request.uri.hostname, request.uri.port, use_ssl: request.uri.scheme == 'https') do |http|
85
102
  http.request(request)
86
103
  end
87
104
  else
88
105
  response = response.value
89
106
  end
90
107
 
91
- case process_response_as
108
+ process_response(response, process_response_as)
109
+ end
110
+
111
+ protected
112
+
113
+ def self.interpret_response(response)
114
+ end
115
+
116
+ def self.request_body(protocol, payload)
117
+ if protocol == 'POST'
118
+ payload = {} if payload.nil?
119
+ JSON.generate(payload) # Json.new(payload) # utf-8 encoding?
120
+ else
121
+ nil
122
+ end
123
+ end
124
+
125
+ def self.new_request(protocol, url, headers)
126
+ case protocol
127
+ when 'POST'
128
+ Net::HTTP::Post.new(url, initheader = headers)
129
+ when 'GET'
130
+ Net::HTTP::Get.new(url, initheader = headers)
131
+ else
132
+ raise 'invalid protocol'
133
+ end
134
+ end
135
+
136
+ def self.process_response(response, as)
137
+ case as
92
138
  when 'text'
93
139
  response.body
94
140
  when 'json'
95
141
  parse_json(response.body)
96
142
  else
97
- raise
143
+ raise 'response process type not provided'
98
144
  end
99
145
  end
100
146
 
data/ref2bibtex.gemspec CHANGED
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
19
19
  spec.require_paths = ["lib"]
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
- spec.add_development_dependency "rake"
23
- spec.add_development_dependency "byebug"
22
+ spec.add_development_dependency "rake", "~> 12.0"
23
+ spec.add_development_dependency "byebug", "~> 9.0"
24
24
  spec.add_development_dependency "awesome_print"
25
25
 
26
26
  end
@@ -2,37 +2,37 @@ require 'spec_helper'
2
2
 
3
3
  describe Ref2bibtex do
4
4
 
5
- context '#request' do
5
+ context '.request' do
6
6
  let(:request) { Ref2bibtex.request(payload: [CITATIONS[:first]]) }
7
7
 
8
- specify '#Ref2bibtex.request makes a query_ok request' do
8
+ specify 'makes a query_ok request' do
9
9
  expect(request['query_ok']).to eq(true)
10
10
  end
11
11
 
12
- specify '#Ref2bibtex.request returns Hash' do
12
+ specify 'returns Hash' do
13
13
  expect(request.class).to eq(Hash)
14
14
  end
15
15
 
16
- specify '#Ref2bibtex.request results is an Array' do
16
+ specify 'results is an Array' do
17
17
  expect(request['results'].class).to eq(Array)
18
18
  end
19
19
 
20
- specify '#Ref2bibtex.request results is an Array of Hashes' do
20
+ specify 'results is an Array of Hashes' do
21
21
  expect(request['results'].first.class).to eq(Hash)
22
22
  end
23
23
 
24
- specify '#Ref2bibtex.request results is an Array of Hashes, each one having a doi' do
24
+ specify 'results is an Array of Hashes, each one having a doi' do
25
25
  expect(request['results'].first['doi']).to be_truthy
26
26
  end
27
27
  end
28
28
 
29
- context '#get_doi' do
30
- specify 'Ref2bibtex.get_doi() takes a full citation and returns a string' do
29
+ context '.get_doi' do
30
+ specify 'takes a full citation and returns a string' do
31
31
  expect(Ref2bibtex.get_doi(CITATIONS[:first])).to eq('http://dx.doi.org/10.3897/zookeys.20.205')
32
32
  end
33
33
 
34
34
  specify 'a citation that can not be resolved returns false' do
35
- expect(Ref2bibtex.get_doi(CITATIONS[:fifth])).to eq(false)
35
+ expect(Ref2bibtex.get_doi(CITATIONS[:eighth])).to eq(false)
36
36
  end
37
37
 
38
38
  specify 'a badly formed DOI returns false' do
@@ -40,9 +40,9 @@ describe Ref2bibtex do
40
40
  end
41
41
  end
42
42
 
43
- context '#get_bibtex' do
43
+ context '.get_bibtex' do
44
44
  let(:response) { Ref2bibtex.get_bibtex('http://dx.doi.org/10.3897/zookeys.20.205')}
45
- specify 'Ref2bibtex.get_bibtex() takes a full citation and returns bibtex' do
45
+ specify 'takes a full citation and returns bibtex' do
46
46
  expect(response).to match(/author\s=/)
47
47
  expect(response).to match(/title\s=/)
48
48
  expect(response).to match(/year\s=\s2009/)
@@ -53,8 +53,64 @@ describe Ref2bibtex do
53
53
  end
54
54
  end
55
55
 
56
- specify "a citation that can not be resolved returns false" do
57
- expect(Ref2bibtex.get(CITATIONS[:fifth])).to eq(false)
56
+ specify "a citation that can not be resolved returns false from .get" do
57
+ expect(Ref2bibtex.get(CITATIONS[:eighth])).to eq(false)
58
58
  end
59
59
 
60
+ context 'score' do
61
+ specify 'can be returned with .get_score' do
62
+ expect(Ref2bibtex.get_score(CITATIONS[:first])).to be > 0
63
+ end
64
+
65
+ context 'interpretation' do
66
+ before(:all) {
67
+ @scores = CITATIONS.keys.inject({}) { |hsh, c|
68
+ hsh.merge!(
69
+ c => Ref2bibtex.get_score(CITATIONS[c])
70
+ )
71
+ }
72
+ }
73
+
74
+ specify 'mangled text is worse than good text' do
75
+ expect( @scores[:second] > @scores[:seventh] ).to be_truthy
76
+ end
77
+
78
+ context 'default @@cutoff is reasonable and slightly conservative' do
79
+ let(:good_citations) { [:first, :second, :third, :fourth, :sixth] }
80
+ let(:bad_citations) { CITATIONS.keys - good_citations }
81
+
82
+ specify 'for good citations' do
83
+ good_citations.each do |c|
84
+ expect(@scores[c]).to be > Ref2bibtex.cutoff
85
+ end
86
+ end
87
+
88
+ specify 'for bad citations' do
89
+ bad_citations.each do |c|
90
+ if @scores[c]
91
+ expect(@scores[c]).to be < Ref2bibtex.cutoff
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ context 'cutoff' do
99
+ after(:all) {
100
+ Ref2bibtex.reset_cutoff
101
+ }
102
+
103
+ specify 'can be used to reject good matches' do
104
+ Ref2bibtex.cutoff = 1000
105
+ expect(Ref2bibtex.get_doi(CITATIONS[:first])).to eq(false)
106
+ end
107
+
108
+ specify 'can be used to accept bad matches' do
109
+ Ref2bibtex.cutoff = 1
110
+ expect(Ref2bibtex.get_doi(CITATIONS[:fifth])).to be_truthy
111
+ end
112
+
113
+ end
114
+
115
+ end
60
116
  end
@@ -8,4 +8,11 @@
8
8
  :fourth:
9
9
  "Otte, D. 1994. Crickets (Grylloidea). Orthoptera Species File, The Orthopterists' Society and The Academy of Natural Sciences of Philadelphia, Philadelphia 1:87"
10
10
  :fifth:
11
- "Defaut. 2006. Révision préliminaire des Oedipoda ouest-paléarctiques (Caelifera, Acrididae, Oedipodinae). Matériaux Orthoptériques et Entomocénotiques 11:23-48"
11
+ "Iam, F.K. 1337. Let's go Crossref, give me a DOI for this fake reference in my unit test, I dare you. Journal of Examples for Unit tests. 13:37"
12
+ :sixth:
13
+ "Simon, E. (1879b) Les Arachnides de France. Tome 7. Contenant les ordres des Chernetes, Scorpiones et Opiliones. Librairie Encyclopédique de Roret, Paris, pp. 1–332, pl. 17–24. "
14
+ :seventh:
15
+ 'Jaost & K.P. Shuw. 2007. Phyloguny of Ensifere (Hesapoda: Prthoptera) usine threa rubosomal toci, wuth implocations far teh evolushun off acoustik commmunication. Tolecular Fylogenetics & Evolotion (Mul. Phylagenet. Evil.) 39:509-528'
16
+ :eighth:
17
+ 'Only two'
18
+
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ref2bibtex
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matt Yoder
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-06 00:00:00.000000000 Z
11
+ date: 2017-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -28,30 +28,30 @@ dependencies:
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ">="
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '0'
33
+ version: '12.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ">="
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '0'
40
+ version: '12.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: byebug
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ">="
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: '9.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ">="
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0'
54
+ version: '9.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: awesome_print
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
106
  version: '0'
107
107
  requirements: []
108
108
  rubyforge_project:
109
- rubygems_version: 2.2.2
109
+ rubygems_version: 2.6.12
110
110
  signing_key:
111
111
  specification_version: 4
112
112
  summary: Pass a full citation, get the bibtex back, that's all.