serrano 0.5.0 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.rubocop.yml +14 -0
- data/.rubocop_todo.yml +122 -0
- data/.travis.yml +7 -3
- data/CHANGELOG.md +5 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +42 -26
- data/LICENSE +1 -1
- data/README.md +5 -0
- data/Rakefile +25 -18
- data/bin/serrano +96 -98
- data/lib/serrano.rb +112 -85
- data/lib/serrano/cn.rb +6 -8
- data/lib/serrano/cnrequest.rb +41 -27
- data/lib/serrano/error.rb +2 -0
- data/lib/serrano/faraday.rb +15 -14
- data/lib/serrano/filterhandler.rb +13 -15
- data/lib/serrano/filters.rb +72 -70
- data/lib/serrano/helpers/configuration.rb +2 -2
- data/lib/serrano/request.rb +41 -39
- data/lib/serrano/request_cursor.rb +62 -61
- data/lib/serrano/styles.rb +14 -9
- data/lib/serrano/utils.rb +16 -13
- data/lib/serrano/version.rb +3 -1
- data/serrano.gemspec +19 -17
- metadata +77 -52
- data/lib/serrano/constants.rb +0 -36
- data/lib/serrano/cursor_testing.rb +0 -52
data/lib/serrano.rb
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
require 'serrano/version'
|
5
|
+
require 'serrano/request'
|
6
|
+
require 'serrano/request_cursor'
|
7
|
+
require 'serrano/filterhandler'
|
8
|
+
require 'serrano/cnrequest'
|
9
|
+
require 'serrano/filters'
|
10
|
+
require 'serrano/styles'
|
8
11
|
|
9
12
|
require 'rexml/document'
|
10
13
|
require 'rexml/xpath'
|
@@ -19,10 +22,10 @@ require 'rexml/xpath'
|
|
19
22
|
# @param sort [String] Field to sort on, one of score, relevance,
|
20
23
|
# updated (date of most recent change to metadata - currently the same as deposited),
|
21
24
|
# deposited (time of most recent deposit), indexed (time of most recent index),
|
22
|
-
# published (publication date), published-print (print publication date),
|
23
|
-
# published-online (online publication date), issued (issued date (earliest known publication date)),
|
24
|
-
# is-referenced-by-count (number of times this DOI is referenced by other Crossref DOIs), or
|
25
|
-
# references-count (number of references included in the references section of the document
|
25
|
+
# published (publication date), published-print (print publication date),
|
26
|
+
# published-online (online publication date), issued (issued date (earliest known publication date)),
|
27
|
+
# is-referenced-by-count (number of times this DOI is referenced by other Crossref DOIs), or
|
28
|
+
# references-count (number of references included in the references section of the document
|
26
29
|
# identified by this DOI). Note: If the API call includes a query, then the sort
|
27
30
|
# order will be by the relevance score. If no query is included, then the sort order
|
28
31
|
# will be by DOI update date.
|
@@ -32,7 +35,7 @@ require 'rexml/xpath'
|
|
32
35
|
# @param select [String/Array(String)] Crossref metadata records can be
|
33
36
|
# quite large. Sometimes you just want a few elements from the schema. You can "select"
|
34
37
|
# a subset of elements to return. This can make your API calls much more efficient. Not
|
35
|
-
# clear yet which fields are allowed here.
|
38
|
+
# clear yet which fields are allowed here.
|
36
39
|
# @param verbose [Boolean] Print request headers to stdout. Default: false
|
37
40
|
|
38
41
|
# @!macro cursor_params
|
@@ -60,7 +63,7 @@ require 'rexml/xpath'
|
|
60
63
|
# - oauth [Hash] A hash with OAuth details
|
61
64
|
|
62
65
|
# @!macro field_queries
|
63
|
-
# @param [Hash<Object>] args Field queries, as named parameters. See
|
66
|
+
# @param [Hash<Object>] args Field queries, as named parameters. See
|
64
67
|
# https://github.com/CrossRef/rest-api-doc/blob/master/rest_api.md#field-queries
|
65
68
|
# Field query parameters mut be named, and must start with `query_`. Any dashes or
|
66
69
|
# periods should be replaced with underscores. The options include:
|
@@ -119,13 +122,13 @@ require 'rexml/xpath'
|
|
119
122
|
# information, then they will send you to a separate pool of machines,
|
120
123
|
# with better control the performance of these machines because they can
|
121
124
|
# block abusive users.
|
122
|
-
#
|
125
|
+
#
|
123
126
|
# We have been using `https` in `serrano` for a while now, so that's good
|
124
127
|
# to go. To get into the Polite Pool, also set your `mailto` email address
|
125
128
|
# with `Serrano.configuration` (example below), or set as an environment
|
126
129
|
# variable with the name `CROSSREF_EMAIL` and your mailto will be set
|
127
|
-
# for each request automatically.
|
128
|
-
#
|
130
|
+
# for each request automatically.
|
131
|
+
#
|
129
132
|
# require 'serrano'
|
130
133
|
# Serrano.configuration do |config|
|
131
134
|
# config.mailto = "foo@bar.com"
|
@@ -138,14 +141,20 @@ require 'rexml/xpath'
|
|
138
141
|
# limit is 50 requests per second. Look for the headers `X-Rate-Limit-Limit`
|
139
142
|
# and `X-Rate-Limit-Interval` in requests to see what the current rate
|
140
143
|
# limits are.
|
144
|
+
#
|
145
|
+
#
|
146
|
+
# URL Encoding
|
147
|
+
# We do URL encoding of DOIs for you for all methods except `Serrano.citation_count`
|
148
|
+
# which doesn't work if you encode DOIs beforehand. We use `ERB::Util.url_encode`
|
149
|
+
# to encode.
|
141
150
|
|
142
151
|
module Serrano
|
143
152
|
extend Configuration
|
144
153
|
|
145
154
|
define_setting :access_token
|
146
155
|
define_setting :access_secret
|
147
|
-
define_setting :mailto, ENV[
|
148
|
-
define_setting :base_url,
|
156
|
+
define_setting :mailto, ENV['CROSSREF_EMAIL']
|
157
|
+
define_setting :base_url, 'https://api.crossref.org/'
|
149
158
|
|
150
159
|
##
|
151
160
|
# Search the works route
|
@@ -193,7 +202,7 @@ module Serrano
|
|
193
202
|
#
|
194
203
|
# # sample
|
195
204
|
# Serrano.works(sample: 2)
|
196
|
-
#
|
205
|
+
#
|
197
206
|
# # select - pass an array or a comma separated string
|
198
207
|
# Serrano.works(query: "ecology", select: "DOI,title", limit: 30)
|
199
208
|
# Serrano.works(query: "ecology", select: ["DOI","title"], limit: 30)
|
@@ -221,13 +230,13 @@ module Serrano
|
|
221
230
|
# # select certain fields
|
222
231
|
# Serrano.works(select: ['DOI', 'title'], limit: 3)
|
223
232
|
def self.works(ids: nil, query: nil, filter: nil, offset: nil,
|
224
|
-
|
225
|
-
|
226
|
-
|
233
|
+
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
234
|
+
select: nil, options: nil, verbose: false, cursor: nil,
|
235
|
+
cursor_max: 5000, **args)
|
227
236
|
|
228
237
|
RequestCursor.new('works', ids, query, filter, offset,
|
229
|
-
|
230
|
-
|
238
|
+
limit, sample, sort, order, facet, select, nil, nil, options,
|
239
|
+
verbose, cursor, cursor_max, args).perform
|
231
240
|
end
|
232
241
|
|
233
242
|
##
|
@@ -277,13 +286,13 @@ module Serrano
|
|
277
286
|
# # select certain fields
|
278
287
|
# Serrano.members(ids: 340, works: true, select: ['DOI', 'title'], limit: 3)
|
279
288
|
def self.members(ids: nil, query: nil, filter: nil, offset: nil,
|
280
|
-
|
281
|
-
|
282
|
-
|
289
|
+
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
290
|
+
select: nil, works: false, options: nil, verbose: false,
|
291
|
+
cursor: nil, cursor_max: 5000, **args)
|
283
292
|
|
284
293
|
RequestCursor.new('members', ids, query, filter, offset,
|
285
|
-
|
286
|
-
|
294
|
+
limit, sample, sort, order, facet, select, works, nil,
|
295
|
+
options, verbose, cursor, cursor_max, args).perform
|
287
296
|
end
|
288
297
|
|
289
298
|
##
|
@@ -322,15 +331,15 @@ module Serrano
|
|
322
331
|
# res[0]['message']['items'].collect { |x| x['title'] }
|
323
332
|
#
|
324
333
|
# # select certain fields
|
325
|
-
# Serrano.prefixes(ids: "10.1016", works: true, select: ['DOI', 'title'], limit: 3)
|
334
|
+
# Serrano.prefixes(ids: "10.1016", works: true, select: ['DOI', 'title'], limit: 3)
|
326
335
|
def self.prefixes(ids:, filter: nil, offset: nil,
|
327
|
-
|
328
|
-
|
329
|
-
|
336
|
+
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
337
|
+
select: nil, works: false, options: nil, verbose: false,
|
338
|
+
cursor: nil, cursor_max: 5000, **args)
|
330
339
|
|
331
340
|
RequestCursor.new('prefixes', ids, nil, filter, offset,
|
332
|
-
|
333
|
-
|
341
|
+
limit, sample, sort, order, facet, select, works, nil,
|
342
|
+
options, verbose, cursor, cursor_max, args).perform
|
334
343
|
end
|
335
344
|
|
336
345
|
##
|
@@ -374,15 +383,15 @@ module Serrano
|
|
374
383
|
# res[0]['message']['items'].collect { |x| x['author'][0]['family'] }
|
375
384
|
#
|
376
385
|
# # select certain fields
|
377
|
-
# Serrano.funders(ids: "10.13039/100000001", works: true, select: ['DOI', 'title'], limit: 3)
|
386
|
+
# Serrano.funders(ids: "10.13039/100000001", works: true, select: ['DOI', 'title'], limit: 3)
|
378
387
|
def self.funders(ids: nil, query: nil, filter: nil, offset: nil,
|
379
|
-
|
380
|
-
|
381
|
-
|
388
|
+
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
389
|
+
select: nil, works: false, options: nil, verbose: false,
|
390
|
+
cursor: nil, cursor_max: 5000, **args)
|
382
391
|
|
383
392
|
RequestCursor.new('funders', ids, query, filter, offset,
|
384
|
-
|
385
|
-
|
393
|
+
limit, sample, sort, order, facet, select, works, nil, options,
|
394
|
+
verbose, cursor, cursor_max, args).perform
|
386
395
|
end
|
387
396
|
|
388
397
|
##
|
@@ -426,15 +435,15 @@ module Serrano
|
|
426
435
|
# res[0]['message']['items'].collect { |x| x['container-title'] }
|
427
436
|
#
|
428
437
|
# # select certain fields
|
429
|
-
# Serrano.journals(ids: "2167-8359", works: true, select: ['DOI', 'title'], limit: 3)
|
438
|
+
# Serrano.journals(ids: "2167-8359", works: true, select: ['DOI', 'title'], limit: 3)
|
430
439
|
def self.journals(ids: nil, query: nil, filter: nil, offset: nil,
|
431
|
-
|
432
|
-
|
433
|
-
|
440
|
+
limit: nil, sample: nil, sort: nil, order: nil, facet: nil,
|
441
|
+
select: nil, works: false, options: nil, verbose: false,
|
442
|
+
cursor: nil, cursor_max: 5000, **args)
|
434
443
|
|
435
444
|
RequestCursor.new('journals', ids, query, filter, offset,
|
436
|
-
|
437
|
-
|
445
|
+
limit, sample, sort, order, facet, select, works, nil, options,
|
446
|
+
verbose, cursor, cursor_max, args).perform
|
438
447
|
end
|
439
448
|
|
440
449
|
##
|
@@ -448,7 +457,7 @@ module Serrano
|
|
448
457
|
# @param select [String/Array(String)] Crossref metadata records can be
|
449
458
|
# quite large. Sometimes you just want a few elements from the schema. You can "select"
|
450
459
|
# a subset of elements to return. This can make your API calls much more efficient. Not
|
451
|
-
# clear yet which fields are allowed here.
|
460
|
+
# clear yet which fields are allowed here.
|
452
461
|
# @return [Array] An array of hashes
|
453
462
|
#
|
454
463
|
# @example
|
@@ -470,21 +479,40 @@ module Serrano
|
|
470
479
|
# res[0]['message']['items'].collect { |x| x['container-title'] }
|
471
480
|
#
|
472
481
|
# # select certain fields
|
473
|
-
# Serrano.types(ids: "journal", works: true, select: ['DOI', 'title'], limit: 3)
|
482
|
+
# Serrano.types(ids: "journal", works: true, select: ['DOI', 'title'], limit: 3)
|
474
483
|
def self.types(ids: nil, offset: nil, limit: nil, select: nil, works: false,
|
475
|
-
|
484
|
+
options: nil, verbose: false, cursor: nil, cursor_max: 5000, **args)
|
476
485
|
|
477
486
|
RequestCursor.new('types', ids, nil, nil, offset,
|
478
|
-
|
479
|
-
|
487
|
+
limit, nil, nil, nil, nil, select, works, nil, options,
|
488
|
+
verbose, cursor, cursor_max, args).perform
|
480
489
|
end
|
481
490
|
|
482
491
|
##
|
483
492
|
# Search the licenses route
|
484
493
|
#
|
485
|
-
# @!macro serrano_params
|
486
494
|
# @!macro serrano_options
|
487
495
|
# @param query [String] A query string
|
496
|
+
# @param offset [Fixnum] Number of record to start at, any non-negative integer up to 10,000
|
497
|
+
# @param limit [Fixnum] Number of results to return. Not relavant when searching with specific dois.
|
498
|
+
# Default: 20. Max: 1000
|
499
|
+
# @param sample [Fixnum] Number of random results to return. when you use the sample parameter,
|
500
|
+
# the limit and offset parameters are ignored. This parameter only used when works requested.
|
501
|
+
# Max: 100.
|
502
|
+
# @param sort [String] Field to sort on, one of score, relevance,
|
503
|
+
# updated (date of most recent change to metadata - currently the same as deposited),
|
504
|
+
# deposited (time of most recent deposit), indexed (time of most recent index),
|
505
|
+
# published (publication date), published-print (print publication date),
|
506
|
+
# published-online (online publication date), issued (issued date (earliest known publication date)),
|
507
|
+
# is-referenced-by-count (number of times this DOI is referenced by other Crossref DOIs), or
|
508
|
+
# references-count (number of references included in the references section of the document
|
509
|
+
# identified by this DOI). Note: If the API call includes a query, then the sort
|
510
|
+
# order will be by the relevance score. If no query is included, then the sort order
|
511
|
+
# will be by DOI update date.
|
512
|
+
# @param order [String] Sort order, one of 'asc' or 'desc'
|
513
|
+
# @param facet [Boolean/String] Include facet results OR a query (e.g., `license:*`) to facet by
|
514
|
+
# license. Default: false
|
515
|
+
# @param verbose [Boolean] Print request headers to stdout. Default: false
|
488
516
|
# @return [Array] An array of hashes
|
489
517
|
#
|
490
518
|
# @example
|
@@ -493,11 +521,11 @@ module Serrano
|
|
493
521
|
# Serrano.licenses()
|
494
522
|
# Serrano.licenses(limit: 3)
|
495
523
|
def self.licenses(query: nil, offset: nil,
|
496
|
-
|
497
|
-
|
524
|
+
limit: nil, sample: nil, sort: nil, order: nil,
|
525
|
+
facet: nil, options: nil, verbose: false)
|
498
526
|
|
499
527
|
Request.new('licenses', nil, query, nil, offset,
|
500
|
-
|
528
|
+
limit, sample, sort, order, facet, nil, nil, nil, options, verbose).perform
|
501
529
|
end
|
502
530
|
|
503
531
|
##
|
@@ -512,9 +540,8 @@ module Serrano
|
|
512
540
|
# Serrano.registration_agency(ids: '10.1371/journal.pone.0033693')
|
513
541
|
# Serrano.registration_agency(ids: ['10.1007/12080.1874-1746','10.1007/10452.1573-5125', '10.1111/(issn)1442-9993'])
|
514
542
|
def self.registration_agency(ids:, options: nil, verbose: false)
|
515
|
-
|
516
543
|
Request.new('works', ids, nil, nil, nil,
|
517
|
-
|
544
|
+
nil, nil, nil, nil, nil, false, true, options, verbose).perform
|
518
545
|
end
|
519
546
|
|
520
547
|
##
|
@@ -535,9 +562,8 @@ module Serrano
|
|
535
562
|
# Serrano.random_dois(sample: 10)
|
536
563
|
# Serrano.random_dois(sample: 100)
|
537
564
|
def self.random_dois(sample: 10, options: nil, verbose: false)
|
538
|
-
|
539
565
|
tmp = Request.new('works', nil, nil, nil, nil,
|
540
|
-
|
566
|
+
nil, sample, nil, nil, nil, nil, false, nil, options, verbose).perform
|
541
567
|
tmp['message']['items'].collect { |x| x['DOI'] }
|
542
568
|
end
|
543
569
|
|
@@ -564,7 +590,7 @@ module Serrano
|
|
564
590
|
# Serrano.content_negotiation(ids: "10.1126/science.169.3946.635", format: "crossref-xml")
|
565
591
|
# Serrano.content_negotiation(ids: "10.1126/science.169.3946.635", format: "text")
|
566
592
|
#
|
567
|
-
# # return
|
593
|
+
# # return a bibentry type
|
568
594
|
# Serrano.content_negotiation(ids: "10.1126/science.169.3946.635", format: "bibentry")
|
569
595
|
# Serrano.content_negotiation(ids: "10.6084/m9.figshare.97218", format: "bibentry")
|
570
596
|
#
|
@@ -577,30 +603,32 @@ module Serrano
|
|
577
603
|
# Serrano.content_negotiation(ids: "10.1126/science.169.3946.635", format: "text", style: "oikos")
|
578
604
|
#
|
579
605
|
# # example with many DOIs
|
580
|
-
# dois =
|
581
|
-
# Serrano.content_negotiation(dois, format: "text", style: "apa")
|
606
|
+
# dois = Serrano.random_dois(sample: 2)
|
607
|
+
# Serrano.content_negotiation(ids: dois, format: "text", style: "apa")
|
582
608
|
#
|
583
609
|
# # Using DataCite DOIs
|
584
|
-
#
|
585
|
-
#
|
586
|
-
#
|
587
|
-
#
|
610
|
+
# doi = "10.1126/science.169.3946.635"
|
611
|
+
# Serrano.content_negotiation(ids: doi, format: "text")
|
612
|
+
# Serrano.content_negotiation(ids: doi, format: "crossref-xml")
|
613
|
+
# Serrano.content_negotiation(ids: doi, format: "crossref-tdm")
|
588
614
|
#
|
589
615
|
# ## But most do work
|
590
|
-
# Serrano.content_negotiation(ids:
|
591
|
-
# Serrano.content_negotiation(ids:
|
592
|
-
# Serrano.content_negotiation(ids:
|
593
|
-
# Serrano.content_negotiation(ids:
|
594
|
-
# Serrano.content_negotiation(ids:
|
595
|
-
# Serrano.content_negotiation(ids:
|
596
|
-
# Serrano.content_negotiation(ids:
|
597
|
-
# Serrano.content_negotiation(ids:
|
616
|
+
# Serrano.content_negotiation(ids: doi, format: "datacite-xml")
|
617
|
+
# Serrano.content_negotiation(ids: doi, format: "rdf-xml")
|
618
|
+
# Serrano.content_negotiation(ids: doi, format: "turtle")
|
619
|
+
# Serrano.content_negotiation(ids: doi, format: "citeproc-json")
|
620
|
+
# Serrano.content_negotiation(ids: doi, format: "ris")
|
621
|
+
# Serrano.content_negotiation(ids: doi, format: "bibtex")
|
622
|
+
# Serrano.content_negotiation(ids: doi, format: "bibentry")
|
623
|
+
# Serrano.content_negotiation(ids: doi, format: "bibtex")
|
598
624
|
#
|
599
625
|
# # many DOIs
|
600
|
-
# dois = ['10.5167/UZH-30455','10.5167/UZH-49216','10.5167/UZH-503',
|
626
|
+
# dois = ['10.5167/UZH-30455','10.5167/UZH-49216','10.5167/UZH-503',
|
627
|
+
# '10.5167/UZH-38402','10.5167/UZH-41217']
|
601
628
|
# x = Serrano.content_negotiation(ids: dois)
|
602
629
|
# puts x
|
603
|
-
def self.content_negotiation(ids:, format:
|
630
|
+
def self.content_negotiation(ids:, format: 'bibtex', style: 'apa', locale: 'en-US')
|
631
|
+
ids = Array(ids).map { |x| ERB::Util.url_encode(x) }
|
604
632
|
CNRequest.new(ids, format, style, locale).perform
|
605
633
|
end
|
606
634
|
|
@@ -619,17 +647,17 @@ module Serrano
|
|
619
647
|
# Serrano.citation_count(doi: "10.1016/j.fbr.2012.01.001")
|
620
648
|
# # DOI not found
|
621
649
|
# Serrano.citation_count(doi: "10.1016/j.fbr.2012")
|
622
|
-
def self.citation_count(doi:, url:
|
623
|
-
|
650
|
+
def self.citation_count(doi:, url: 'http://www.crossref.org/openurl/',
|
651
|
+
key: 'cboettig@ropensci.org', options: nil)
|
624
652
|
|
625
|
-
args = { id:
|
626
|
-
opts = args.delete_if { |
|
627
|
-
conn = Faraday.new(:
|
653
|
+
args = { id: 'doi:' + doi, pid: key, noredirect: true }
|
654
|
+
opts = args.delete_if { |_k, v| v.nil? }
|
655
|
+
conn = Faraday.new(url: url, request: options)
|
628
656
|
res = conn.get '', opts
|
629
657
|
x = res.body
|
630
658
|
oc = REXML::Document.new("<doc>#{x}</doc>")
|
631
659
|
value = REXML::XPath.first(oc, '//query').attributes['fl_count'].to_i
|
632
|
-
|
660
|
+
value
|
633
661
|
end
|
634
662
|
|
635
663
|
# Get csl styles
|
@@ -639,7 +667,6 @@ module Serrano
|
|
639
667
|
# @example
|
640
668
|
# Serrano.csl_styles
|
641
669
|
def self.csl_styles
|
642
|
-
|
670
|
+
fetch_styles
|
643
671
|
end
|
644
|
-
|
645
672
|
end
|
data/lib/serrano/cn.rb
CHANGED
@@ -1,20 +1,20 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'serrano/version'
|
4
|
+
require 'serrano/cnrequest'
|
3
5
|
|
4
6
|
##
|
5
7
|
# ContentNegotiation - Content Negotiation class
|
6
8
|
#
|
7
9
|
# @see http://www.crosscite.org/cn/ for details
|
8
10
|
module Serrano
|
9
|
-
|
10
11
|
class ContentNegotiation
|
11
|
-
|
12
12
|
attr_accessor :ids
|
13
13
|
attr_accessor :format
|
14
14
|
attr_accessor :style
|
15
15
|
attr_accessor :locale
|
16
16
|
|
17
|
-
def initialize(ids, format =
|
17
|
+
def initialize(ids, format = 'bibtex', style = 'apa', locale = 'en-US')
|
18
18
|
self.ids = ids
|
19
19
|
self.format = format
|
20
20
|
self.style = style
|
@@ -22,9 +22,7 @@ module Serrano
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def cn
|
25
|
-
CNRequest.new(
|
25
|
+
CNRequest.new(ids, format, style, locale).perform
|
26
26
|
end
|
27
|
-
|
28
27
|
end
|
29
|
-
|
30
28
|
end
|
data/lib/serrano/cnrequest.rb
CHANGED
@@ -1,23 +1,39 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
require 'faraday_middleware'
|
5
|
+
require 'multi_json'
|
6
|
+
require 'serrano/error'
|
6
7
|
require 'serrano/utils'
|
7
8
|
require 'serrano/helpers/configuration'
|
8
9
|
|
10
|
+
CN_FORMAT_HEADERS = { 'rdf-xml' => 'application/rdf+xml',
|
11
|
+
'turtle' => 'text/turtle',
|
12
|
+
'citeproc-json' => 'transform/application/vnd.citationstyles.csl+json',
|
13
|
+
'text' => 'text/x-bibliography',
|
14
|
+
'ris' => 'application/x-research-info-systems',
|
15
|
+
'bibtex' => 'application/x-bibtex',
|
16
|
+
'crossref-xml' => 'application/vnd.crossref.unixref+xml',
|
17
|
+
'datacite-xml' => 'application/vnd.datacite.datacite+xml',
|
18
|
+
'bibentry' => 'application/x-bibtex',
|
19
|
+
'crossref-tdm' => 'application/vnd.crossref.unixsd+xml' }.freeze
|
20
|
+
|
9
21
|
##
|
10
22
|
# Serrano::CNRequest
|
11
23
|
#
|
12
24
|
# Class to perform HTTP requests to the Crossref API
|
13
25
|
module Serrano
|
14
26
|
class CNRequest #:nodoc:
|
15
|
-
|
16
27
|
attr_accessor :ids
|
17
28
|
attr_accessor :format
|
18
29
|
attr_accessor :style
|
19
30
|
attr_accessor :locale
|
20
31
|
|
32
|
+
CN_FORMATS = %w[rdf-xml turtle citeproc-json
|
33
|
+
citeproc-json-ish text ris bibtex
|
34
|
+
crossref-xml datacite-xml bibentry
|
35
|
+
crossref-tdm].freeze
|
36
|
+
|
21
37
|
def initialize(ids, format, style, locale)
|
22
38
|
self.ids = ids
|
23
39
|
self.format = format
|
@@ -26,24 +42,22 @@ module Serrano
|
|
26
42
|
end
|
27
43
|
|
28
44
|
def perform
|
29
|
-
|
30
|
-
raise
|
45
|
+
unless CN_FORMATS.include? format
|
46
|
+
raise 'format not one of accepted types'
|
31
47
|
end
|
32
48
|
|
33
|
-
|
49
|
+
conn = Faraday.new 'https://doi.org/' do |c|
|
34
50
|
c.use FaradayMiddleware::FollowRedirects
|
35
51
|
c.adapter :net_http
|
36
52
|
end
|
37
53
|
|
38
|
-
if
|
39
|
-
|
40
|
-
|
41
|
-
end
|
42
|
-
return make_request(self.ids, self.format, self.style, self.locale)
|
54
|
+
if ids.length == 1
|
55
|
+
self.ids = ids[0] if ids.class == Array
|
56
|
+
return make_request(conn, ids, format, style, locale)
|
43
57
|
else
|
44
58
|
coll = []
|
45
|
-
Array(
|
46
|
-
coll << make_request(x,
|
59
|
+
Array(ids).each do |x|
|
60
|
+
coll << make_request(conn, x, format, style, locale)
|
47
61
|
end
|
48
62
|
return coll
|
49
63
|
end
|
@@ -51,29 +65,29 @@ module Serrano
|
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
54
|
-
def make_request(ids, format, style, locale)
|
55
|
-
type =
|
68
|
+
def make_request(conn, ids, format, style, locale)
|
69
|
+
type = CN_FORMAT_HEADERS.select { |x, _| x.include? format }.values[0]
|
56
70
|
|
57
|
-
if format ==
|
58
|
-
endpt =
|
59
|
-
cr_works = Faraday.new(:
|
71
|
+
if format == 'citeproc-json'
|
72
|
+
endpt = 'http://api.crossref.org/works/' + ids + '/' + type
|
73
|
+
cr_works = Faraday.new(url: endpt)
|
60
74
|
cr_works.headers[:user_agent] = make_ua
|
61
|
-
cr_works.headers[
|
75
|
+
cr_works.headers['X-USER-AGENT'] = make_ua
|
62
76
|
res = cr_works.get
|
63
77
|
else
|
64
|
-
if format ==
|
65
|
-
type = type +
|
78
|
+
if format == 'text'
|
79
|
+
type = type + '; style = ' + style + '; locale = ' + locale
|
66
80
|
end
|
67
81
|
|
68
|
-
res =
|
82
|
+
res = conn.get do |req|
|
69
83
|
req.url ids
|
70
84
|
req.headers['Accept'] = type
|
71
85
|
req.headers[:user_agent] = make_ua
|
72
|
-
req.headers[
|
86
|
+
req.headers['X-USER-AGENT'] = make_ua
|
73
87
|
end
|
74
88
|
end
|
75
89
|
|
76
|
-
|
90
|
+
res.body
|
77
91
|
end
|
78
92
|
|
79
93
|
# parser <- cn_types[[self.format]]
|