restfully 0.3.2 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +6 -0
- data/README.rdoc +82 -92
- data/Rakefile +1 -0
- data/VERSION +1 -1
- data/bin/restfully +10 -46
- data/examples/grid5000.rb +5 -5
- data/lib/restfully.rb +3 -2
- data/lib/restfully/collection.rb +64 -139
- data/lib/restfully/extensions.rb +0 -17
- data/lib/restfully/http/adapters/abstract_adapter.rb +1 -1
- data/lib/restfully/http/adapters/rest_client_adapter.rb +25 -3
- data/lib/restfully/http/request.rb +20 -3
- data/lib/restfully/http/response.rb +21 -3
- data/lib/restfully/link.rb +4 -3
- data/lib/restfully/resource.rb +144 -74
- data/lib/restfully/session.rb +36 -22
- data/restfully.gemspec +9 -4
- data/spec/collection_spec.rb +24 -25
- data/spec/http/request_spec.rb +6 -2
- data/spec/http/response_spec.rb +4 -0
- data/spec/http/rest_client_adapter_spec.rb +3 -2
- data/spec/link_spec.rb +7 -4
- data/spec/resource_spec.rb +31 -56
- data/spec/session_spec.rb +77 -41
- metadata +13 -2
data/CHANGELOG
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
0.4.0
|
2
|
+
* removed 'root_path' option: 'base_uri' must point to the starting resource;
|
3
|
+
* objects can now be pretty printed using 'pp object';
|
4
|
+
* Restfully::Collection now include the Enumerable module;
|
5
|
+
* Restfully::Collection inherits from Restfully::Resource;
|
6
|
+
* 'object.uid' is no longer valid. Use 'object["uid"]' instead;
|
data/README.rdoc
CHANGED
@@ -10,105 +10,95 @@ Alpha work.
|
|
10
10
|
== Usage
|
11
11
|
=== Command line
|
12
12
|
$ export RUBYOPT="-rubygems"
|
13
|
-
$ restfully base_uri [
|
13
|
+
$ restfully base_uri [-u username] [-p password]
|
14
14
|
|
15
15
|
e.g., for the Grid5000 API:
|
16
|
-
$ restfully https://api.grid5000.fr/sid
|
17
|
-
|
18
|
-
If the connection was successful, you should get a prompt.
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
@uid: "ee1f8111c8835496a9e4a6f7c9491c0238ee9827"
|
95
|
-
@type: "version"
|
96
|
-
@parent: Restfully::Resource
|
97
|
-
------------ PROPERTIES ------------
|
98
|
-
"author" => "Cyril Constantin <>"
|
99
|
-
"date" => "Fri, 11 Sep 2009 14:32:48 GMT"
|
100
|
-
"message" => "[environments] update of environments on sites">
|
101
|
-
|
102
|
-
You may also prefer to use a configuration file to avoid entering the command line options:
|
16
|
+
$ restfully https://api.grid5000.fr/sid/grid5000 -u username -p password
|
17
|
+
|
18
|
+
If the connection was successful, you should get a prompt. You may enter
|
19
|
+
irb(main):001:0> pp root
|
20
|
+
|
21
|
+
to get back a pretty-printed output of the root resource:
|
22
|
+
#<Restfully::Resource:0x91f08c
|
23
|
+
@uri=#<URI::HTTP:0x123e30c URL:http://api.local/sid/grid5000>
|
24
|
+
LINKS
|
25
|
+
@environments=#<Restfully::Collection:0x917666>,
|
26
|
+
@sites=#<Restfully::Collection:0x9170d0>,
|
27
|
+
@version=#<Restfully::Resource:0x91852a>,
|
28
|
+
@versions=#<Restfully::Collection:0x917e68>
|
29
|
+
PROPERTIES
|
30
|
+
"uid"=>"grid5000",
|
31
|
+
"type"=>"grid",
|
32
|
+
"version"=>"4fe96b25d2cbfee16abe5a4fb999c82dbafc2ee8">
|
33
|
+
|
34
|
+
You can see the LINKS and PROPERTIES headers that respectively indicate what links you can follow from there (by calling +root.link_name+) and what properties are available (by calling +root[property_name]+).
|
35
|
+
|
36
|
+
Let's say you want to access the collection of +sites+, you would enter:
|
37
|
+
irb(main):002:0> pp root.sites
|
38
|
+
|
39
|
+
and get back:
|
40
|
+
#<Restfully::Collection:0x9170d0
|
41
|
+
@uri=#<URI::HTTP:0x122e128 URL:http://api.local/sid/grid5000/sites>
|
42
|
+
LINKS
|
43
|
+
@version=#<Restfully::Resource:0x8f553e>,
|
44
|
+
@versions=#<Restfully::Collection:0x8f52be>
|
45
|
+
PROPERTIES
|
46
|
+
"total"=>9,
|
47
|
+
"version"=>"4fe96b25d2cbfee16abe5a4fb999c82dbafc2ee8",
|
48
|
+
"offset"=>0
|
49
|
+
ITEMS (0..9)/9
|
50
|
+
#<Restfully::Resource:0x9058bc uid="bordeaux">,
|
51
|
+
#<Restfully::Resource:0x903d0a uid="grenoble">,
|
52
|
+
#<Restfully::Resource:0x901cc6 uid="lille">,
|
53
|
+
#<Restfully::Resource:0x8fff0c uid="lyon">,
|
54
|
+
#<Restfully::Resource:0x8fe288 uid="nancy">,
|
55
|
+
#<Restfully::Resource:0x8fc4a6 uid="orsay">,
|
56
|
+
#<Restfully::Resource:0x8fa782 uid="rennes">,
|
57
|
+
#<Restfully::Resource:0x8f8bb2 uid="sophia">,
|
58
|
+
#<Restfully::Resource:0x8f6c9a uid="toulouse">>
|
59
|
+
|
60
|
+
A Restfully::Collection is a special kind of Resource, which includes the Enumerable module, which means you can call all of its methods on the Restfully::Collection object. For example:
|
61
|
+
irb(main):003:0> pp root.sites.find{|s| s['uid'] == 'rennes'}
|
62
|
+
#<Restfully::Resource:0x8fa782
|
63
|
+
@uri=#<URI::HTTP:0x11f4e64 URL:http://api.local/sid/grid5000/sites/rennes>
|
64
|
+
LINKS
|
65
|
+
@environments=#<Restfully::Collection:0x8f9ab2>,
|
66
|
+
@parent=#<Restfully::Resource:0x8f981e>,
|
67
|
+
@deployments=#<Restfully::Collection:0x8f935a>,
|
68
|
+
@clusters=#<Restfully::Collection:0x8f9d46>,
|
69
|
+
@version=#<Restfully::Resource:0x8fa354>,
|
70
|
+
@versions=#<Restfully::Collection:0x8fa0b6>,
|
71
|
+
@status=#<Restfully::Collection:0x8f95ee>
|
72
|
+
PROPERTIES
|
73
|
+
"name"=>"Rennes",
|
74
|
+
"latitude"=>48.1,
|
75
|
+
"location"=>"Rennes, France",
|
76
|
+
"security_contact"=>"rennes-staff@lists.grid5000.fr",
|
77
|
+
"uid"=>"rennes",
|
78
|
+
"type"=>"site",
|
79
|
+
"user_support_contact"=>"rennes-staff@lists.grid5000.fr",
|
80
|
+
"version"=>"4fe96b25d2cbfee16abe5a4fb999c82dbafc2ee8",
|
81
|
+
"description"=>"",
|
82
|
+
"longitude"=>-1.6667,
|
83
|
+
"compilation_server"=>false,
|
84
|
+
"email_contact"=>"rennes-staff@lists.grid5000.fr",
|
85
|
+
"web"=>"http://www.irisa.fr",
|
86
|
+
"sys_admin_contact"=>"rennes-staff@lists.grid5000.fr">
|
87
|
+
|
88
|
+
or:
|
89
|
+
irb(main):006:0> root.sites.map{|s| s['uid']}.grep(/re/)
|
90
|
+
=> ["grenoble", "rennes"]
|
91
|
+
|
92
|
+
|
93
|
+
To enter the command-line options, you may prefer to use a configuration file to avoid re-entering the options every time you use the client:
|
103
94
|
$ echo '
|
104
|
-
base_uri: https://api.grid5000.fr/sid
|
105
|
-
root_path: /grid5000
|
95
|
+
base_uri: https://api.grid5000.fr/sid/grid5000
|
106
96
|
username: MYLOGIN
|
107
97
|
password: MYPASSWORD
|
108
|
-
' >
|
98
|
+
' > ~/.restfully/api.grid5000.fr.yml && chmod 600 ~/.restfully/api.grid5000.fr.yml
|
109
99
|
|
110
100
|
And then:
|
111
|
-
$ restfully -c
|
101
|
+
$ restfully -c ~/.restfully/api.grid5000.fr.yml
|
112
102
|
|
113
103
|
=== As a library
|
114
104
|
See the +examples+ directory for examples.
|
data/Rakefile
CHANGED
@@ -11,6 +11,7 @@ begin
|
|
11
11
|
gem.homepage = "http://github.com/crohr/restfully"
|
12
12
|
gem.authors = ["Cyril Rohr"]
|
13
13
|
gem.add_dependency "rest-client", '>= 1.0'
|
14
|
+
gem.add_dependency "backports"
|
14
15
|
gem.rubyforge_project = 'restfully'
|
15
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
17
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
data/bin/restfully
CHANGED
@@ -1,19 +1,26 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# The command line Restfully client
|
3
3
|
|
4
|
-
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
4
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' unless $LOAD_PATH.include? File.dirname(__FILE__) + '/../lib'
|
5
5
|
|
6
6
|
require 'restfully'
|
7
7
|
require 'optparse'
|
8
8
|
require 'logger'
|
9
9
|
require 'yaml'
|
10
|
+
require 'pp'
|
10
11
|
|
11
12
|
|
12
13
|
logger = Logger.new(STDOUT)
|
13
14
|
logger.level = Logger::WARN
|
14
15
|
@options = {:logger => logger}
|
15
16
|
option_parser = OptionParser.new do |opts|
|
16
|
-
opts.banner =
|
17
|
+
opts.banner = <<BANNER
|
18
|
+
* Description
|
19
|
+
Restfully #{Restfully::VERSION} - Access REST APIs effortlessly
|
20
|
+
* Usage
|
21
|
+
restfully [base_uri] [root_path] [options]
|
22
|
+
* Options
|
23
|
+
BANNER
|
17
24
|
|
18
25
|
opts.on("-u=", "--username=", "Sets the username") do |u|
|
19
26
|
@options[:username] = u
|
@@ -43,7 +50,6 @@ end
|
|
43
50
|
option_parser.parse!
|
44
51
|
|
45
52
|
@options[:base_uri] = ARGV.shift
|
46
|
-
@options[:root_path] = ARGV.shift || "/"
|
47
53
|
|
48
54
|
def session
|
49
55
|
@session ||= Restfully::Session.new(@options)
|
@@ -51,52 +57,10 @@ end
|
|
51
57
|
|
52
58
|
def root
|
53
59
|
@root ||= session.root.load
|
54
|
-
rescue Restfully::HTTP::Error => e
|
55
|
-
puts "#{e.class.name}: #{e.message}"
|
56
60
|
end
|
57
61
|
|
58
62
|
require 'irb'
|
59
63
|
require 'irb/completion'
|
60
64
|
ARGV.clear
|
61
65
|
IRB.start
|
62
|
-
exit!
|
63
|
-
|
64
|
-
|
65
|
-
# if (config_filename = @options.delete('configuration_file')) && File.exists?(File.expand_path(config_filename))
|
66
|
-
# config = YAML.load_file(File.expand_path(config_filename))
|
67
|
-
# @base_uri = config.delete('base_uri') || @base_uri
|
68
|
-
# @root_path = config.delete('root_path') || @root_path
|
69
|
-
# @options.merge!(config)
|
70
|
-
# end
|
71
|
-
#
|
72
|
-
# unless @base_uri
|
73
|
-
# $stderr.puts option_parser.help
|
74
|
-
# exit(-1)
|
75
|
-
# else
|
76
|
-
# if (log_file=@options.delete('log'))
|
77
|
-
# @logger = Logger.new(File.expand_path(log_file))
|
78
|
-
# else
|
79
|
-
# @logger = Logger.new(STDOUT)
|
80
|
-
# end
|
81
|
-
# if @options.delete('verbose')
|
82
|
-
# @logger.level = Logger::DEBUG
|
83
|
-
# else
|
84
|
-
# @logger.level = Logger::WARN
|
85
|
-
# end
|
86
|
-
#
|
87
|
-
# def session
|
88
|
-
# @session ||= Restfully::Session.new(@base_uri, @options.merge('root_path' => @root_path, 'logger' => @logger))
|
89
|
-
# end
|
90
|
-
# def root
|
91
|
-
# @root ||= Restfully::Resource.new(session.root_path, session).load
|
92
|
-
# end
|
93
|
-
#
|
94
|
-
# root # preloads
|
95
|
-
#
|
96
|
-
# require 'irb'
|
97
|
-
# require 'irb/completion'
|
98
|
-
#
|
99
|
-
# ARGV.clear
|
100
|
-
# IRB.start
|
101
|
-
# exit!
|
102
|
-
# end
|
66
|
+
exit!
|
data/examples/grid5000.rb
CHANGED
@@ -5,12 +5,12 @@ require 'pp'
|
|
5
5
|
require File.dirname(__FILE__)+'/../lib/restfully'
|
6
6
|
|
7
7
|
logger = Logger.new(STDOUT)
|
8
|
-
logger.level = Logger::
|
8
|
+
logger.level = Logger::WARN
|
9
9
|
|
10
10
|
# Restfully.adapter = Restfully::HTTP::RestClientAdapter
|
11
11
|
# Restfully.adapter = Patron::Session
|
12
12
|
RestClient.log = 'stdout'
|
13
|
-
Restfully::Session.new(:base_uri => 'http://api.local/sid
|
13
|
+
Restfully::Session.new(:base_uri => 'http://api.local/sid/grid5000', :logger => logger) do |grid, session|
|
14
14
|
grid_stats = {'hardware' => {}, 'system' => {}}
|
15
15
|
grid.sites.each do |site|
|
16
16
|
site_stats = site.status.inject({'hardware' => {}, 'system' => {}}) {|accu, node_status|
|
@@ -20,9 +20,9 @@ Restfully::Session.new(:base_uri => 'http://api.local/sid', :root_path => '/grid
|
|
20
20
|
} rescue {'hardware' => {}, 'system' => {}}
|
21
21
|
grid_stats['hardware'].merge!(site_stats['hardware']) { |key,oldval,newval| oldval+newval }
|
22
22
|
grid_stats['system'].merge!(site_stats['system']) { |key,oldval,newval| oldval+newval }
|
23
|
-
p [site
|
23
|
+
p [site['uid'], site_stats]
|
24
24
|
end
|
25
25
|
p [:total, grid_stats]
|
26
26
|
puts "Getting status of a few nodes in rennes:"
|
27
|
-
pp grid.sites.
|
28
|
-
end
|
27
|
+
pp grid.sites.find{|s| s['uid'] == 'rennes'}.status(:query => {:only => ['paradent-1', 'paradent-10', 'paramount-3']})
|
28
|
+
end
|
data/lib/restfully.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'backports'
|
1
2
|
require 'restfully/error'
|
2
3
|
require 'restfully/parsing'
|
3
4
|
require 'restfully/http'
|
@@ -12,9 +13,9 @@ require 'restfully/collection'
|
|
12
13
|
|
13
14
|
|
14
15
|
module Restfully
|
15
|
-
VERSION = "0.
|
16
|
+
VERSION = "0.4.0"
|
16
17
|
class << self
|
17
18
|
attr_accessor :adapter
|
18
19
|
end
|
19
20
|
self.adapter = Restfully::HTTP::Adapters::RestClientAdapter
|
20
|
-
end
|
21
|
+
end
|
data/lib/restfully/collection.rb
CHANGED
@@ -1,161 +1,86 @@
|
|
1
|
-
require 'delegate'
|
2
1
|
|
3
2
|
module Restfully
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
# This includes the <tt>Enumerable</tt> module, but does not have all the
|
4
|
+
# methods that you could expect from an <tt>Array</tt>.
|
5
|
+
# Remember that this class inherits from a <tt>Restfully::Resource</tt> and
|
6
|
+
# as such, the <tt>#[]</tt> method gives access to Resource properties, and
|
7
|
+
# not to an item in the collection.
|
8
|
+
# If you want to operate on the array of items, you MUST call <tt>#to_a</tt>
|
9
|
+
# first (or <tt>#items</tt>) on the Restfully::Collection.
|
10
|
+
class Collection < Resource
|
11
|
+
include Enumerable
|
12
|
+
attr_reader :items
|
8
13
|
|
14
|
+
# See Resource#new
|
9
15
|
def initialize(uri, session, options = {})
|
10
|
-
|
11
|
-
@uri = uri
|
12
|
-
@title = options[:title]
|
13
|
-
@session = session
|
14
|
-
reset
|
15
|
-
super(@items)
|
16
|
+
super(uri, session, options)
|
16
17
|
end
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
|
19
|
+
# See Resource#reset
|
20
20
|
def reset
|
21
|
-
|
22
|
-
@
|
23
|
-
@
|
24
|
-
|
25
|
-
@items = []
|
26
|
-
@raw = nil
|
27
|
-
@state = :unloaded
|
21
|
+
super
|
22
|
+
@items = Array.new
|
23
|
+
@indexes = Hash.new
|
24
|
+
self
|
28
25
|
end
|
29
26
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
else
|
34
|
-
super(key)
|
35
|
-
end
|
27
|
+
# Iterates over the collection of items
|
28
|
+
def each(*args, &block)
|
29
|
+
@items.each(*args, &block)
|
36
30
|
end
|
37
|
-
|
38
|
-
def
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
}
|
49
|
-
if args.empty?
|
50
|
-
@indexes[method.to_s]
|
51
|
-
elsif args.length == 1
|
52
|
-
@indexes[method.to_s][args.first]
|
53
|
-
else
|
54
|
-
@indexes[method.to_s].values_at(*args)
|
55
|
-
end
|
56
|
-
else
|
57
|
-
super(method, *args)
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
|
-
def load(options = {})
|
62
|
-
options = options.symbolize_keys
|
63
|
-
force_reload = !!options.delete(:reload)
|
64
|
-
request_hash = [:get, options].hash
|
65
|
-
if loaded? && !force_reload && request_hash == @last_request_hash
|
66
|
-
self
|
67
|
-
else
|
68
|
-
reset
|
69
|
-
@last_request_hash = request_hash
|
70
|
-
@raw = options[:raw]
|
71
|
-
if raw.nil? || force_reload
|
72
|
-
response = session.get(uri, options)
|
73
|
-
@raw = response.body
|
74
|
-
end
|
75
|
-
raw.each do |key, value|
|
76
|
-
case key
|
77
|
-
when "total", "offset"
|
78
|
-
instance_variable_set("@#{key}".to_sym, value)
|
79
|
-
when "links"
|
80
|
-
value.each{|link| define_link(Link.new(link))}
|
81
|
-
when "items"
|
82
|
-
value.each do |item|
|
83
|
-
self_link = (item['links'] || []).map{|link| Link.new(link)}.detect{|link| link.self?}
|
84
|
-
if self_link && self_link.valid?
|
85
|
-
self.push Resource.new(self_link.href, session).load(:raw => item)
|
86
|
-
else
|
87
|
-
session.logger.warn "Resource #{key} does not have a 'self' link. skipped."
|
88
|
-
end
|
89
|
-
end
|
31
|
+
|
32
|
+
def populate_object(key, value)
|
33
|
+
case key
|
34
|
+
when "links"
|
35
|
+
value.each{|link| define_link(Link.new(link))}
|
36
|
+
when "items"
|
37
|
+
value.each do |item|
|
38
|
+
self_link = (item['links'] || []).
|
39
|
+
map{|link| Link.new(link)}.detect{|link| link.self?}
|
40
|
+
if self_link && self_link.valid?
|
41
|
+
@items.push Resource.new(uri.merge(self_link.href), session).load(:body => item)
|
90
42
|
else
|
91
|
-
|
92
|
-
when Hash
|
93
|
-
@attributes.store(key, SpecialHash.new.replace(value)) unless @associations.has_key?(key)
|
94
|
-
when Array
|
95
|
-
@attributes.store(key, SpecialArray.new(value))
|
96
|
-
else
|
97
|
-
@attributes.store(key, value)
|
98
|
-
end
|
43
|
+
session.logger.warn "Resource #{key} does not have a 'self' link. skipped."
|
99
44
|
end
|
100
45
|
end
|
101
|
-
|
102
|
-
|
46
|
+
else
|
47
|
+
case value
|
48
|
+
when Hash
|
49
|
+
@properties.store(key, SpecialHash.new.replace(value)) unless @links.has_key?(key)
|
50
|
+
when Array
|
51
|
+
@properties.store(key, SpecialArray.new(value))
|
52
|
+
else
|
53
|
+
@properties.store(key, value)
|
54
|
+
end
|
103
55
|
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def inspect
|
59
|
+
@items.inspect
|
104
60
|
end
|
105
61
|
|
106
|
-
|
107
|
-
|
62
|
+
# Returns the current number of items (not the total number)
|
63
|
+
# in the collection.
|
64
|
+
def length
|
65
|
+
@items.length
|
108
66
|
end
|
109
67
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
# output += "\n#{options[:space]}------------ PROPERTIES ------------"
|
123
|
-
# @attributes.each do |key, value|
|
124
|
-
# output += "\n#{options[:space]}#{key.inspect} => #{value.inspect}"
|
125
|
-
# end
|
126
|
-
# end
|
127
|
-
# unless self.empty?
|
128
|
-
# output += "\n#{options[:space]}------------ ITEMS ------------"
|
129
|
-
# self.each do |value|
|
130
|
-
# output += "\n#{options[:space]}#{value.class.name}"
|
131
|
-
# end
|
132
|
-
# end
|
133
|
-
# end
|
134
|
-
# output += ">"
|
135
|
-
# end
|
136
|
-
|
137
|
-
protected
|
138
|
-
def define_link(link)
|
139
|
-
if link.valid?
|
140
|
-
case link.rel
|
141
|
-
when 'parent'
|
142
|
-
@associations['parent'] = Resource.new(link.href, session)
|
143
|
-
when 'collection'
|
144
|
-
raw_included = link.resolved? ? raw[link.title] : nil
|
145
|
-
@associations[link.title] = Collection.new(link.href, session,
|
146
|
-
:raw => raw_included,
|
147
|
-
:title => link.title)
|
148
|
-
when 'member'
|
149
|
-
raw_included = link.resolved? ? raw[link.title] : nil
|
150
|
-
@associations[link.title] = Resource.new(link.href, session,
|
151
|
-
:title => link.title,
|
152
|
-
:raw => raw_included)
|
153
|
-
when 'self'
|
154
|
-
# we do nothing
|
68
|
+
def pretty_print(pp)
|
69
|
+
super(pp) do |pp|
|
70
|
+
if @items.length > 0
|
71
|
+
pp.breakable
|
72
|
+
pp.text "ITEMS (#{self["offset"]}..#{self["offset"]+@items.length})/#{self["total"]}"
|
73
|
+
pp.nest 2 do
|
74
|
+
@items.each_with_index do |item, i|
|
75
|
+
pp.breakable
|
76
|
+
pp.text "#<#{item.class}:0x#{item.object_id.to_s(16)} uid=#{item['uid'].inspect}>"
|
77
|
+
pp.text "," if i < @items.length-1
|
78
|
+
end
|
79
|
+
end
|
155
80
|
end
|
156
|
-
else
|
157
|
-
session.logger.warn link.errors.join("\n")
|
158
81
|
end
|
159
82
|
end
|
83
|
+
|
84
|
+
alias_method :size, :length
|
160
85
|
end
|
161
86
|
end
|