halibut 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Guardfile +5 -5
- data/README.md +5 -1
- data/halibut.gemspec +0 -1
- data/lib/halibut.rb +2 -3
- data/lib/halibut/adapter/json.rb +5 -5
- data/lib/halibut/adapter/xml.rb +19 -21
- data/lib/halibut/builder.rb +45 -4
- data/lib/halibut/hal/link.rb +62 -13
- data/lib/halibut/hal/resource.rb +77 -9
- data/lib/halibut/relation_map.rb +9 -1
- data/lib/halibut/version.rb +2 -1
- data/spec/adapter/xml_spec.rb +0 -1
- data/spec/resource_spec.rb +42 -5
- metadata +2 -2
data/Guardfile
CHANGED
@@ -2,9 +2,9 @@
|
|
2
2
|
# More info at https://github.com/guard/guard#readme
|
3
3
|
|
4
4
|
guard 'bundler' do
|
5
|
-
watch('Gemfile')
|
5
|
+
# watch('Gemfile')
|
6
6
|
# Uncomment next line if Gemfile contain `gemspec' command
|
7
|
-
watch(/^.+\.gemspec/)
|
7
|
+
# watch(/^.+\.gemspec/)
|
8
8
|
end
|
9
9
|
|
10
10
|
guard 'minitest' do
|
@@ -21,10 +21,10 @@ guard 'minitest' do
|
|
21
21
|
# Rails 3.2
|
22
22
|
# watch(%r|^app/controllers/(.*)\.rb|) { |m| "test/controllers/#{m[1]}_test.rb" }
|
23
23
|
# watch(%r|^app/helpers/(.*)\.rb|) { |m| "test/helpers/#{m[1]}_test.rb" }
|
24
|
-
# watch(%r|^app/models/(.*)\.rb|) { |m| "test/unit/#{m[1]}_test.rb" }
|
25
|
-
|
24
|
+
# watch(%r|^app/models/(.*)\.rb|) { |m| "test/unit/#{m[1]}_test.rb" }
|
25
|
+
|
26
26
|
# Rails
|
27
27
|
# watch(%r|^app/controllers/(.*)\.rb|) { |m| "test/functional/#{m[1]}_test.rb" }
|
28
28
|
# watch(%r|^app/helpers/(.*)\.rb|) { |m| "test/helpers/#{m[1]}_test.rb" }
|
29
|
-
# watch(%r|^app/models/(.*)\.rb|) { |m| "test/unit/#{m[1]}_test.rb" }
|
29
|
+
# watch(%r|^app/models/(.*)\.rb|) { |m| "test/unit/#{m[1]}_test.rb" }
|
30
30
|
end
|
data/README.md
CHANGED
@@ -1,4 +1,8 @@
|
|
1
|
-
# Halibut
|
1
|
+
# Halibut [![endorse](http://api.coderwall.com/locks/endorsecount.png)](http://coderwall.com/locks)
|
2
|
+
|
3
|
+
[![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/locks/halibut)
|
4
|
+
[![Build Status](https://secure.travis-ci.org/locks/halibut.png?branch=master)](https://travis-ci.org/locks/halibut)
|
5
|
+
[![Dependency Status](https://gemnasium.com/locks/halibut.png)](https://gemnasium.com/locks/halibut)
|
2
6
|
|
3
7
|
Halibut is a tiny gem that makes it easier to deal with the [HAL](http://stateless.co/hal_specification.html) format.
|
4
8
|
|
data/halibut.gemspec
CHANGED
data/lib/halibut.rb
CHANGED
@@ -2,8 +2,7 @@ require "halibut/version"
|
|
2
2
|
|
3
3
|
# Halibut is the main namespace
|
4
4
|
module Halibut
|
5
|
-
autoload :Builder,
|
6
|
-
|
5
|
+
autoload :Builder, 'halibut/builder'
|
7
6
|
autoload :RelationMap, 'halibut/relation_map'
|
8
7
|
end
|
9
8
|
|
@@ -16,6 +15,6 @@ end
|
|
16
15
|
|
17
16
|
# Halibut::HAL contains the domain objects that reflect the HAL specs.
|
18
17
|
module Halibut::HAL
|
19
|
-
autoload :Link,
|
18
|
+
autoload :Link, 'halibut/hal/link'
|
20
19
|
autoload :Resource, 'halibut/hal/resource'
|
21
20
|
end
|
data/lib/halibut/adapter/json.rb
CHANGED
@@ -3,10 +3,6 @@ require 'multi_json'
|
|
3
3
|
module Halibut::Adapter
|
4
4
|
|
5
5
|
module JSON
|
6
|
-
def self.extended(base)
|
7
|
-
base.extend InstanceMethods
|
8
|
-
end
|
9
|
-
|
10
6
|
def self.load(json)
|
11
7
|
ResourceExtractor.new(json).resource
|
12
8
|
end
|
@@ -16,6 +12,10 @@ module Halibut::Adapter
|
|
16
12
|
end
|
17
13
|
|
18
14
|
private
|
15
|
+
def self.extended(base)
|
16
|
+
base.extend InstanceMethods
|
17
|
+
end
|
18
|
+
|
19
19
|
module InstanceMethods
|
20
20
|
def to_json
|
21
21
|
MultiJson.dump self.to_hash
|
@@ -61,7 +61,7 @@ module Halibut::Adapter
|
|
61
61
|
def extract_resources(resources)
|
62
62
|
resources.each do |relation,values|
|
63
63
|
embeds = ([] << values).flatten
|
64
|
-
|
64
|
+
|
65
65
|
embeds.map {|embed| MultiJson.dump embed }
|
66
66
|
.map {|embed| Halibut::Adapter::JSON.load embed }
|
67
67
|
.each {|embed| @halibut.embed_resource(relation, embed) }
|
data/lib/halibut/adapter/xml.rb
CHANGED
@@ -3,31 +3,34 @@ require 'nokogiri'
|
|
3
3
|
module Halibut::Adapter
|
4
4
|
|
5
5
|
module XML
|
6
|
-
def self.extended(base)
|
7
|
-
base.extend InstanceMethods
|
8
|
-
end
|
9
|
-
|
10
6
|
def self.load(xml)
|
11
7
|
ResourceExtractor.new(xml).resource
|
12
8
|
end
|
13
9
|
|
14
10
|
def self.dump(resource)
|
11
|
+
raise NotImplementedError
|
15
12
|
end
|
16
13
|
|
17
14
|
private
|
15
|
+
def self.extended(base)
|
16
|
+
base.extend InstanceMethods
|
17
|
+
end
|
18
|
+
|
18
19
|
module InstanceMethods
|
19
20
|
def to_xml
|
21
|
+
raise NotImplementedError
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
25
|
class ResourceExtractor
|
26
|
+
|
27
|
+
attr_reader :resource
|
28
|
+
|
24
29
|
def initialize(xml)
|
25
30
|
xml = Nokogiri::XML(xml)
|
26
31
|
|
27
32
|
@document = xml.root
|
28
|
-
@
|
29
|
-
|
30
|
-
# binding.pry
|
33
|
+
@resource = Halibut::HAL::Resource.new extract_self_link
|
31
34
|
|
32
35
|
extract_curie
|
33
36
|
extract_properties
|
@@ -35,10 +38,6 @@ module Halibut::Adapter
|
|
35
38
|
extract_resources
|
36
39
|
end
|
37
40
|
|
38
|
-
def resource
|
39
|
-
@halibut
|
40
|
-
end
|
41
|
-
|
42
41
|
private
|
43
42
|
def extract_self_link
|
44
43
|
@document.attr 'href'
|
@@ -48,7 +47,7 @@ module Halibut::Adapter
|
|
48
47
|
@document.namespace_scopes
|
49
48
|
.reject {|ns| ns.prefix.eql? 'xsi' }
|
50
49
|
.each do |ns|
|
51
|
-
@
|
50
|
+
@resource.add_link 'curie', ns.href, name: ns.prefix
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
@@ -56,7 +55,7 @@ module Halibut::Adapter
|
|
56
55
|
properties = @document.xpath '/resource/*[not(self::link) and not(self::resource)]'
|
57
56
|
|
58
57
|
properties.each do |property|
|
59
|
-
@
|
58
|
+
@resource.set_property property.name, property.content
|
60
59
|
end
|
61
60
|
end
|
62
61
|
|
@@ -64,25 +63,24 @@ module Halibut::Adapter
|
|
64
63
|
links = @document.xpath('/resource/link')
|
65
64
|
|
66
65
|
links.each do |link|
|
67
|
-
@
|
68
|
-
|
69
|
-
|
66
|
+
@resource.add_link link['rel'],
|
67
|
+
link['href'],
|
68
|
+
extract_link_options(link)
|
70
69
|
end
|
71
70
|
end
|
72
71
|
|
73
72
|
# In case there are no options on the link, it returns an empty hash
|
74
73
|
def extract_link_options(link)
|
75
|
-
link.
|
76
|
-
|
77
|
-
.reduce(:merge) || {}
|
74
|
+
Hash[link.reject {|(key)| key.eql? 'rel' }
|
75
|
+
.reject {|(key)| key.eql? 'href' }]
|
78
76
|
end
|
79
77
|
|
80
78
|
def extract_resources
|
81
79
|
@document.xpath('/resource/resource')
|
82
80
|
.map {|r| [] << r['rel'] << ResourceExtractor.new(r.to_xml).resource }
|
83
|
-
.each {|rel,res| @
|
81
|
+
.each {|rel,res| @resource.embed_resource rel, res }
|
84
82
|
end
|
85
83
|
end
|
86
84
|
end
|
87
85
|
|
88
|
-
end
|
86
|
+
end
|
data/lib/halibut/builder.rb
CHANGED
@@ -4,8 +4,14 @@ module Halibut
|
|
4
4
|
|
5
5
|
# Builder provides a very thin wrapper around creating a HAL resource.
|
6
6
|
class Builder
|
7
|
-
attr_accessor :resource
|
8
7
|
|
8
|
+
# The HAL resource built
|
9
|
+
attr_reader :resource
|
10
|
+
|
11
|
+
#
|
12
|
+
#
|
13
|
+
# @param [String] href
|
14
|
+
# @param [Proc] blk
|
9
15
|
def initialize(href=nil, &blk)
|
10
16
|
@resource = Halibut::HAL::Resource.new href
|
11
17
|
|
@@ -21,6 +27,10 @@ module Halibut
|
|
21
27
|
end
|
22
28
|
|
23
29
|
private
|
30
|
+
|
31
|
+
# This is the root context of Halibut::Builder.
|
32
|
+
#
|
33
|
+
#
|
24
34
|
class RootContext
|
25
35
|
extend Forwardable
|
26
36
|
|
@@ -33,8 +43,23 @@ module Halibut
|
|
33
43
|
instance_eval(&blk) if block_given?
|
34
44
|
end
|
35
45
|
|
46
|
+
# Adds a namespace to the resource.
|
47
|
+
#
|
48
|
+
# A namespace is a conceptual abstraction of CURIE links.
|
49
|
+
# Since the client of the library doesn't need to handle CURIE links
|
50
|
+
# directly because they're just for dereferencing link relations, no
|
51
|
+
# CURIE links are presented.
|
52
|
+
#
|
53
|
+
# resource = Halibut::Builder.new do
|
54
|
+
# namespace :john, 'http://appleseed.com'
|
55
|
+
# end.resource
|
56
|
+
# resource.namespace(:john).href
|
57
|
+
# # => "http://appleseed.com"
|
58
|
+
#
|
59
|
+
# @param [String,Symbol] name name of the namespace
|
60
|
+
# @param [String] href URI of the namespace
|
36
61
|
def namespace(name, href)
|
37
|
-
@resource.
|
62
|
+
@resource.add_namespace(name, href)
|
38
63
|
end
|
39
64
|
|
40
65
|
def resource(rel, href=nil, &blk)
|
@@ -43,6 +68,23 @@ module Halibut
|
|
43
68
|
@resource.embed_resource(rel, embedded.resource)
|
44
69
|
end
|
45
70
|
|
71
|
+
# Adds links or resources to a relation.
|
72
|
+
#
|
73
|
+
# Relation allows the user to specify links, or resources, per relation,
|
74
|
+
# instead of individually.
|
75
|
+
# This feature was introduced as an attempt to reduce repeating the
|
76
|
+
# relation per link/resource, and thus reducing typos.
|
77
|
+
#
|
78
|
+
# resource = Halibut::Builder.new do
|
79
|
+
# relation :john do
|
80
|
+
# link 'http://appleseed.com/john'
|
81
|
+
# end
|
82
|
+
# end.resource
|
83
|
+
# resource.links[:john].first.href
|
84
|
+
#
|
85
|
+
# @param [String,Symbol] rel
|
86
|
+
# @param [Proc] blk Instructions to be executed in the relation
|
87
|
+
# context
|
46
88
|
def relation(rel, &blk)
|
47
89
|
RelationContext.new(@resource, rel, &blk)
|
48
90
|
end
|
@@ -58,7 +100,6 @@ module Halibut
|
|
58
100
|
instance_eval(&blk) if block_given?
|
59
101
|
end
|
60
102
|
|
61
|
-
private
|
62
103
|
def link(href, opts={})
|
63
104
|
@resource.add_link(@rel, href, opts)
|
64
105
|
end
|
@@ -72,4 +113,4 @@ module Halibut
|
|
72
113
|
|
73
114
|
end
|
74
115
|
|
75
|
-
end
|
116
|
+
end
|
data/lib/halibut/hal/link.rb
CHANGED
@@ -5,29 +5,56 @@ module Halibut::HAL
|
|
5
5
|
class Link
|
6
6
|
extend Forwardable
|
7
7
|
|
8
|
+
# The URI associated with this link.
|
8
9
|
attr_reader :href
|
9
10
|
|
10
11
|
def_delegators :@options, :templated, :templated?, :type,
|
11
12
|
:name, :profile, :title, :hreflang
|
13
|
+
|
12
14
|
# Returns an instance of a HAL Link object
|
13
15
|
#
|
16
|
+
# # link with no options
|
17
|
+
# link = Link.new('http://homeopathy.org')
|
18
|
+
#
|
19
|
+
# # link with name and type options
|
20
|
+
# link = Link.new('http://homeopathy.org', name: 'Homeopath'
|
21
|
+
# , type: 'text/html')
|
22
|
+
#
|
23
|
+
# If you pass an options that is not one of the reserved link properties
|
24
|
+
# as defined by the spec, they are dropped.
|
25
|
+
# It should possibly raise an error, hafta think about it.
|
26
|
+
#
|
14
27
|
# @param [String] href URI or URI Template
|
15
|
-
# @param [Boolean] templated true if URI Template or false otherwise
|
16
28
|
# @param [Hash] opts Options: type, name, profile, title, hreflang
|
17
29
|
#
|
18
30
|
# @return [Halibut::HAL::Link] HAL Link object
|
19
31
|
def initialize(href, opts={})
|
20
|
-
@href
|
32
|
+
@href = href
|
21
33
|
@options = Options.new opts
|
22
34
|
end
|
23
35
|
|
24
|
-
#
|
36
|
+
# Simply returns a hash of the href and the options that are not empty.
|
37
|
+
#
|
38
|
+
# link = Link.new('/links', name: 'Links')
|
39
|
+
# link.to_hash
|
40
|
+
# # => { "href" => "/links", "name" => "links" }
|
25
41
|
#
|
26
42
|
# @return [Hash] hash from Link Object
|
27
43
|
def to_hash
|
28
44
|
{ 'href' => href }.merge @options
|
29
45
|
end
|
30
46
|
|
47
|
+
# Generic comparison method.
|
48
|
+
#
|
49
|
+
# Two objects are the same if they have the same href and the same options.
|
50
|
+
#
|
51
|
+
# link_one = Link.new('/link', name: 'One', type: 'text/html')
|
52
|
+
# link_two = Link.new('/link', name: 'One', type: 'text/html')
|
53
|
+
# link_one == link_two
|
54
|
+
# # => true
|
55
|
+
#
|
56
|
+
# @param [Link] other Link object to compare to
|
57
|
+
# @return [true,false] return of the comparison of the two objects
|
31
58
|
def ==(other)
|
32
59
|
@href == other.href && @options == other.options
|
33
60
|
end
|
@@ -36,6 +63,15 @@ module Halibut::HAL
|
|
36
63
|
attr_reader :options
|
37
64
|
|
38
65
|
private
|
66
|
+
# Options reifies the various optional properties of a link, as per the
|
67
|
+
# spec.
|
68
|
+
#
|
69
|
+
# hash = { name: 'John le Carré', templated: true }
|
70
|
+
# opts = Options.new(hash)
|
71
|
+
# opts.name # => John le Carré
|
72
|
+
# opts['name'] # => John le Carré
|
73
|
+
# opts[:name] # => John le Carré
|
74
|
+
#
|
39
75
|
class Options
|
40
76
|
attr_reader :templated, :type, :name,
|
41
77
|
:profile, :title, :hreflang
|
@@ -59,23 +95,36 @@ module Halibut::HAL
|
|
59
95
|
@templated || false
|
60
96
|
end
|
61
97
|
|
98
|
+
# When converting to a hash, options that weren't set (.nil? == true) are
|
99
|
+
# kept out.
|
100
|
+
#
|
101
|
+
# This might have some implications, as it does not 'serialiaze' options
|
102
|
+
# that were explicitely set to nil. On the other hand, one can argue that
|
103
|
+
# if they were explicitly set to nil, then they shouldn't show up anyway.
|
62
104
|
def to_hash
|
63
|
-
instance_variables.each_with_object({}) do |
|
64
|
-
|
105
|
+
instance_variables.each_with_object({}) do |ivar, hash|
|
106
|
+
name = ivar.to_s.reverse.chomp("@").reverse
|
107
|
+
value = instance_variable_get(ivar)
|
65
108
|
|
66
|
-
|
109
|
+
next if value.nil?
|
110
|
+
|
111
|
+
hash[name] = value
|
67
112
|
end
|
68
113
|
end
|
69
114
|
|
115
|
+
# Straight forward comparison between two Options objects.
|
116
|
+
#
|
117
|
+
# opts_one = Options.new(name: 'Link', templated: true)
|
118
|
+
# opts_two = Options.new(name: 'Link', templated: true)
|
119
|
+
# opts_one == opts_two
|
120
|
+
# # => true
|
121
|
+
#
|
122
|
+
# @param [Options] other Options object to compare to.
|
123
|
+
# @return [true,false] whether these two objects are equivalent or not.
|
70
124
|
def ==(other)
|
71
|
-
|
72
|
-
type == other.type &&
|
73
|
-
name == other.name &&
|
74
|
-
profile == other.profile &&
|
75
|
-
title == other.title &&
|
76
|
-
hreflang == other.hreflang
|
125
|
+
to_hash == other.to_hash
|
77
126
|
end
|
78
127
|
end
|
79
128
|
end
|
80
129
|
|
81
|
-
end
|
130
|
+
end
|
data/lib/halibut/hal/resource.rb
CHANGED
@@ -4,12 +4,38 @@ module Halibut::HAL
|
|
4
4
|
#
|
5
5
|
# spec spec spec
|
6
6
|
class Resource
|
7
|
-
attr_reader :properties, :links, :embedded
|
8
7
|
|
9
|
-
#
|
8
|
+
# All the properties set in this resource
|
9
|
+
attr_reader :properties
|
10
|
+
|
11
|
+
# A collection of links, grouped by relation
|
12
|
+
attr_reader :links
|
13
|
+
|
14
|
+
# A collection of embedded resources, grouped by relation.
|
15
|
+
attr_reader :embedded
|
16
|
+
|
17
|
+
# A collection of namespaces defined in the document
|
18
|
+
attr_reader :namespace
|
19
|
+
|
20
|
+
# Initialize a new Resource.
|
21
|
+
#
|
22
|
+
# As defined in the spec, the resource SHOULD have a self link, but it
|
23
|
+
# isn't required.
|
24
|
+
# Also optionally, I'm toying with the idea of being able to pass in
|
25
|
+
# properties, links and embedded resources as parameters to this method,
|
26
|
+
# like suggested in https://github.com/locks/halibut/issues/1.
|
27
|
+
#
|
28
|
+
# # Resource without self link (e.g. POSTing a new resource)
|
29
|
+
# resource = Halibut::HAL::Resource.new
|
30
|
+
# resource.set_property :name, 'Halibut Rules'
|
31
|
+
# resource.set_property :winner, 'Tiger Blood'
|
32
|
+
#
|
33
|
+
# # Resource with a self link
|
34
|
+
# resource = Halibut::HAL::Resource.new
|
10
35
|
#
|
11
36
|
# @param [String] href Link that will be added to the self relation.
|
12
|
-
def initialize(href=nil)
|
37
|
+
def initialize(href=nil, properties={}, links={}, embedded={})
|
38
|
+
@namespaces = Halibut::RelationMap.new
|
13
39
|
@links = Halibut::RelationMap.new
|
14
40
|
@embedded = Halibut::RelationMap.new
|
15
41
|
@properties = {}
|
@@ -17,7 +43,28 @@ module Halibut::HAL
|
|
17
43
|
add_link('self', href) if href
|
18
44
|
end
|
19
45
|
|
20
|
-
#
|
46
|
+
# Returns the self link of the resource.
|
47
|
+
#
|
48
|
+
# @return [String,nil] the self link of the resource
|
49
|
+
def href
|
50
|
+
@links.fetch('self', []).map(&:href).first
|
51
|
+
end
|
52
|
+
|
53
|
+
def namespace(name)
|
54
|
+
@links['curie'].select {|ns| ns.name == name }.first
|
55
|
+
end
|
56
|
+
alias_method :ns, :namespace
|
57
|
+
|
58
|
+
def namespaces
|
59
|
+
@links['curie']
|
60
|
+
end
|
61
|
+
|
62
|
+
# Sets a property in the resource.
|
63
|
+
#
|
64
|
+
# resource = Halibut::HAL::Resource.new
|
65
|
+
# resource.set_property :name, 'FooBar'
|
66
|
+
# resource.property :name
|
67
|
+
# # => "FooBar"
|
21
68
|
#
|
22
69
|
# @param [Object] property the key
|
23
70
|
# @param [Object] value the value
|
@@ -27,17 +74,38 @@ module Halibut::HAL
|
|
27
74
|
|
28
75
|
# Returns the value of a property in the resource
|
29
76
|
#
|
77
|
+
# resource = Halibut::HAL::Resource.new
|
78
|
+
# resource.set_property :name, 'FooBar'
|
79
|
+
# resource.property :name
|
80
|
+
# # => "FooBar"
|
81
|
+
#
|
30
82
|
# @param [String] property property
|
31
|
-
def
|
32
|
-
@properties
|
83
|
+
def property(property)
|
84
|
+
@properties.fetch(property, nil)
|
33
85
|
end
|
34
86
|
|
35
|
-
# Adds
|
87
|
+
# Adds a namespace to the resource.
|
88
|
+
#
|
89
|
+
# @param [String] name The name of the namespace
|
90
|
+
# @param [String] href The templated URI of the namespace
|
91
|
+
def add_namespace(name, href)
|
92
|
+
@links.add 'curie', Link.new(href, templated: true, name: name)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Adds link to relation.
|
96
|
+
#
|
97
|
+
# resource = Halibut::HAL::Resource.new
|
98
|
+
# resource.add_link 'next', '/resource/2', name: 'Foo'
|
99
|
+
# link = resource.links['next'].first
|
100
|
+
# link.href
|
101
|
+
# # => "/resource/2"
|
102
|
+
# link.name
|
103
|
+
# # => "Foo"
|
36
104
|
#
|
37
105
|
# @param [String] relation relation
|
38
106
|
# @param [String] href href
|
39
|
-
# @param [
|
40
|
-
#
|
107
|
+
# @param [Hash] opts options: templated, type, name, profile,
|
108
|
+
# title, hreflang
|
41
109
|
def add_link(relation, href, opts={})
|
42
110
|
@links.add relation, Link.new(href, opts)
|
43
111
|
end
|
data/lib/halibut/relation_map.rb
CHANGED
@@ -6,7 +6,7 @@ module Halibut
|
|
6
6
|
class RelationMap
|
7
7
|
extend Forwardable
|
8
8
|
|
9
|
-
def_delegators :@relations, :[], :empty?,
|
9
|
+
def_delegators :@relations, :[], :empty?, :==, :fetch
|
10
10
|
|
11
11
|
def initialize
|
12
12
|
@relations = {}
|
@@ -14,6 +14,14 @@ module Halibut
|
|
14
14
|
|
15
15
|
# Adds an object to a relation.
|
16
16
|
#
|
17
|
+
# relations = RelationMap.new
|
18
|
+
# relations.add 'self', Link.new('/resource/1')
|
19
|
+
# relations['self']
|
20
|
+
# # => [#<Halibut::HAL::Link:0x007fa0ca5b92b8 @href=\"/resource/1\",
|
21
|
+
# @options=#<Halibut::HAL::Link::Options:0x007fa0ca5b9240
|
22
|
+
# @templated=nil, @type=nil, @name=nil, @profile=nil,
|
23
|
+
# @title=nil, @hreflang=nil>>]
|
24
|
+
#
|
17
25
|
# @param [String] relation relation that the object belongs to
|
18
26
|
# @param [Object] item the object to add to the relation
|
19
27
|
def add(relation, item)
|
data/lib/halibut/version.rb
CHANGED
data/spec/adapter/xml_spec.rb
CHANGED
data/spec/resource_spec.rb
CHANGED
@@ -1,12 +1,11 @@
|
|
1
1
|
require_relative 'spec_helper'
|
2
2
|
|
3
3
|
describe Halibut::HAL::Resource do
|
4
|
+
subject { Halibut::HAL::Resource.new }
|
4
5
|
let(:templated_uri) { "http://example.com/{path}{?query}" }
|
5
6
|
let(:normal_uri) { "http://example.com" }
|
6
7
|
|
7
8
|
describe "Properties" do
|
8
|
-
subject { Halibut::HAL::Resource.new }
|
9
|
-
|
10
9
|
it "set property" do
|
11
10
|
subject.set_property "property", "value"
|
12
11
|
|
@@ -16,7 +15,7 @@ describe Halibut::HAL::Resource do
|
|
16
15
|
it "read property" do
|
17
16
|
subject.set_property "property", "value"
|
18
17
|
|
19
|
-
subject.
|
18
|
+
subject.property('property').must_equal "value"
|
20
19
|
end
|
21
20
|
end
|
22
21
|
|
@@ -24,8 +23,8 @@ describe Halibut::HAL::Resource do
|
|
24
23
|
|
25
24
|
describe "self link" do
|
26
25
|
it "no default" do
|
27
|
-
|
28
|
-
|
26
|
+
subject.links.must_be_empty
|
27
|
+
subject.href.must_be_nil
|
29
28
|
end
|
30
29
|
|
31
30
|
it "default" do
|
@@ -33,9 +32,47 @@ describe Halibut::HAL::Resource do
|
|
33
32
|
|
34
33
|
resource.links.wont_be_empty
|
35
34
|
resource.links['self'].first.href.must_equal normal_uri
|
35
|
+
resource.href.must_equal normal_uri
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
+
it "adds link to resource" do
|
40
|
+
subject.links.must_be_empty
|
41
|
+
|
42
|
+
subject.add_link 'lol', normal_uri
|
43
|
+
subject.links['lol'].first.href.must_equal normal_uri
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "Namespaces" do
|
49
|
+
let(:href) { 'http://relations.com/{rel}' }
|
50
|
+
|
51
|
+
it "has a single namespace" do
|
52
|
+
subject.add_namespace 'lol', href
|
53
|
+
|
54
|
+
subject.namespaces.size.must_equal 1
|
55
|
+
subject.namespaces.first.must_equal subject.namespace('lol')
|
56
|
+
|
57
|
+
subject.namespace('lol').must_be :templated?
|
58
|
+
subject.namespace('lol').href.must_equal href
|
59
|
+
subject.namespace('lol').name.must_equal 'lol'
|
60
|
+
end
|
61
|
+
|
62
|
+
it "has multiple namespaces" do
|
63
|
+
subject.add_namespace 'lol', "http://lol.com/{rel}"
|
64
|
+
subject.add_namespace 'lmao', "http://lmao.com/{rel}"
|
65
|
+
|
66
|
+
subject.namespaces.size.must_equal 2
|
67
|
+
|
68
|
+
subject.namespace('lol').must_be :templated?
|
69
|
+
subject.namespace('lol').href.must_equal 'http://lol.com/{rel}'
|
70
|
+
subject.namespace('lol').name.must_equal 'lol'
|
71
|
+
|
72
|
+
subject.namespace('lmao').must_be :templated?
|
73
|
+
subject.namespace('lmao').href.must_equal 'http://lmao.com/{rel}'
|
74
|
+
subject.namespace('lmao').name.must_equal 'lmao'
|
75
|
+
end
|
39
76
|
end
|
40
77
|
|
41
78
|
describe "Embedded resources" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: halibut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: multi_json
|