roar 0.9.2 → 0.10.0
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.
- data/.travis.yml +3 -0
- data/CHANGES.markdown +15 -6
- data/README.textile +7 -18
- data/lib/roar/representer/feature/client.rb +32 -0
- data/lib/roar/representer/feature/http_verbs.rb +1 -1
- data/lib/roar/representer/feature/hypermedia.rb +43 -15
- data/lib/roar/representer/json.rb +10 -10
- data/lib/roar/representer/json/hal.rb +109 -0
- data/lib/roar/representer/xml.rb +6 -9
- data/lib/roar/version.rb +1 -1
- data/roar.gemspec +3 -1
- data/test/client_test.rb +24 -0
- data/test/fake_server.rb +3 -4
- data/test/hal_json_test.rb +69 -0
- data/test/http_verbs_feature_test.rb +4 -4
- data/test/hypermedia_feature_test.rb +63 -7
- data/test/json_representer_test.rb +36 -3
- data/test/test_helper.rb +7 -1
- data/test/transport_test.rb +5 -5
- data/test/xml_representer_test.rb +24 -30
- metadata +79 -82
data/.travis.yml
ADDED
data/CHANGES.markdown
CHANGED
@@ -1,27 +1,36 @@
|
|
1
|
-
|
1
|
+
## 0.10.0
|
2
|
+
|
3
|
+
* Requiring representable-0.1.3.
|
4
|
+
* Added JSON-HAL support.
|
5
|
+
* Links are no longer rendered when `href` is `nil` or `false`.
|
6
|
+
* `Representer.link` class method now accepts either the `rel` value, only, or a hash of link attributes (defined in `Hypermedia::Hyperlink.params`), like `link :rel => :self, :title => "You're good" do..`
|
7
|
+
* API CHANGE: `Representer#links` no longer returns the `href` value but the link object. Use it like `object.links[:self].href` to retrieve the URL.
|
8
|
+
* `#from_json` won't throw an exception anymore when passed an empty json document.
|
9
|
+
|
10
|
+
## 0.9.2
|
2
11
|
|
3
12
|
* Using representable-1.1.
|
4
13
|
|
5
|
-
|
14
|
+
## 0.9.1
|
6
15
|
|
7
16
|
* Removed @Representer#to_attributes@ and @#from_attributes@.
|
8
17
|
* Using representable-1.0.1 now.
|
9
18
|
|
10
|
-
|
19
|
+
## 0.9.0
|
11
20
|
|
12
21
|
* Using representable-0.12.x.
|
13
22
|
* `Representer::Base` is now simply `Representer`.
|
14
23
|
* Removed all the class methods from `HttpVerbs` except for `get`.
|
15
24
|
|
16
25
|
|
17
|
-
|
26
|
+
## 0.8.3
|
18
27
|
|
19
28
|
* Maintenance release for representable compat.
|
20
29
|
|
21
|
-
|
30
|
+
## 0.8.2
|
22
31
|
|
23
32
|
* Removing `restfulie` dependency - we now use `Net::HTTP`.
|
24
33
|
|
25
|
-
|
34
|
+
## 0.8.1
|
26
35
|
|
27
36
|
* Added the :except and :include options to `#from_*`.
|
data/README.textile
CHANGED
@@ -2,28 +2,14 @@ h1. ROAR
|
|
2
2
|
|
3
3
|
_Resource-Oriented Architectures in Ruby._
|
4
4
|
|
5
|
-
"Lets make documents suit our models and not models fit to documents."
|
6
|
-
|
7
|
-
Questions? Need help? Free 1st Level Support on irc.freenode.org#roar !
|
8
|
-
|
9
5
|
h2. Introduction
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
Most REST gems provide a neat HTTP interface, automatic parsing of documents and a more or less convenient way for rendering representations. Roar is different. The central concept of Roar are *representers* - object-oriented documents suitable for parsing _and_ rendering, extendable at runtime and with hypermedia support. The Representer concept is the answer to the missing REST abstraction layer in most frameworks.
|
14
|
-
|
15
|
-
|
16
|
-
h2. Features
|
17
|
-
|
18
|
-
* OOP access to documents.
|
19
|
-
* Parsing _and_ rendering of representations in one place.
|
20
|
-
* Declaratively define document syntax and semantics.
|
21
|
-
* Hypermedia support.
|
22
|
-
* ActiveResource-like client support.
|
23
|
-
* Useable in both client _and_ server.
|
24
|
-
* Framework agnostic, runs with sinatra, Rails, webmachine and friends.
|
7
|
+
Roar is a framework for parsing and rendering REST documents. Nothing more. With Roar, REST documents - also known as representations - are defined using a new concept called representers. Both syntax and semantics are declared in Ruby modules that can be mixed into your domain models, following clean OOP patterns.
|
25
8
|
|
9
|
+
Roar comes with built-in JSON, JSON::HAL and XML support. It exposes a highly modular architecture and makes it very simple to add new media types and functionality where needed. Additional features include client HTTP support, coercion, client-side caching, awesome hypermedia support and more. Representers feel pretty well in DCI environments, too.
|
26
10
|
|
11
|
+
Roar is completely framework-agnostic and loves being used in web kits like Rails, Webmachine, Sinatra, Padrino, etc. Actually, Roar makes it fun designing real, hypermedia-driven, and resource-oriented systems that will even make Steve sleep happily at night so he finally gets some REST!
|
12
|
+
|
27
13
|
h2. Example
|
28
14
|
|
29
15
|
Say your webshop consists of two completely separated apps. The REST backend, a Sinatra app, serves articles and processes orders. The frontend, being browsed by your clients, is a rich Rails application. It queries the services for articles, renders them nicely and reads or writes orders with REST calls. That being said, the frontend turns out to be a pure REST client.
|
@@ -307,3 +293,6 @@ Making that system RESTful basically means
|
|
307
293
|
# Do _not_ let the frontend compute any URLs to further actions.
|
308
294
|
# Showing articles, creating a new order, adding articles to it and finally placing the order - this all requires further URLs. These URLs are embedded as _hypermedia_ in the representations sent by the REST backend.
|
309
295
|
|
296
|
+
h2. Support
|
297
|
+
|
298
|
+
Questions? Need help? Free 1st Level Support on irc.freenode.org#roar !
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require "roar/representer/feature/http_verbs"
|
2
|
+
|
3
|
+
module Roar
|
4
|
+
# Automatically add accessors for properties and collections. Also mixes in HttpVerbs.
|
5
|
+
module Representer
|
6
|
+
module Feature
|
7
|
+
module Client
|
8
|
+
include HttpVerbs
|
9
|
+
|
10
|
+
def self.extended(base)
|
11
|
+
base.instance_eval do
|
12
|
+
representable_attrs.each do |attr|
|
13
|
+
next unless attr.instance_of? Representable::Definition # ignore hyperlinks etc for now.
|
14
|
+
name = attr.name
|
15
|
+
|
16
|
+
# TODO: could anyone please make this better?
|
17
|
+
instance_eval %Q{
|
18
|
+
def #{name}=(v)
|
19
|
+
@#{name} = v
|
20
|
+
end
|
21
|
+
|
22
|
+
def #{name}
|
23
|
+
@#{name}
|
24
|
+
end
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -27,7 +27,7 @@ module Roar
|
|
27
27
|
# and updates properties accordingly.
|
28
28
|
def post(url, format)
|
29
29
|
# DISCUSS: what if a redirect happens here?
|
30
|
-
document = http.post_uri(url, serialize
|
30
|
+
document = http.post_uri(url, serialize, format).body
|
31
31
|
deserialize(document)
|
32
32
|
end
|
33
33
|
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Roar
|
2
2
|
module Representer
|
3
3
|
module Feature
|
4
|
-
#
|
4
|
+
# Define hypermedia links in your representations.
|
5
5
|
#
|
6
6
|
# Example:
|
7
7
|
#
|
@@ -13,6 +13,12 @@ module Roar
|
|
13
13
|
# link :self do
|
14
14
|
# "http://orders/#{id}"
|
15
15
|
# end
|
16
|
+
#
|
17
|
+
# If you want more attributes, just pass a hash to #link.
|
18
|
+
#
|
19
|
+
# link :rel => :next, :title => "Next, please!" do
|
20
|
+
# "http://orders/#{id}"
|
21
|
+
# end
|
16
22
|
module Hypermedia
|
17
23
|
def self.included(base)
|
18
24
|
base.extend ClassMethods
|
@@ -34,14 +40,13 @@ module Roar
|
|
34
40
|
protected
|
35
41
|
# Setup hypermedia links by invoking their blocks. Usually called by #serialize.
|
36
42
|
def prepare_links!
|
37
|
-
links_def
|
38
|
-
hyperlink_class = links_def.sought_type
|
43
|
+
links_def = find_links_definition or return
|
39
44
|
|
40
|
-
links_def.rel2block.each do |
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
+
links_def.rel2block.each do |config| # config is [{..}, block]
|
46
|
+
options = config.first
|
47
|
+
options[:href] = run_link_block(config.last) or next
|
48
|
+
|
49
|
+
links.update_link(Feature::Hypermedia::Hyperlink.new(options))
|
45
50
|
end
|
46
51
|
end
|
47
52
|
|
@@ -56,7 +61,7 @@ module Roar
|
|
56
61
|
|
57
62
|
class LinkCollection < Array
|
58
63
|
def [](rel)
|
59
|
-
link = find { |l| l.rel.to_s == rel.to_s } and return link
|
64
|
+
link = find { |l| l.rel.to_s == rel.to_s } and return link
|
60
65
|
end
|
61
66
|
|
62
67
|
# Checks if the link is already contained by querying for its +rel+.
|
@@ -81,18 +86,23 @@ module Roar
|
|
81
86
|
#
|
82
87
|
# The block is executed in instance context, so you may call properties or other accessors.
|
83
88
|
# Note that you're free to put decider logic into #link blocks, too.
|
84
|
-
def link(
|
85
|
-
|
86
|
-
links = LinksDefinition.new(:links, links_definition_options)
|
87
|
-
representable_attrs << links
|
88
|
-
end
|
89
|
+
def link(options, &block)
|
90
|
+
links = find_links_definition || create_links
|
89
91
|
|
90
|
-
|
92
|
+
options = {:rel => options} if options.is_a?(Symbol)
|
93
|
+
links.rel2block << [options, block]
|
91
94
|
end
|
92
95
|
|
93
96
|
def find_links_definition
|
94
97
|
representable_attrs.find { |d| d.is_a?(LinksDefinition) }
|
95
98
|
end
|
99
|
+
|
100
|
+
private
|
101
|
+
def create_links
|
102
|
+
LinksDefinition.new(*links_definition_options).tap do |links|
|
103
|
+
representable_attrs << links
|
104
|
+
end
|
105
|
+
end
|
96
106
|
end
|
97
107
|
|
98
108
|
|
@@ -102,6 +112,24 @@ module Roar
|
|
102
112
|
@rel2block ||= []
|
103
113
|
end
|
104
114
|
end
|
115
|
+
|
116
|
+
|
117
|
+
# An abstract hypermedia link with +rel+, +href+ and other attributes.
|
118
|
+
# Overwrite the Hyperlink.params method if you need more link attributes.
|
119
|
+
class Hyperlink
|
120
|
+
def self.params
|
121
|
+
[:rel, :href, :media, :title, :hreflang]
|
122
|
+
end
|
123
|
+
|
124
|
+
attr_accessor *params
|
125
|
+
|
126
|
+
def initialize(options={})
|
127
|
+
options.each do |k,v|
|
128
|
+
next unless self.class.params.include?(k.to_sym)
|
129
|
+
instance_variable_set("@#{k}", v)
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
105
133
|
end
|
106
134
|
end
|
107
135
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'roar/representer'
|
2
|
+
require 'roar/representer/feature/hypermedia'
|
2
3
|
require 'representable/json'
|
3
4
|
|
4
5
|
module Roar
|
@@ -21,7 +22,7 @@ module Roar
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def from_json(document, options={})
|
24
|
-
document
|
25
|
+
document = '{}' if document.nil? or document.empty?
|
25
26
|
|
26
27
|
super
|
27
28
|
end
|
@@ -38,24 +39,23 @@ module Roar
|
|
38
39
|
|
39
40
|
|
40
41
|
module ClassMethods
|
41
|
-
def deserialize(
|
42
|
-
from_json(
|
42
|
+
def deserialize(*args)
|
43
|
+
from_json(*args)
|
43
44
|
end
|
44
45
|
|
45
46
|
# TODO: move to instance method, or remove?
|
46
47
|
def links_definition_options
|
47
|
-
{:class => Hyperlink , :collection => true}
|
48
|
+
[:links, {:class => Feature::Hypermedia::Hyperlink, :extend => HyperlinkRepresenter, :collection => true}]
|
48
49
|
end
|
49
50
|
end
|
50
51
|
|
51
52
|
|
52
|
-
#
|
53
|
-
|
53
|
+
# Represents a hyperlink in standard roar+json.
|
54
|
+
module HyperlinkRepresenter
|
54
55
|
include JSON
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
property :href
|
56
|
+
Feature::Hypermedia::Hyperlink.params.each do |attr|
|
57
|
+
property attr
|
58
|
+
end
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Roar::Representer
|
2
|
+
module JSON
|
3
|
+
# Including the JSON::HAL module in your representer will render and parse documents
|
4
|
+
# following the HAL specification: http://stateless.co/hal_specification.html
|
5
|
+
# Links will be embedded using the +_links+ key, nested resources with the +_embedded+ key.
|
6
|
+
#
|
7
|
+
# Embedded resources can be specified when calling #property or +collection using the
|
8
|
+
# :embedded => true option.
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# module OrderRepresenter
|
13
|
+
# include Roar::Representer::JSON::HAL
|
14
|
+
#
|
15
|
+
# property :id
|
16
|
+
# collection :items, :class => Item, :extend => ItemRepresenter, :embedded => true
|
17
|
+
#
|
18
|
+
# link :self do
|
19
|
+
# "http://orders/#{id}"
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# Renders to
|
24
|
+
#
|
25
|
+
# "{\"id\":1,\"_embedded\":{\"items\":[{\"value\":\"Beer\",\"_links\":{\"self\":{\"href\":\"http://items/Beer\"}}}]},\"_links\":{\"self\":{\"href\":\"http://orders/1\"}}}"
|
26
|
+
module HAL
|
27
|
+
def self.included(base)
|
28
|
+
base.class_eval do
|
29
|
+
include Roar::Representer::JSON
|
30
|
+
include Links # overwrites #links_definition_options.
|
31
|
+
extend ClassMethods # overwrites #links_definition_options, again.
|
32
|
+
include Resources
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module Resources
|
37
|
+
# Write the property to the +_embedded+ hash when it's a resource.
|
38
|
+
def compile_fragment(bin, doc)
|
39
|
+
return super unless bin.definition.options[:embedded]
|
40
|
+
super(bin, doc[:_embedded] ||= {})
|
41
|
+
end
|
42
|
+
|
43
|
+
def uncompile_fragment(bin, doc)
|
44
|
+
return super unless bin.definition.options[:embedded]
|
45
|
+
super(bin, doc["_embedded"])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
module ClassMethods
|
50
|
+
def links_definition_options
|
51
|
+
super.tap { |options| options[1].merge!({:from => :_links}) }
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Including this module in your representer will render and parse your embedded hyperlinks
|
56
|
+
# following the HAL specification: http://stateless.co/hal_specification.html
|
57
|
+
#
|
58
|
+
# module SongRepresenter
|
59
|
+
# include Roar::Representer::JSON
|
60
|
+
# include Roar::Representer::JSON::HAL::Links
|
61
|
+
#
|
62
|
+
# link :self { "http://self" }
|
63
|
+
# end
|
64
|
+
#
|
65
|
+
# Renders to
|
66
|
+
#
|
67
|
+
# {"links":{"self":{"href":"http://self"}}}
|
68
|
+
#
|
69
|
+
# Note that the HAL::Links module alone doesn't prepend an underscore to +links+. Use the JSON::HAL module for that.
|
70
|
+
module Links
|
71
|
+
# TODO: allow more attributes besides :href in Hyperlink.
|
72
|
+
def self.included(base)
|
73
|
+
base.class_eval do
|
74
|
+
include Roar::Representer::Feature::Hypermedia
|
75
|
+
extend Links::ClassMethods
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
module LinkCollectionRepresenter
|
81
|
+
include JSON
|
82
|
+
|
83
|
+
def to_hash(*)
|
84
|
+
{}.tap do |hash|
|
85
|
+
each do |link|
|
86
|
+
# TODO: we statically use JSON::HyperlinkRepresenter here.
|
87
|
+
hash[link.rel] = link.extend(JSON::HyperlinkRepresenter).to_hash(:except => [:rel])
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def from_hash(json, *)
|
93
|
+
json.each do |k, v|
|
94
|
+
self << Feature::Hypermedia::Hyperlink.new(v.merge :rel => k)
|
95
|
+
end
|
96
|
+
self
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
|
101
|
+
module ClassMethods
|
102
|
+
def links_definition_options
|
103
|
+
super.tap { |options| options[1] = {:class => Feature::Hypermedia::LinkCollection, :extend => LinkCollectionRepresenter} }
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/roar/representer/xml.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'roar/representer'
|
2
|
+
require 'roar/representer/feature/hypermedia'
|
2
3
|
require 'representable/xml'
|
3
4
|
|
4
5
|
module Roar
|
@@ -37,7 +38,7 @@ module Roar
|
|
37
38
|
include Representable::XML::ClassMethods
|
38
39
|
|
39
40
|
def links_definition_options
|
40
|
-
{:from => :link, :class => Hyperlink, :collection => true}
|
41
|
+
[:links, {:from => :link, :class => Feature::Hypermedia::Hyperlink, :collection => true, :extend => XML::HyperlinkRepresenter}]
|
41
42
|
end
|
42
43
|
|
43
44
|
# Generic entry-point for parsing.
|
@@ -46,19 +47,15 @@ module Roar
|
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
|
-
|
50
|
-
# Encapsulates a hypermedia <link ...>.
|
51
|
-
class Hyperlink
|
52
|
-
# TODO: make XML a module to include in Hyperlink < Base.
|
53
|
-
attr_accessor :rel, :href
|
50
|
+
module HyperlinkRepresenter
|
54
51
|
include XML
|
55
52
|
|
56
53
|
self.representation_wrap = :link
|
57
54
|
|
58
|
-
|
59
|
-
|
55
|
+
Feature::Hypermedia::Hyperlink.params.each do |attr|
|
56
|
+
property attr, :attribute => true
|
57
|
+
end
|
60
58
|
end
|
61
|
-
|
62
59
|
end
|
63
60
|
end
|
64
61
|
end
|
data/lib/roar/version.rb
CHANGED
data/roar.gemspec
CHANGED
@@ -19,9 +19,11 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_runtime_dependency "representable", "
|
22
|
+
s.add_runtime_dependency "representable", ">= 1.1.3"
|
23
23
|
|
24
|
+
s.add_development_dependency "rake"
|
24
25
|
s.add_development_dependency "test_xml"
|
25
26
|
s.add_development_dependency "minitest", ">= 2.8.1"
|
26
27
|
s.add_development_dependency "sinatra", "~> 1.2.6"
|
28
|
+
s.add_development_dependency "sham_rack", "~> 1.3.0"
|
27
29
|
end
|
data/test/client_test.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/representer/feature/client'
|
3
|
+
|
4
|
+
class ClientTest < MiniTest::Spec
|
5
|
+
describe "Client" do
|
6
|
+
before do
|
7
|
+
@representer = Module.new do
|
8
|
+
include Roar::Representer
|
9
|
+
property :name
|
10
|
+
property :band
|
11
|
+
end
|
12
|
+
|
13
|
+
@song = Object.new.extend(@representer)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should add accessors" do
|
17
|
+
@song.extend Roar::Representer::Feature::Client
|
18
|
+
@song.name = "Social Suicide"
|
19
|
+
@song.band = "Bad Religion"
|
20
|
+
assert_equal "Social Suicide", @song.name
|
21
|
+
assert_equal "Bad Religion", @song.band
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/test/fake_server.rb
CHANGED
@@ -36,13 +36,13 @@ class FakeServer < Sinatra::Base
|
|
36
36
|
end
|
37
37
|
|
38
38
|
|
39
|
-
require
|
39
|
+
require './test/order_representers'
|
40
40
|
JSON::Order.class_eval do
|
41
41
|
def items_url
|
42
|
-
"http://
|
42
|
+
"http://roar.example.com/orders/1/items"
|
43
43
|
end
|
44
44
|
def order_url(order)
|
45
|
-
"http://
|
45
|
+
"http://roar.example.com/orders/#{order}"
|
46
46
|
end
|
47
47
|
def represented
|
48
48
|
1
|
@@ -72,4 +72,3 @@ class FakeServer < Sinatra::Base
|
|
72
72
|
|
73
73
|
end
|
74
74
|
|
75
|
-
FakeServer.run! :host => 'localhost', :port => 9999
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'roar/representer/json/hal'
|
2
|
+
|
3
|
+
class HalJsonTest < MiniTest::Spec
|
4
|
+
module SongRepresenter
|
5
|
+
include Roar::Representer::JSON
|
6
|
+
include Roar::Representer::JSON::HAL::Links
|
7
|
+
|
8
|
+
link :self do
|
9
|
+
"http://self"
|
10
|
+
end
|
11
|
+
|
12
|
+
link :rel => :next, :title => "Hey, @myabc" do
|
13
|
+
"http://hit"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "JSON::HAL::Links" do
|
18
|
+
before do
|
19
|
+
@song = Object.new.extend(SongRepresenter)
|
20
|
+
end
|
21
|
+
|
22
|
+
it "renders links according to the HAL spec" do
|
23
|
+
assert_equal "{\"links\":{\"self\":{\"href\":\"http://self\"},\"next\":{\"href\":\"http://hit\",\"title\":\"Hey, @myabc\"}}}", @song.to_json
|
24
|
+
end
|
25
|
+
|
26
|
+
it "parses incoming JSON links correctly" do
|
27
|
+
@song.from_json "{\"links\":{\"self\":{\"href\":\"http://self\",\"title\":\"Hey, @myabc\"}}}"
|
28
|
+
assert_equal "http://self", @song.links[:self].href
|
29
|
+
assert_equal "Hey, @myabc", @song.links[:self].title
|
30
|
+
assert_equal nil, @song.links[:next]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
describe "HAL/JSON" do
|
36
|
+
before do
|
37
|
+
Bla = Module.new do
|
38
|
+
include Roar::Representer::JSON::HAL
|
39
|
+
property :value
|
40
|
+
link :self do
|
41
|
+
"http://items/#{value}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
@order_rep = Module.new do
|
46
|
+
include Roar::Representer::JSON::HAL
|
47
|
+
property :id
|
48
|
+
collection :items, :class => Item, :extend => Bla, :embedded => true
|
49
|
+
link :self do
|
50
|
+
"http://orders/#{id}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
@order = Order.new(:items => [Item.new(:value => "Beer")], :id => 1).extend(@order_rep)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "render links and embedded resources according to HAL" do
|
58
|
+
assert_equal "{\"id\":1,\"_embedded\":{\"items\":[{\"value\":\"Beer\",\"_links\":{\"self\":{\"href\":\"http://items/Beer\"}}}]},\"_links\":{\"self\":{\"href\":\"http://orders/1\"}}}", @order.to_json
|
59
|
+
end
|
60
|
+
|
61
|
+
it "parses links and resources following the mighty HAL" do
|
62
|
+
@order.from_json("{\"id\":2,\"_embedded\":{\"items\":[{\"value\":\"Coffee\",\"_links\":{\"self\":{\"href\":\"http://items/Coffee\"}}}]},\"_links\":{\"self\":{\"href\":\"http://orders/2\"}}}")
|
63
|
+
assert_equal 2, @order.id
|
64
|
+
assert_equal "Coffee", @order.items.first.value
|
65
|
+
assert_equal "http://items/Coffee", @order.items.first.links[:self].href
|
66
|
+
assert_equal "http://orders/2", @order.links[:self].href
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -32,7 +32,7 @@ class HttpVerbsTest < MiniTest::Spec
|
|
32
32
|
include Roar::Representer::Feature::HttpVerbs
|
33
33
|
attr_accessor :name, :label
|
34
34
|
end
|
35
|
-
@band = @Band.get("http://
|
35
|
+
@band = @Band.get("http://roar.example.com/bands/slayer", "application/json")
|
36
36
|
assert_equal "Slayer", @band.name
|
37
37
|
assert_equal "Canadian Maple", @band.label
|
38
38
|
end
|
@@ -40,7 +40,7 @@ class HttpVerbsTest < MiniTest::Spec
|
|
40
40
|
|
41
41
|
describe "#get" do
|
42
42
|
it "updates instance with incoming representation" do
|
43
|
-
@band.get("http://
|
43
|
+
@band.get("http://roar.example.com/bands/slayer", "application/json")
|
44
44
|
assert_equal "Slayer", @band.name
|
45
45
|
assert_equal "Canadian Maple", @band.label
|
46
46
|
end
|
@@ -51,7 +51,7 @@ class HttpVerbsTest < MiniTest::Spec
|
|
51
51
|
@band.name = "Strung Out"
|
52
52
|
assert_equal nil, @band.label
|
53
53
|
|
54
|
-
@band.post("http://
|
54
|
+
@band.post("http://roar.example.com/bands", "application/xml")
|
55
55
|
assert_equal "Strung Out", @band.name
|
56
56
|
assert_equal "n/a", @band.label
|
57
57
|
end
|
@@ -61,7 +61,7 @@ class HttpVerbsTest < MiniTest::Spec
|
|
61
61
|
it "updates instance with incoming representation" do
|
62
62
|
@band.name = "Strung Out"
|
63
63
|
@band.label = "Fat Wreck"
|
64
|
-
@band.put("http://
|
64
|
+
@band.put("http://roar.example.com/bands/strungout", "application/xml")
|
65
65
|
assert_equal "Strung Out", @band.name
|
66
66
|
assert_equal "Fat Wreck", @band.label
|
67
67
|
end
|
@@ -4,6 +4,36 @@ require 'roar/representer/json'
|
|
4
4
|
|
5
5
|
class HypermediaTest
|
6
6
|
describe "Hypermedia Feature" do
|
7
|
+
describe "Hypermedia.link" do
|
8
|
+
before do
|
9
|
+
@mod = Module.new do
|
10
|
+
include Roar::Representer::JSON
|
11
|
+
include Roar::Representer::Feature::Hypermedia
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
it "accepts rel symbol, only" do
|
16
|
+
@mod.class_eval do
|
17
|
+
link :self do
|
18
|
+
"http://self"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
assert_equal "{\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"}]}", Object.new.extend(@mod).to_json
|
23
|
+
end
|
24
|
+
|
25
|
+
it "accepts any options" do
|
26
|
+
@mod.class_eval do
|
27
|
+
link :rel => :self, :title => "Hey, @myabc" do
|
28
|
+
"http://self"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
assert_equal "{\"links\":[{\"rel\":\"self\",\"href\":\"http://self\",\"title\":\"Hey, @myabc\"}]}", Object.new.extend(@mod).to_json
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
|
7
37
|
before do
|
8
38
|
@bookmarks = Class.new do
|
9
39
|
include AttributesContructor
|
@@ -67,7 +97,7 @@ class HypermediaTest
|
|
67
97
|
attr_accessor :note
|
68
98
|
end
|
69
99
|
|
70
|
-
assert_equal "{\"note\":{\"links\":[{\"rel\":\"self\",\"href\":\"http://me\"}]}}", Page.new(note
|
100
|
+
assert_equal "{\"note\":{\"links\":[{\"rel\":\"self\",\"href\":\"http://me\"}]}}", Page.new(:note => Note.new).to_json
|
71
101
|
end
|
72
102
|
end
|
73
103
|
|
@@ -95,7 +125,7 @@ class HypermediaTest
|
|
95
125
|
describe "#links" do
|
96
126
|
before do
|
97
127
|
@set = @bookmarks.new
|
98
|
-
hyper = Roar::Representer::
|
128
|
+
hyper = Roar::Representer::Feature::Hypermedia::Hyperlink
|
99
129
|
|
100
130
|
@set.links = [
|
101
131
|
{:rel => "self", :href => "http://self"},
|
@@ -115,10 +145,10 @@ class HypermediaTest
|
|
115
145
|
end
|
116
146
|
|
117
147
|
describe "#link[]" do
|
118
|
-
it "
|
119
|
-
assert_equal "http://self", @set.links["self"]
|
120
|
-
assert_equal "http://self", @set.links[:self]
|
121
|
-
assert_equal "http://next", @set.links[:next]
|
148
|
+
it "returns link object" do
|
149
|
+
assert_equal "http://self", @set.links["self"].href
|
150
|
+
assert_equal "http://self", @set.links[:self].href
|
151
|
+
assert_equal "http://next", @set.links[:next].href
|
122
152
|
assert_equal nil, @set.links[:prev]
|
123
153
|
end
|
124
154
|
end
|
@@ -171,7 +201,9 @@ class LinkCollectionTest < MiniTest::Spec
|
|
171
201
|
describe "LinkCollection" do
|
172
202
|
it "provides #update_link" do
|
173
203
|
collection = Roar::Representer::Feature::Hypermedia::LinkCollection.new
|
174
|
-
link = Roar::Representer::
|
204
|
+
link = Roar::Representer::Feature::Hypermedia::Hyperlink.new
|
205
|
+
link.rel = "self"
|
206
|
+
link.href = "http://self"
|
175
207
|
|
176
208
|
collection.update_link(link)
|
177
209
|
assert_equal 1, collection.size
|
@@ -182,3 +214,27 @@ class LinkCollectionTest < MiniTest::Spec
|
|
182
214
|
end
|
183
215
|
end
|
184
216
|
|
217
|
+
class HyperlinkTest < MiniTest::Spec
|
218
|
+
Hyperlink = Roar::Representer::Feature::Hypermedia::Hyperlink
|
219
|
+
describe "Hyperlink" do
|
220
|
+
before do
|
221
|
+
@link = Hyperlink.new(:rel => "self", :href => "http://self")
|
222
|
+
end
|
223
|
+
|
224
|
+
it "accepts string keys in constructor" do
|
225
|
+
assert_equal "Hey, @myabc", Hyperlink.new("title" => "Hey, @myabc").title
|
226
|
+
end
|
227
|
+
|
228
|
+
it "responds to #media" do
|
229
|
+
assert_equal nil, @link.media
|
230
|
+
end
|
231
|
+
|
232
|
+
it "responds to #rel" do
|
233
|
+
assert_equal "self", @link.rel
|
234
|
+
end
|
235
|
+
|
236
|
+
it "responds to #href" do
|
237
|
+
assert_equal "http://self", @link.href
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
@@ -30,6 +30,10 @@ class JsonRepresenterTest < MiniTest::Spec
|
|
30
30
|
it "is aliased by #serialize" do
|
31
31
|
assert_equal '{"id":1}', @order.serialize
|
32
32
|
end
|
33
|
+
|
34
|
+
it "accepts :include and :except" do
|
35
|
+
assert_equal '{}', @order.to_json(:except => [:id])
|
36
|
+
end
|
33
37
|
end
|
34
38
|
|
35
39
|
describe "#from_json" do
|
@@ -46,6 +50,15 @@ class JsonRepresenterTest < MiniTest::Spec
|
|
46
50
|
it "works with a nil document" do
|
47
51
|
assert @order.from_json(nil)
|
48
52
|
end
|
53
|
+
|
54
|
+
it "works with an empty document" do
|
55
|
+
assert @order.from_json('')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "accepts :include and :except" do
|
59
|
+
@order.from_json('{"id":1}', :except => [:id])
|
60
|
+
assert_equal nil, @order.id
|
61
|
+
end
|
49
62
|
end
|
50
63
|
|
51
64
|
describe "JSON.from_json" do
|
@@ -57,18 +70,27 @@ class JsonRepresenterTest < MiniTest::Spec
|
|
57
70
|
end
|
58
71
|
end
|
59
72
|
|
73
|
+
# test the generic roar+json HyperlinkRepresenter
|
60
74
|
class JsonHyperlinkRepresenterTest
|
61
75
|
describe "API" do
|
62
76
|
before do
|
63
|
-
@
|
77
|
+
@link = Roar::Representer::Feature::Hypermedia::Hyperlink.new.extend(Roar::Representer::JSON::HyperlinkRepresenter).from_json({:rel => :self, :href => "http://roar.apotomo.de", :media => "web"}.to_json)
|
64
78
|
end
|
65
79
|
|
66
80
|
it "responds to #rel" do
|
67
|
-
assert_equal "self", @
|
81
|
+
assert_equal "self", @link.rel
|
68
82
|
end
|
69
83
|
|
70
84
|
it "responds to #href" do
|
71
|
-
assert_equal "http://roar.apotomo.de", @
|
85
|
+
assert_equal "http://roar.apotomo.de", @link.href
|
86
|
+
end
|
87
|
+
|
88
|
+
it "responds to #media" do
|
89
|
+
assert_equal "web", @link.media
|
90
|
+
end
|
91
|
+
|
92
|
+
it "responds to #to_json" do
|
93
|
+
assert_equal "{\"rel\":\"self\",\"href\":\"http://roar.apotomo.de\",\"media\":\"web\"}", @link.to_json
|
72
94
|
end
|
73
95
|
end
|
74
96
|
end
|
@@ -105,6 +127,17 @@ class JsonHypermediaTest
|
|
105
127
|
it "renders link: correctly in JSON" do
|
106
128
|
assert_equal "{\"id\":1,\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"},{\"rel\":\"next\",\"href\":\"http://next/1\"}]}", @c.new(:id => 1).to_json
|
107
129
|
end
|
130
|
+
|
131
|
+
it "doesn't render links when empty" do
|
132
|
+
assert_equal("{\"links\":[]}", Class.new do
|
133
|
+
include Roar::Representer::JSON
|
134
|
+
include Roar::Representer::Feature::Hypermedia
|
135
|
+
|
136
|
+
link :self do nil end
|
137
|
+
link :next do false end
|
138
|
+
end.new.to_json)
|
139
|
+
end
|
140
|
+
|
108
141
|
end
|
109
142
|
end
|
110
143
|
|
data/test/test_helper.rb
CHANGED
@@ -5,7 +5,6 @@ require 'test/unit'
|
|
5
5
|
require 'minitest/spec'
|
6
6
|
|
7
7
|
require 'roar/representer'
|
8
|
-
require 'roar/representer/feature/hypermedia'
|
9
8
|
require 'roar/representer/feature/http_verbs'
|
10
9
|
|
11
10
|
|
@@ -34,3 +33,10 @@ end
|
|
34
33
|
|
35
34
|
require "test_xml/mini_test"
|
36
35
|
require "roar/representer/xml"
|
36
|
+
|
37
|
+
require 'sham_rack'
|
38
|
+
require './test/fake_server'
|
39
|
+
|
40
|
+
ShamRack.at('roar.example.com').rackup do
|
41
|
+
run FakeServer
|
42
|
+
end
|
data/test/transport_test.rb
CHANGED
@@ -8,24 +8,24 @@ class TransportTest < MiniTest::Spec
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "#get_uri returns response" do
|
11
|
-
assert_equal "<method>get</method>", @transport.get_uri("http://
|
11
|
+
assert_equal "<method>get</method>", @transport.get_uri("http://roar.example.com/method", "application/xml").body
|
12
12
|
end
|
13
13
|
|
14
14
|
it "#post_uri returns response" do
|
15
|
-
assert_equal "<method>post</method>", @transport.post_uri("http://
|
15
|
+
assert_equal "<method>post</method>", @transport.post_uri("http://roar.example.com/method", "booty", "application/xml").body
|
16
16
|
end
|
17
17
|
|
18
18
|
it "#put_uri returns response" do
|
19
|
-
assert_equal "<method>put</method>", @transport.put_uri("http://
|
19
|
+
assert_equal "<method>put</method>", @transport.put_uri("http://roar.example.com/method", "booty", "application/xml").body
|
20
20
|
end
|
21
21
|
|
22
22
|
it "#delete_uri returns response" do
|
23
|
-
assert_equal "<method>delete</method>", @transport.delete_uri("http://
|
23
|
+
assert_equal "<method>delete</method>", @transport.delete_uri("http://roar.example.com/method", "application/xml").body
|
24
24
|
end
|
25
25
|
|
26
26
|
# TODO: how to get PATCH into Sinatra?
|
27
27
|
#it "#patch_uri returns Restfulie response" do
|
28
|
-
# assert_equal "<method>patch</method>", @o.patch_uri("http://
|
28
|
+
# assert_equal "<method>patch</method>", @o.patch_uri("http://roar.example.com/method", "booty", "application/xml").body
|
29
29
|
#end
|
30
30
|
end
|
31
31
|
end
|
@@ -18,34 +18,15 @@ class PositionRepresenter
|
|
18
18
|
end
|
19
19
|
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
class XMLRepresenterUnitTest < MiniTest::Spec
|
24
|
-
describe "XmlRepresenter" do
|
25
|
-
describe "#link" do
|
26
|
-
class Rapper
|
27
|
-
include Roar::Representer::XML
|
28
|
-
include Roar::Representer::Feature::Hypermedia
|
29
|
-
|
30
|
-
link :self
|
31
|
-
link :next
|
32
|
-
end
|
33
|
-
|
34
|
-
it "creates a LinksDefinition" do
|
35
|
-
assert_equal 1, Rapper.representable_attrs.size
|
36
|
-
assert_equal [{:rel=>:self, :block=>nil}, {:rel=>:next, :block=>nil}], Rapper.representable_attrs.first.rel2block
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
|
43
21
|
class XMLRepresenterFunctionalTest < MiniTest::Spec
|
44
|
-
class
|
22
|
+
class Order
|
45
23
|
include AttributesContructor
|
46
24
|
attr_accessor :id, :items
|
47
25
|
end
|
48
26
|
|
27
|
+
class GreedyOrder < Order
|
28
|
+
end
|
29
|
+
|
49
30
|
class TestXmlRepresenter
|
50
31
|
include Roar::Representer::XML
|
51
32
|
self.representation_wrap= :order
|
@@ -58,6 +39,7 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
|
|
58
39
|
before do
|
59
40
|
@m = {"id" => "1"}
|
60
41
|
@o = Order.new(@m)
|
42
|
+
|
61
43
|
@r = TestXmlRepresenter.new
|
62
44
|
@i = ItemRepresenter.new
|
63
45
|
@i.value = "Beer"
|
@@ -77,6 +59,10 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
|
|
77
59
|
it "is aliased by #serialize" do
|
78
60
|
assert_equal @r.to_xml, @r.serialize
|
79
61
|
end
|
62
|
+
|
63
|
+
it "accepts :include and :except" do
|
64
|
+
assert_equal '<order/>', @r.to_xml(:except => [:id])
|
65
|
+
end
|
80
66
|
end
|
81
67
|
|
82
68
|
describe "#from_xml" do
|
@@ -89,6 +75,11 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
|
|
89
75
|
@order = Order.new.deserialize("<order><id>1</id></order>")
|
90
76
|
assert_equal "1", @order.id
|
91
77
|
end
|
78
|
+
|
79
|
+
it "accepts :include and :except" do
|
80
|
+
@order = Order.new.deserialize("<order><id>1</id></order>", :except => [:id])
|
81
|
+
assert_equal nil, @order.id
|
82
|
+
end
|
92
83
|
end
|
93
84
|
|
94
85
|
|
@@ -195,20 +186,23 @@ end
|
|
195
186
|
class XmlHyperlinkRepresenterTest < MiniTest::Spec
|
196
187
|
describe "API" do
|
197
188
|
before do
|
198
|
-
@
|
189
|
+
@link = Roar::Representer::Feature::Hypermedia::Hyperlink.new.extend(Roar::Representer::XML::HyperlinkRepresenter).from_xml(%{<link rel="self" href="http://roar.apotomo.de" media="web"/>})
|
199
190
|
end
|
200
191
|
|
201
|
-
it "responds to #
|
202
|
-
|
192
|
+
it "responds to #rel" do
|
193
|
+
assert_equal "self", @link.rel
|
203
194
|
end
|
204
195
|
|
196
|
+
it "responds to #href" do
|
197
|
+
assert_equal "http://roar.apotomo.de", @link.href
|
198
|
+
end
|
205
199
|
|
206
|
-
it "responds to #
|
207
|
-
assert_equal "
|
200
|
+
it "responds to #media" do
|
201
|
+
assert_equal "web", @link.media
|
208
202
|
end
|
209
203
|
|
210
|
-
it "responds to #
|
211
|
-
|
204
|
+
it "responds to #to_xml" do
|
205
|
+
assert_xml_equal %{<link rel=\"self\" href=\"http://roar.apotomo.de\" media="web"/>}, @link.to_xml
|
212
206
|
end
|
213
207
|
end
|
214
208
|
end
|
metadata
CHANGED
@@ -1,90 +1,92 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: roar
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 9
|
8
|
-
- 2
|
9
|
-
version: 0.9.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.10.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Nick Sutterer
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
dependencies:
|
20
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2012-03-22 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
21
15
|
name: representable
|
22
|
-
|
23
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &82244490 !ruby/object:Gem::Requirement
|
24
17
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
- 1
|
30
|
-
- 1
|
31
|
-
version: "1.1"
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.3
|
32
22
|
type: :runtime
|
33
|
-
version_requirements: *id001
|
34
|
-
- !ruby/object:Gem::Dependency
|
35
|
-
name: test_xml
|
36
23
|
prerelease: false
|
37
|
-
|
24
|
+
version_requirements: *82244490
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &82244190 !ruby/object:Gem::Requirement
|
38
28
|
none: false
|
39
|
-
requirements:
|
40
|
-
- -
|
41
|
-
- !ruby/object:Gem::Version
|
42
|
-
|
43
|
-
- 0
|
44
|
-
version: "0"
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
45
33
|
type: :development
|
46
|
-
version_requirements: *id002
|
47
|
-
- !ruby/object:Gem::Dependency
|
48
|
-
name: minitest
|
49
34
|
prerelease: false
|
50
|
-
|
35
|
+
version_requirements: *82244190
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: test_xml
|
38
|
+
requirement: &82243710 !ruby/object:Gem::Requirement
|
51
39
|
none: false
|
52
|
-
requirements:
|
53
|
-
- -
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *82243710
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: minitest
|
49
|
+
requirement: &82243040 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
59
54
|
version: 2.8.1
|
60
55
|
type: :development
|
61
|
-
version_requirements: *id003
|
62
|
-
- !ruby/object:Gem::Dependency
|
63
|
-
name: sinatra
|
64
56
|
prerelease: false
|
65
|
-
|
57
|
+
version_requirements: *82243040
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: sinatra
|
60
|
+
requirement: &82242340 !ruby/object:Gem::Requirement
|
66
61
|
none: false
|
67
|
-
requirements:
|
62
|
+
requirements:
|
68
63
|
- - ~>
|
69
|
-
- !ruby/object:Gem::Version
|
70
|
-
segments:
|
71
|
-
- 1
|
72
|
-
- 2
|
73
|
-
- 6
|
64
|
+
- !ruby/object:Gem::Version
|
74
65
|
version: 1.2.6
|
75
66
|
type: :development
|
76
|
-
|
77
|
-
|
78
|
-
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *82242340
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sham_rack
|
71
|
+
requirement: &82241770 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 1.3.0
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *82241770
|
80
|
+
description: Streamlines the development of RESTful, resource-oriented architectures
|
81
|
+
in Ruby.
|
82
|
+
email:
|
79
83
|
- apotonick@gmail.com
|
80
84
|
executables: []
|
81
|
-
|
82
85
|
extensions: []
|
83
|
-
|
84
86
|
extra_rdoc_files: []
|
85
|
-
|
86
|
-
files:
|
87
|
+
files:
|
87
88
|
- .gitignore
|
89
|
+
- .travis.yml
|
88
90
|
- CHANGES.markdown
|
89
91
|
- Gemfile
|
90
92
|
- README.textile
|
@@ -93,14 +95,17 @@ files:
|
|
93
95
|
- lib/roar.rb
|
94
96
|
- lib/roar/rails.rb
|
95
97
|
- lib/roar/representer.rb
|
98
|
+
- lib/roar/representer/feature/client.rb
|
96
99
|
- lib/roar/representer/feature/http_verbs.rb
|
97
100
|
- lib/roar/representer/feature/hypermedia.rb
|
98
101
|
- lib/roar/representer/feature/transport.rb
|
99
102
|
- lib/roar/representer/json.rb
|
103
|
+
- lib/roar/representer/json/hal.rb
|
100
104
|
- lib/roar/representer/xml.rb
|
101
105
|
- lib/roar/version.rb
|
102
106
|
- roar.gemspec
|
103
107
|
- test/Gemfile
|
108
|
+
- test/client_test.rb
|
104
109
|
- test/dummy/Rakefile
|
105
110
|
- test/dummy/app/controllers/albums_controller.rb
|
106
111
|
- test/dummy/app/controllers/application_controller.rb
|
@@ -137,6 +142,7 @@ files:
|
|
137
142
|
- test/dummy/tmp/app/cells/blog/post/latest.html.erb
|
138
143
|
- test/dummy/tmp/app/cells/blog/post_cell.rb
|
139
144
|
- test/fake_server.rb
|
145
|
+
- test/hal_json_test.rb
|
140
146
|
- test/http_verbs_feature_test.rb
|
141
147
|
- test/hypermedia_feature_test.rb
|
142
148
|
- test/integration_test.rb
|
@@ -148,37 +154,28 @@ files:
|
|
148
154
|
- test/test_helper.rb
|
149
155
|
- test/transport_test.rb
|
150
156
|
- test/xml_representer_test.rb
|
151
|
-
has_rdoc: true
|
152
157
|
homepage: http://rubygems.org/gems/roar
|
153
158
|
licenses: []
|
154
|
-
|
155
159
|
post_install_message:
|
156
160
|
rdoc_options: []
|
157
|
-
|
158
|
-
require_paths:
|
161
|
+
require_paths:
|
159
162
|
- lib
|
160
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
163
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
161
164
|
none: false
|
162
|
-
requirements:
|
163
|
-
- -
|
164
|
-
- !ruby/object:Gem::Version
|
165
|
-
|
166
|
-
|
167
|
-
version: "0"
|
168
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - ! '>='
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '0'
|
169
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
170
|
none: false
|
170
|
-
requirements:
|
171
|
-
- -
|
172
|
-
- !ruby/object:Gem::Version
|
173
|
-
|
174
|
-
- 0
|
175
|
-
version: "0"
|
171
|
+
requirements:
|
172
|
+
- - ! '>='
|
173
|
+
- !ruby/object:Gem::Version
|
174
|
+
version: '0'
|
176
175
|
requirements: []
|
177
|
-
|
178
176
|
rubyforge_project: roar
|
179
|
-
rubygems_version: 1.
|
177
|
+
rubygems_version: 1.8.10
|
180
178
|
signing_key:
|
181
179
|
specification_version: 3
|
182
180
|
summary: Resource-oriented architectures in Ruby.
|
183
181
|
test_files: []
|
184
|
-
|