collection_json 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +49 -0
- data/Rakefile +2 -0
- data/collection_json.gemspec +17 -0
- data/lib/collection_json/crud_operations.rb +4 -0
- data/lib/collection_json/query.rb +4 -0
- data/lib/collection_json/version.rb +3 -0
- data/lib/collection_json.rb +84 -0
- data/spec/lib/collection_json_spec.rb +97 -0
- data/spec/spec_helper.rb +13 -0
- metadata +59 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Mark Burns
|
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,49 @@
|
|
1
|
+
# CollectionJson
|
2
|
+
|
3
|
+
A gem to help with producing Hypermedia APIs with a MIME type of
|
4
|
+
'application/vnd.collection+json'
|
5
|
+
|
6
|
+
see http://amundsen.com/media-types/collection/format/#link-relations
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'collection_json'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install collection_json
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
This is still experimental at the moment.
|
25
|
+
The aim is to be able to include the gem in a Rack app and make for easy
|
26
|
+
generation of hypermedia APIs from your resources, effectively something like a
|
27
|
+
hypermedia presenter.
|
28
|
+
|
29
|
+
I'm not clear on the details of how the objects will be presented as
|
30
|
+
Collection+JSON as there is an emphasis on Collections rather than individual
|
31
|
+
items. This makes sense if you think of Rails controllers being plural.
|
32
|
+
|
33
|
+
But it is reasonably different to being used to having the primary unit of data
|
34
|
+
being a singular model.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
SingularActiveRecordObject.all
|
38
|
+
|
39
|
+
#versus:
|
40
|
+
PluralJsonCollection.new collection_of_objects
|
41
|
+
```
|
42
|
+
|
43
|
+
## Contributing
|
44
|
+
|
45
|
+
1. Fork it
|
46
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
47
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
48
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
49
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/collection_json/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Mark Burns"]
|
6
|
+
gem.email = ["markthedeveloper@gmail.com"]
|
7
|
+
gem.description = %q{Help create Collection+JSON hypermedia APIs}
|
8
|
+
gem.summary = %q{As specified by: http://amundsen.com/media-types/collection/format/#objects}
|
9
|
+
gem.homepage = "https://github.com/markburns/collection_json"
|
10
|
+
|
11
|
+
gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
12
|
+
gem.files = `git ls-files`.split("\n")
|
13
|
+
gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
14
|
+
gem.name = "collection_json"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = CollectionJson::VERSION
|
17
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'active_support/core_ext/string'
|
3
|
+
require 'collection_json/version'
|
4
|
+
|
5
|
+
#see http://amundsen.com/media-types/collection/format/#link-relations
|
6
|
+
|
7
|
+
# 2.1. collection
|
8
|
+
# The collection object contains all the "records" in the representation.
|
9
|
+
# This is a REQUIRED object and there MUST NOT be more than one collection object in a Collection+JSON document.
|
10
|
+
# It is a top-level document property.
|
11
|
+
module CollectionJson
|
12
|
+
attr_writer :href, :links, :items, :queries, :template
|
13
|
+
|
14
|
+
def to_json
|
15
|
+
{collection: collection}.to_json
|
16
|
+
end
|
17
|
+
|
18
|
+
def collection
|
19
|
+
{ version: "1.0", #The collection object SHOULD have a version property. For this release,
|
20
|
+
#the value of the version property MUST be set to 1.0.
|
21
|
+
#If there is no version property present, it should be assumed to be set to 1.0.
|
22
|
+
|
23
|
+
href: href, #The collection object SHOULD have an href property.
|
24
|
+
#The href property MUST contain a valid URI.
|
25
|
+
#This URI SHOULD represent the address used to retrieve a representation of the document.
|
26
|
+
#This URI MAY be used to add a new record
|
27
|
+
|
28
|
+
links: links, #The collection object MAY have an links array child property
|
29
|
+
|
30
|
+
items: items, #The collection object MAY have an items array child property.
|
31
|
+
#Each item in a Collection+JSONcollection has an assigned URI (via the href property) and an optional array of one or more data elements along with an optional array of one or more link elements.
|
32
|
+
queries: queries, #The collection object MAY have an queries array child property.
|
33
|
+
|
34
|
+
template: template, #The collection object MAY have an template object child property.
|
35
|
+
error: error #The collection object MAY have an error object child property.
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
def href
|
40
|
+
@href || "/#{self.class.to_s.underscore.pluralize}"
|
41
|
+
end
|
42
|
+
|
43
|
+
#3.4 links
|
44
|
+
#The links array is an OPTIONAL child property of the items array
|
45
|
+
def links
|
46
|
+
#The Collection+JSON hypermedia type has a limited set of predefined link
|
47
|
+
#relation values and supports additional values applied by implementors
|
48
|
+
#in order to better describe the application domain to which the media
|
49
|
+
#type is applied.
|
50
|
+
@links ||= []
|
51
|
+
end
|
52
|
+
|
53
|
+
def items
|
54
|
+
@items
|
55
|
+
end
|
56
|
+
|
57
|
+
#3.3. queries
|
58
|
+
#The queries array is an OPTIONAL top-level property of the Collection+JSON document.
|
59
|
+
def queries
|
60
|
+
@queries ||= []
|
61
|
+
end
|
62
|
+
|
63
|
+
#The template object contains all the input elements used to add or edit collection "records." This is an OPTIONAL object and there MUST NOT be more than one template object in a Collection+JSON document. It is a top-level document property.
|
64
|
+
#The template object SHOULD have a data array child property.
|
65
|
+
def template
|
66
|
+
@template ||= {}
|
67
|
+
end
|
68
|
+
|
69
|
+
#2.2. error
|
70
|
+
#The error object contains addiitional information on the latest error
|
71
|
+
#condition reported by the server.
|
72
|
+
#This is an OPTIONAL object and there MUST NOT be more than one error
|
73
|
+
#object in a Collection+JSON document.
|
74
|
+
#
|
75
|
+
#It is a top-level document property.
|
76
|
+
#
|
77
|
+
#The following elements MAY appear as child properties of the error object:
|
78
|
+
#code message and title.
|
79
|
+
Error = Struct.new :code, :message, :title
|
80
|
+
|
81
|
+
def error
|
82
|
+
@error
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require File.expand_path('spec/spec_helper')
|
2
|
+
|
3
|
+
|
4
|
+
class HerdOfSpiderCows
|
5
|
+
include CollectionJson
|
6
|
+
extend CollectionJson::CrudOperations
|
7
|
+
extend CollectionJson::Query
|
8
|
+
|
9
|
+
def initialize items, links=[], queries=[], template={}
|
10
|
+
@items, @links, @queries, @template = items, links, queries, template
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
#see http://amundsen.com/media-types/collection/format/#link-relations
|
15
|
+
describe CollectionJson do
|
16
|
+
let(:spider_cows) { HerdOfSpiderCows.new [1,2,3],
|
17
|
+
['/spider_cow/1', '/spider_cow/2', 'spider_cow/3'] }
|
18
|
+
|
19
|
+
|
20
|
+
describe "#href" do
|
21
|
+
specify {spider_cows.href.should == "/herd_of_spider_cows" }
|
22
|
+
|
23
|
+
specify do
|
24
|
+
spider_cows.href= "/gathering_of_spider_cows"
|
25
|
+
spider_cows.href.should == "/gathering_of_spider_cows"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "#links" do
|
30
|
+
specify "has links" do
|
31
|
+
spider_cows.links.should ==
|
32
|
+
['/spider_cow/1', '/spider_cow/2', 'spider_cow/3']
|
33
|
+
end
|
34
|
+
|
35
|
+
specify do
|
36
|
+
spider_cows.links = %w[egg banana cheese]
|
37
|
+
spider_cows.links.should == %w[egg banana cheese]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
describe "#collection" do
|
42
|
+
specify do
|
43
|
+
spider_cows.collection.should be_a Hash
|
44
|
+
end
|
45
|
+
|
46
|
+
specify "has items" do
|
47
|
+
spider_cows.collection[:items].should == [1,2,3]
|
48
|
+
end
|
49
|
+
|
50
|
+
specify "has links" do
|
51
|
+
spider_cows.collection[:links].should ==
|
52
|
+
['/spider_cow/1', '/spider_cow/2', 'spider_cow/3']
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
describe CollectionJson::CrudOperations do
|
59
|
+
describe ".create" do
|
60
|
+
#1.1.2. Adding an Item
|
61
|
+
#To create a new item in the collection, the client first uses the template object to compose a valid item representation and then uses HTTP POST to send that representation to the server for processing.
|
62
|
+
|
63
|
+
#If the item resource was created successfully, the server responds with a status code of 201 and a Location header that contains the URI of the newly created item resource.
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
describe ".read" do
|
68
|
+
#1.1.3. Reading an Item
|
69
|
+
#Clients can retrieve an existing item resource by sending an HTTP GET request to the URI of an item resource.
|
70
|
+
#If the request is valid, the server will respond with a representation of that item resource.
|
71
|
+
end
|
72
|
+
|
73
|
+
describe ".update" do
|
74
|
+
#1.1.4. Updating an Item
|
75
|
+
#To update an existing resource, the client uses the template object as a guide to composing a replacement item representation and then uses HTTP PUT to send that representation to the server.
|
76
|
+
#If the update is successful, the server will respond with HTTP status code 200 and possibly a representation of the updated item resource representation.
|
77
|
+
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
describe ".delete" do
|
82
|
+
#1.1.5. Deleting an Item
|
83
|
+
#Clients can delete existing resources by sending an HTTP DELETE request to the URI of the item resource.
|
84
|
+
|
85
|
+
#If the delete request is successful, the server SHOULD respond with an HTTP status code of 204.
|
86
|
+
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
#1.2. Query Templates
|
92
|
+
#Clients that support the Collection+JSON media type SHOULD be able to recognize and parse query templates found within responses. Query templates consist of a data array associated with an href property. The queries array supports query templates.
|
93
|
+
|
94
|
+
#For query templates, the name/value pairs of the data array set are appended to the URI found in the href property associated with the queries array (with a question-mark ["?"] as separator) and this new URI is sent to the processing agent.
|
95
|
+
describe CollectionJson::Query do
|
96
|
+
|
97
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper.rb"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
Dir['./lib/**/*.rb'].each {|r| require r}
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
11
|
+
config.run_all_when_everything_filtered = true
|
12
|
+
config.filter_run :focus
|
13
|
+
end
|
metadata
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: collection_json
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Mark Burns
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-25 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: Help create Collection+JSON hypermedia APIs
|
15
|
+
email:
|
16
|
+
- markthedeveloper@gmail.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- .gitignore
|
22
|
+
- Gemfile
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- Rakefile
|
26
|
+
- collection_json.gemspec
|
27
|
+
- lib/collection_json.rb
|
28
|
+
- lib/collection_json/crud_operations.rb
|
29
|
+
- lib/collection_json/query.rb
|
30
|
+
- lib/collection_json/version.rb
|
31
|
+
- spec/lib/collection_json_spec.rb
|
32
|
+
- spec/spec_helper.rb
|
33
|
+
homepage: https://github.com/markburns/collection_json
|
34
|
+
licenses: []
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ! '>='
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
46
|
+
none: false
|
47
|
+
requirements:
|
48
|
+
- - ! '>='
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: '0'
|
51
|
+
requirements: []
|
52
|
+
rubyforge_project:
|
53
|
+
rubygems_version: 1.8.15
|
54
|
+
signing_key:
|
55
|
+
specification_version: 3
|
56
|
+
summary: ! 'As specified by: http://amundsen.com/media-types/collection/format/#objects'
|
57
|
+
test_files:
|
58
|
+
- spec/lib/collection_json_spec.rb
|
59
|
+
- spec/spec_helper.rb
|