ref2bibtex 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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.