restfully 0.3.2 → 0.4.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/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
|