zenodo 0.0.1
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 +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +91 -0
- data/Rakefile +2 -0
- data/config/gem_secret.yml.example +1 -0
- data/lib/zenodo.rb +22 -0
- data/lib/zenodo/client.rb +56 -0
- data/lib/zenodo/dsl.rb +21 -0
- data/lib/zenodo/dsl/deposition_actions.rb +19 -0
- data/lib/zenodo/dsl/deposition_files.rb +17 -0
- data/lib/zenodo/dsl/depositions.rb +54 -0
- data/lib/zenodo/errors.rb +10 -0
- data/lib/zenodo/errors/client_error.rb +9 -0
- data/lib/zenodo/errors/resource_not_found_error.rb +8 -0
- data/lib/zenodo/resources.rb +10 -0
- data/lib/zenodo/resources/deposition.rb +9 -0
- data/lib/zenodo/resources/object.rb +29 -0
- data/lib/zenodo/resources/object/attributes.rb +71 -0
- data/lib/zenodo/resources/object/serializers.rb +102 -0
- data/lib/zenodo/utils.rb +8 -0
- data/lib/zenodo/utils/url_helper.rb +17 -0
- data/lib/zenodo/version.rb +3 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/zenodo/client_spec.rb +12 -0
- data/spec/zenodo/dsl/deposition_actions_spec.rb +34 -0
- data/spec/zenodo/dsl/deposition_files_spec.rb +5 -0
- data/spec/zenodo/dsl/depositions_spec.rb +76 -0
- data/zenodo.gemspec +28 -0
- metadata +177 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: cd009682a5116ded3fc34b4c6cd29f379bb58151
|
4
|
+
data.tar.gz: 8314835d3f2e89512b92bc9fa04e430eea5ddc74
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fea91f7edd47ebef37c68a0ee97ff217f229f4799d7a3334c939809e2ca7003eb85302a2c63b09bcfdab01dda7438adafca1b2c67c6a9ef21a7936cde98b617e
|
7
|
+
data.tar.gz: 5c70998c8a61f1d1db0cbe9f73e51090503a591a165c1689cdff880ee6bdda01a6857f95c9c4608cee8b0918f0231d8d8a5324fcb0fa4f5a5a707682715a5383
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 David Iorns
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
# Zenodo
|
2
|
+
|
3
|
+
A Ruby wrapper for the Zenodo API.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
gem 'zenodo'
|
11
|
+
```
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install zenodo
|
20
|
+
|
21
|
+
Due to the use of keyword arguments this gem requires Ruby 2.0 and above.
|
22
|
+
|
23
|
+
## Configuration
|
24
|
+
|
25
|
+
This gem uses VCR for testing. https://github.com/vcr/vcr
|
26
|
+
|
27
|
+
To run gem tests complete the following:
|
28
|
+
|
29
|
+
1. Obtain a Zenodo API token from their site. https://zenodo.org.
|
30
|
+
2. Create file gem_secret.yml in the gems config folder.
|
31
|
+
3. Add the following to your gem_secret.yml file. ```zenodo_api_key: '<YOUR API TOKEN>'```
|
32
|
+
4. Run rspec as normal.
|
33
|
+
|
34
|
+
VCR will create fixtures in the spec/fixtures/vcr_cassettes folder.
|
35
|
+
|
36
|
+
## Usage
|
37
|
+
|
38
|
+
Set the client API key.
|
39
|
+
```
|
40
|
+
Zenodo.api_key = <your API key>
|
41
|
+
```
|
42
|
+
|
43
|
+
Get depositions.
|
44
|
+
```
|
45
|
+
depositions = Zenodo.client.get_depositions
|
46
|
+
```
|
47
|
+
|
48
|
+
Get a deposition.
|
49
|
+
```
|
50
|
+
deposition = Zenodo.client.get_deposition(id: 1)
|
51
|
+
```
|
52
|
+
|
53
|
+
Create a deposition.
|
54
|
+
```
|
55
|
+
# Build JSON serialized attributes.
|
56
|
+
# The gem won't do this for you. You need to build a serializer that meets your needs."
|
57
|
+
deposition_attributes = {
|
58
|
+
'metadata' => {
|
59
|
+
'title' => 'My first upload',
|
60
|
+
'upload_type' => 'poster',
|
61
|
+
'description' => 'This is my first upload',
|
62
|
+
'creators' =>[{'name' => 'Doe, John','affiliation' => 'ZENODO'}]
|
63
|
+
}
|
64
|
+
}
|
65
|
+
|
66
|
+
# Create the deposition.
|
67
|
+
deposition = Zenodo.client.create_deposition(deposition: deposition_attributes)
|
68
|
+
```
|
69
|
+
|
70
|
+
Update a deposition.
|
71
|
+
```
|
72
|
+
# Build JSON serialized attributes.
|
73
|
+
# The gem won't do this for you. You need to build a serializer that meets your needs."
|
74
|
+
# deposition_attributes = <same as create>
|
75
|
+
|
76
|
+
# Update the deposition.
|
77
|
+
deposition = Zenodo.client.update_deposition(id: 1, deposition: deposition_attributes)
|
78
|
+
```
|
79
|
+
|
80
|
+
Delete a deposition.
|
81
|
+
```
|
82
|
+
Zenodo.client.delete_deposition(id: 1)
|
83
|
+
```
|
84
|
+
|
85
|
+
## Contributing
|
86
|
+
|
87
|
+
1. Fork it ( https://github.com/[my-github-username]/zenodo/fork )
|
88
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
89
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
90
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
91
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
zenodo_api_key: 'YOUR TESTING API KEY GOES HERE'
|
data/lib/zenodo.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'zenodo/version'
|
2
|
+
|
3
|
+
module Zenodo
|
4
|
+
autoload :Client, 'zenodo/client'
|
5
|
+
autoload :DSL, 'zenodo/dsl'
|
6
|
+
autoload :Resources, 'zenodo/resources'
|
7
|
+
autoload :Errors, 'zenodo/errors'
|
8
|
+
autoload :Utils, 'zenodo/utils'
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# @return [String]
|
12
|
+
attr_accessor :api_key
|
13
|
+
attr_accessor :logger
|
14
|
+
end
|
15
|
+
|
16
|
+
module_function
|
17
|
+
|
18
|
+
# @return [Zenodo::Client]
|
19
|
+
def client
|
20
|
+
@client ||= Client.new(Zenodo.api_key)
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'faraday'
|
2
|
+
require 'json'
|
3
|
+
require 'openssl'
|
4
|
+
require 'active_support/all'
|
5
|
+
require 'zenodo/dsl'
|
6
|
+
require 'zenodo/errors'
|
7
|
+
require 'zenodo/utils'
|
8
|
+
|
9
|
+
module Zenodo
|
10
|
+
class Client
|
11
|
+
include DSL
|
12
|
+
include Errors
|
13
|
+
include Utils
|
14
|
+
|
15
|
+
URL = 'https://zenodo.org/api/'
|
16
|
+
REQUESTS = [:get, :post, :put, :delete]
|
17
|
+
HEADERS = {'Accept' => 'application/json', 'Content-Type' => 'application/json'}
|
18
|
+
|
19
|
+
# @param [String] api_key
|
20
|
+
def initialize(api_key = Zenodo.api_key)
|
21
|
+
@api_key = api_key
|
22
|
+
|
23
|
+
# Setup HTTP request connection to Zenodo.
|
24
|
+
@connection ||= Faraday.new do |builder|
|
25
|
+
builder.request :url_encoded
|
26
|
+
builder.response :logger if Zenodo.logger
|
27
|
+
builder.adapter Faraday.default_adapter
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# @param [:get, :post, :put, :delete] method.
|
32
|
+
# @param [String] path.
|
33
|
+
# @param [Hash] query (optional).
|
34
|
+
# @param [Hash] headers request headers (optional).
|
35
|
+
# @raise [ArgumentError] If the response is blank.
|
36
|
+
# @raise [ResourceNotFoundError] If the response code is 404.
|
37
|
+
# @raise [ClientError] If the response code is not in the success range.
|
38
|
+
# @return [Faraday::Response] server response.
|
39
|
+
def request(method, path, query = {}, headers = HEADERS)
|
40
|
+
raise ArgumentError, "Unsupported method #{method.inspect}. Only :get, :post, :put, :delete are allowed" unless REQUESTS.include?(method)
|
41
|
+
|
42
|
+
token_url = UrlHelper.build_url(path: "#{URL}#{path}", params: {access_token: @api_key})
|
43
|
+
payload = !query.blank? ? JSON.generate(query) : nil
|
44
|
+
response = @connection.run_request(method, token_url, payload, headers)
|
45
|
+
|
46
|
+
case response.status.to_i
|
47
|
+
when 200..299
|
48
|
+
return response
|
49
|
+
when 404
|
50
|
+
raise ResourceNotFoundError.new(response: response)
|
51
|
+
else
|
52
|
+
raise ClientError.new(response: response)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
data/lib/zenodo/dsl.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'zenodo'
|
2
|
+
|
3
|
+
module Zenodo
|
4
|
+
module DSL
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'zenodo/dsl/depositions'
|
9
|
+
require 'zenodo/dsl/deposition_files'
|
10
|
+
require 'zenodo/dsl/deposition_actions'
|
11
|
+
require 'zenodo/utils'
|
12
|
+
|
13
|
+
module Zenodo
|
14
|
+
module DSL
|
15
|
+
include Depositions
|
16
|
+
include DepositionFiles
|
17
|
+
include DepositionActions
|
18
|
+
include Utils
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'zenodo/dsl'
|
2
|
+
|
3
|
+
module Zenodo
|
4
|
+
module DSL::DepositionActions
|
5
|
+
# Publish POST deposit/depositions/:id/actions/publish
|
6
|
+
# Publishes a deposition.
|
7
|
+
# @param [String, Fixnum] id A deposition's ID.
|
8
|
+
# @raise [ArgumentError] If the method arguments are blank.
|
9
|
+
# @return [Zenodo::Resources::deposition, nil].
|
10
|
+
def publish_deposition(id:)
|
11
|
+
raise ArgumentError, "ID cannot be blank" if id.blank?
|
12
|
+
Resources::Deposition.parse(request(:post, "deposit/depositions/#{id}/actions/publish", nil, nil))
|
13
|
+
end
|
14
|
+
|
15
|
+
# Edit POST deposit/depositions/:id/actions/edit
|
16
|
+
|
17
|
+
# Discard POST deposit/depositions/:id/actions/discard
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'zenodo/dsl'
|
2
|
+
|
3
|
+
module Zenodo
|
4
|
+
module DSL::DepositionFiles
|
5
|
+
# List GET deposit/depositions/:id/files
|
6
|
+
|
7
|
+
# Create (upload) POST deposit/depositions/:id/files
|
8
|
+
|
9
|
+
# Sort PUT deposit/depositions/:id/files
|
10
|
+
|
11
|
+
# Retrieve GET deposit/depositions/:id/files/:file_id
|
12
|
+
|
13
|
+
# Update PUT deposit/depositions/:id/files/:file_id
|
14
|
+
|
15
|
+
# Delete DELETE deposit/depositions/:id/files/:file_id
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'zenodo/dsl'
|
2
|
+
|
3
|
+
module Zenodo
|
4
|
+
module DSL::Depositions
|
5
|
+
# GET /Deposit/Depositions
|
6
|
+
# Get depositions.
|
7
|
+
# @return [Array, nil].
|
8
|
+
def get_depositions
|
9
|
+
Resources::Deposition.parse(request(:get, "deposit/depositions/", nil, nil))
|
10
|
+
end
|
11
|
+
|
12
|
+
# GET /Deposit/Deposition/{id}
|
13
|
+
# Get a deposition.
|
14
|
+
# @param [String, Fixnum] id A deposition's ID.
|
15
|
+
# @raise [ArgumentError] If the method arguments are blank.
|
16
|
+
# @return [Zenodo::Resources::deposition, nil].
|
17
|
+
def get_deposition(id:)
|
18
|
+
raise ArgumentError, "ID cannot be blank" if id.blank?
|
19
|
+
Resources::Deposition.parse(request(:get, "deposit/depositions/#{id}"))
|
20
|
+
end
|
21
|
+
|
22
|
+
# POST /Deposit/Depositions
|
23
|
+
# Creates a deposition.
|
24
|
+
# @param [Hash] deposition The deposition to create.
|
25
|
+
# @raise [ArgumentError] If the method arguments are blank.
|
26
|
+
# @return [Zenodo::Resources::deposition, nil].
|
27
|
+
def create_deposition(deposition:)
|
28
|
+
raise ArgumentError, "Deposition cannot be blank" if deposition.blank?
|
29
|
+
Resources::Deposition.parse(request(:post, "deposit/depositions/", deposition))
|
30
|
+
end
|
31
|
+
|
32
|
+
# PUT /Deposit/Depositions
|
33
|
+
# Updates a deposition.
|
34
|
+
# @param [String, Fixnum] id A deposition's ID.
|
35
|
+
# @param [Hash] deposition The deposition to update.
|
36
|
+
# @raise [ArgumentError] If the method arguments are blank.
|
37
|
+
# @return [Zenodo::Resources::deposition, nil].
|
38
|
+
def update_deposition(id:, deposition:)
|
39
|
+
raise ArgumentError, "ID cannot be blank" if id.blank?
|
40
|
+
raise ArgumentError, "Deposition cannot be blank" if deposition.blank?
|
41
|
+
Resources::Deposition.parse(request(:put, "deposit/depositions/#{id}", deposition))
|
42
|
+
end
|
43
|
+
|
44
|
+
# DELETE /Deposit/Depositions/{id}
|
45
|
+
# Deletes a deposition.
|
46
|
+
# @param [String, Fixnum] id A deposition's ID.
|
47
|
+
# @raise [ArgumentError] If the method arguments are blank.
|
48
|
+
# @return [Faraday::Response].
|
49
|
+
def delete_deposition(id:)
|
50
|
+
raise ArgumentError, "ID cannot be blank" if id.blank?
|
51
|
+
request(:delete, "deposit/depositions/#{id}")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
require 'json'
|
3
|
+
require 'time'
|
4
|
+
|
5
|
+
module Zenodo
|
6
|
+
module Resources
|
7
|
+
class Object < SimpleDelegator
|
8
|
+
require 'zenodo/resources/object/serializers'
|
9
|
+
require 'zenodo/resources/object/attributes'
|
10
|
+
|
11
|
+
include Serializers
|
12
|
+
include Attributes
|
13
|
+
|
14
|
+
# Define common attributes, applicable to different resources
|
15
|
+
attribute :date_created_utc, Time
|
16
|
+
attribute :date_updated_utc, Time
|
17
|
+
|
18
|
+
def inspect
|
19
|
+
"#<#{self.class.name}:#{'0x00%x' % (object_id << 1)} #{inspect_attributes}>"
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def inspect_attributes
|
25
|
+
attributes.map { |key, value| "@#{key}=#{value.inspect}" }.join(' ')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Zenodo::Resources::Object::Attributes
|
2
|
+
module ClassMethods
|
3
|
+
def attributes
|
4
|
+
@attributes ||=
|
5
|
+
begin
|
6
|
+
if superclass.respond_to?(:attributes)
|
7
|
+
superclass.attributes.dup
|
8
|
+
else
|
9
|
+
Hash.new { |hash, key| hash[key] = ::Object }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
# @return [Module] module holding all attribute accessors
|
15
|
+
def attributes_module
|
16
|
+
@attributes_module ||= const_set(:AttributeMethods, Module.new)
|
17
|
+
end
|
18
|
+
|
19
|
+
def define_attribute_accessor(name, type = nil)
|
20
|
+
type ||= attributes[name.to_sym] || Object
|
21
|
+
attributes_module.send(:define_method, name) do
|
22
|
+
deserialize_attribute(name, type)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def attribute(name, type = String)
|
27
|
+
attributes[name] = type
|
28
|
+
|
29
|
+
define_attribute_accessor(name, type)
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :has_many, :attribute
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.included(base)
|
36
|
+
base.extend(ClassMethods)
|
37
|
+
super
|
38
|
+
end
|
39
|
+
|
40
|
+
def attributes
|
41
|
+
{}.tap do |result|
|
42
|
+
__getobj__.keys.each do |key|
|
43
|
+
attribute = key.to_s.downcase
|
44
|
+
result[attribute] = public_send(attribute)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def method_missing(name, *args, &block)
|
50
|
+
attribute = name.to_s.upcase
|
51
|
+
if __getobj__.key?(attribute)
|
52
|
+
self.class.define_attribute_accessor(name)
|
53
|
+
deserialize_attribute(name, self.class.attributes[name.to_sym])
|
54
|
+
else
|
55
|
+
super
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def respond_to_missing?(name, include_all = false)
|
62
|
+
__getobj__.key?(name.to_s.upcase) || super(name, include_all)
|
63
|
+
end
|
64
|
+
|
65
|
+
# @param [String, Symbol] name
|
66
|
+
# @param [Class, #to_s] type
|
67
|
+
def deserialize_attribute(name, type)
|
68
|
+
raw = __getobj__[name.to_s.upcase]
|
69
|
+
self.class.serializer_for(type).deserialize(raw)
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'logger'
|
2
|
+
module Zenodo
|
3
|
+
module Resources
|
4
|
+
class Object
|
5
|
+
module Serializers
|
6
|
+
module Object
|
7
|
+
def self.serialize(value)
|
8
|
+
value.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.deserialize(value)
|
12
|
+
case value
|
13
|
+
when Array
|
14
|
+
value.map { |v| v.deep_transform_keys{ |key| key.downcase } }
|
15
|
+
when Hash
|
16
|
+
value.deep_transform_keys{ |key| key.downcase }
|
17
|
+
else
|
18
|
+
value
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Time
|
24
|
+
def self.serialize(value)
|
25
|
+
value.utc.xmlschema
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.deserialize(value)
|
29
|
+
::Time.parse(value)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
module ClassMethods
|
34
|
+
# @return [Hash] corresponding serializers for different attributes
|
35
|
+
def serializers
|
36
|
+
@serializers ||= {}
|
37
|
+
end
|
38
|
+
|
39
|
+
# @param [String, Symbol] type type of attribute to be serialized or deserialized
|
40
|
+
# @return [#serialize, #deserialize] serializer for provided type
|
41
|
+
def serializer_for(type)
|
42
|
+
serializers[type] ||=
|
43
|
+
begin
|
44
|
+
class_symbol = type.to_s.to_sym
|
45
|
+
if type.respond_to?(:deserialize) && type.respond_to?(:serialize)
|
46
|
+
type
|
47
|
+
elsif Serializers.constants.include?(class_symbol)
|
48
|
+
Serializers.const_get(class_symbol)
|
49
|
+
elsif Resources.constants.include?(class_symbol)
|
50
|
+
Resources.const_get(class_symbol)
|
51
|
+
else
|
52
|
+
Serializers::Object
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Deserialize a Faraday response.
|
58
|
+
# @param [Faraday::Response] response.
|
59
|
+
# @raise [ArgumentError] If the response is blank.
|
60
|
+
# @return [Object, nil].
|
61
|
+
def deserialize(response)
|
62
|
+
raise ArgumentError, "Response cannot be blank" if response.blank?
|
63
|
+
|
64
|
+
attributes = response.body
|
65
|
+
begin
|
66
|
+
attributes = JSON.parse(response.body)
|
67
|
+
case attributes
|
68
|
+
when Array
|
69
|
+
return attributes.map { |object| new(object) }
|
70
|
+
when Hash
|
71
|
+
return new(attributes)
|
72
|
+
end
|
73
|
+
rescue JSON::ParserError
|
74
|
+
logger = Logger.new(STDOUT)
|
75
|
+
logger.error("Could not parse: #{response.body}")
|
76
|
+
end
|
77
|
+
nil
|
78
|
+
end
|
79
|
+
|
80
|
+
alias_method :parse, :deserialize
|
81
|
+
|
82
|
+
def serialize(object)
|
83
|
+
object.serialize
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.included(base)
|
88
|
+
super
|
89
|
+
base.extend ClassMethods
|
90
|
+
end
|
91
|
+
|
92
|
+
def serialize
|
93
|
+
{}.tap do |result|
|
94
|
+
attributes.each do |name, value|
|
95
|
+
result[name.upcase] = self.class.serializer_for(name).serialize(value)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
data/lib/zenodo/utils.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
module Zenodo
|
2
|
+
module Utils
|
3
|
+
class UrlHelper
|
4
|
+
# Build a URL with a querystring containing optional params if supplied.
|
5
|
+
# @param [UrlHelper] path The name of the resource path as per the URL e.g. contacts.
|
6
|
+
# @param [Hash] params A hash of params we're turning into a querystring.
|
7
|
+
# @return [UrlHelper] The URL of the resource with required params.
|
8
|
+
def self.build_url(path:, params:)
|
9
|
+
params.delete_if {|k,v| v.blank?}
|
10
|
+
params = params.to_query
|
11
|
+
query = path
|
12
|
+
query << ("?" + params) unless params.blank?
|
13
|
+
query
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'webmock/rspec'
|
2
|
+
require 'zenodo'
|
3
|
+
require 'vcr'
|
4
|
+
include Zenodo::Resources
|
5
|
+
|
6
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
7
|
+
cnf = YAML::load_file(File.join(APP_ROOT, 'config/gem_secret.yml'))
|
8
|
+
zenodo_api_key = cnf['zenodo_api_key']
|
9
|
+
|
10
|
+
VCR.configure do |c|
|
11
|
+
c.cassette_library_dir = 'spec/fixtures/vcr_cassettes'
|
12
|
+
c.hook_into :webmock
|
13
|
+
c.filter_sensitive_data('<ZENODO_API_KEY>') { zenodo_api_key }
|
14
|
+
end
|
15
|
+
|
16
|
+
RSpec.configure do |config|
|
17
|
+
config.before do
|
18
|
+
Zenodo.api_key = zenodo_api_key
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zenodo::Client do
|
4
|
+
subject(:client) { Zenodo::Client.new }
|
5
|
+
|
6
|
+
it 'makes request to zenodo.org/api' do
|
7
|
+
VCR.use_cassette('z_zenodo_client_status_check') do
|
8
|
+
# response = client.request(:get, 'Users')
|
9
|
+
# expect(response.status).to eq(200)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zenodo::DSL::DepositionActions do
|
4
|
+
let(:deposition_attributes) do
|
5
|
+
{
|
6
|
+
'metadata' => {
|
7
|
+
'title' => 'My first upload',
|
8
|
+
'upload_type' => 'poster',
|
9
|
+
'description' => 'This is my first upload',
|
10
|
+
'creators' =>[{'name' => 'Doe, Jane','affiliation' => 'ZENODO'}]
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
let!(:deposition_id) do
|
15
|
+
VCR.use_cassette('create_deposition_for_publishing') do
|
16
|
+
deposition = Zenodo.client.create_deposition(deposition: deposition_attributes)
|
17
|
+
deposition['id']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Publish POST deposit/depositions/:id/actions/publish
|
22
|
+
describe '#publish_deposition' do
|
23
|
+
it 'publishes a deposition' do
|
24
|
+
VCR.use_cassette('publish_deposition') do
|
25
|
+
response = Zenodo.client.publish_deposition(id: deposition_id)
|
26
|
+
expect(response).to be_a(Deposition)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Edit POST deposit/depositions/:id/actions/edit
|
32
|
+
|
33
|
+
# Discard POST deposit/depositions/:id/actions/discard
|
34
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Zenodo::DSL::Depositions do
|
4
|
+
let(:deposition_attributes) do
|
5
|
+
{
|
6
|
+
'metadata' => {
|
7
|
+
'title' => 'My first upload',
|
8
|
+
'upload_type' => 'poster',
|
9
|
+
'description' => 'This is my first upload',
|
10
|
+
'creators' =>[{'name' => 'Doe, John','affiliation' => 'ZENODO'}]
|
11
|
+
}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
let!(:deposition_id) do
|
15
|
+
VCR.use_cassette('create_deposition') do
|
16
|
+
deposition = Zenodo.client.create_deposition(deposition: deposition_attributes)
|
17
|
+
deposition['id']
|
18
|
+
end
|
19
|
+
end
|
20
|
+
let!(:deleted_deposition_id) do
|
21
|
+
VCR.use_cassette('create_deposition_for_deletion') do
|
22
|
+
deposition = Zenodo.client.create_deposition(deposition: deposition_attributes)
|
23
|
+
deposition['id']
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# GET /Deposit/Depositions
|
28
|
+
describe '#get_depositions' do
|
29
|
+
it 'returns an array of depositions' do
|
30
|
+
VCR.use_cassette('get_depositions') do
|
31
|
+
depositions = Zenodo.client.get_depositions
|
32
|
+
expect(depositions).to be_a(Array)
|
33
|
+
expect(depositions.first).to be_a(Deposition)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# GET /Deposit/Depositions/{id}
|
39
|
+
describe '#get_deposition' do
|
40
|
+
it 'returns a deposition' do
|
41
|
+
VCR.use_cassette('get_deposition') do
|
42
|
+
expect(Zenodo.client.get_deposition(id: deposition_id)).to be_a(Deposition)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# POST /Deposit/Depositions
|
48
|
+
describe '#create_deposition' do
|
49
|
+
it 'creates a deposition' do
|
50
|
+
VCR.use_cassette('create_deposition') do
|
51
|
+
response = Zenodo.client.create_deposition(deposition: deposition_attributes)
|
52
|
+
expect(response).to be_a(Deposition)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# PUT /Deposit/Depositions
|
58
|
+
describe '#update_deposition' do
|
59
|
+
it 'updates a deposition' do
|
60
|
+
VCR.use_cassette('update_deposition') do
|
61
|
+
response = Zenodo.client.update_deposition(id: deposition_id, deposition: deposition_attributes)
|
62
|
+
expect(response).to be_a(Deposition)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# DELETE /Deposit/Depositions/{id}
|
68
|
+
describe '#delete_deposition' do
|
69
|
+
it 'returns a response with code 204' do
|
70
|
+
VCR.use_cassette('delete_deposition') do
|
71
|
+
response = Zenodo.client.delete_deposition(id: deleted_deposition_id)
|
72
|
+
expect(response.status).to eq(204)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/zenodo.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'zenodo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "zenodo"
|
8
|
+
spec.version = Zenodo::VERSION
|
9
|
+
spec.authors = ["David Iorns"]
|
10
|
+
spec.email = ["david.iorns@gmail.com"]
|
11
|
+
spec.summary = 'A Ruby wrapper for the Zenodo API.'
|
12
|
+
spec.homepage = ""
|
13
|
+
spec.license = "MIT"
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
18
|
+
spec.require_paths = ["lib"]
|
19
|
+
|
20
|
+
spec.add_dependency 'faraday'
|
21
|
+
spec.add_dependency 'activesupport'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.0.0'
|
26
|
+
spec.add_development_dependency 'webmock', '~> 1.18.0'
|
27
|
+
spec.add_development_dependency 'vcr'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,177 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: zenodo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- David Iorns
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-11-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: faraday
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: 3.0.0
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: 3.0.0
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: webmock
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: 1.18.0
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.18.0
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: vcr
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description:
|
112
|
+
email:
|
113
|
+
- david.iorns@gmail.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- Gemfile
|
120
|
+
- LICENSE.txt
|
121
|
+
- README.md
|
122
|
+
- Rakefile
|
123
|
+
- config/gem_secret.yml.example
|
124
|
+
- lib/zenodo.rb
|
125
|
+
- lib/zenodo/client.rb
|
126
|
+
- lib/zenodo/dsl.rb
|
127
|
+
- lib/zenodo/dsl/deposition_actions.rb
|
128
|
+
- lib/zenodo/dsl/deposition_files.rb
|
129
|
+
- lib/zenodo/dsl/depositions.rb
|
130
|
+
- lib/zenodo/errors.rb
|
131
|
+
- lib/zenodo/errors/client_error.rb
|
132
|
+
- lib/zenodo/errors/resource_not_found_error.rb
|
133
|
+
- lib/zenodo/resources.rb
|
134
|
+
- lib/zenodo/resources/deposition.rb
|
135
|
+
- lib/zenodo/resources/object.rb
|
136
|
+
- lib/zenodo/resources/object/attributes.rb
|
137
|
+
- lib/zenodo/resources/object/serializers.rb
|
138
|
+
- lib/zenodo/utils.rb
|
139
|
+
- lib/zenodo/utils/url_helper.rb
|
140
|
+
- lib/zenodo/version.rb
|
141
|
+
- spec/spec_helper.rb
|
142
|
+
- spec/zenodo/client_spec.rb
|
143
|
+
- spec/zenodo/dsl/deposition_actions_spec.rb
|
144
|
+
- spec/zenodo/dsl/deposition_files_spec.rb
|
145
|
+
- spec/zenodo/dsl/depositions_spec.rb
|
146
|
+
- zenodo.gemspec
|
147
|
+
homepage: ''
|
148
|
+
licenses:
|
149
|
+
- MIT
|
150
|
+
metadata: {}
|
151
|
+
post_install_message:
|
152
|
+
rdoc_options: []
|
153
|
+
require_paths:
|
154
|
+
- lib
|
155
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - ">="
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - ">="
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
requirements: []
|
166
|
+
rubyforge_project:
|
167
|
+
rubygems_version: 2.4.4
|
168
|
+
signing_key:
|
169
|
+
specification_version: 4
|
170
|
+
summary: A Ruby wrapper for the Zenodo API.
|
171
|
+
test_files:
|
172
|
+
- spec/spec_helper.rb
|
173
|
+
- spec/zenodo/client_spec.rb
|
174
|
+
- spec/zenodo/dsl/deposition_actions_spec.rb
|
175
|
+
- spec/zenodo/dsl/deposition_files_spec.rb
|
176
|
+
- spec/zenodo/dsl/depositions_spec.rb
|
177
|
+
has_rdoc:
|