restful 0.2.20
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.markdown +40 -0
- data/LICENSE.markdown +22 -0
- data/README.markdown +126 -0
- data/Rakefile +22 -0
- data/TODO.markdown +10 -0
- data/init.rb +1 -0
- data/lib/restful.rb +65 -0
- data/lib/restful/apimodel/attribute.rb +17 -0
- data/lib/restful/apimodel/collection.rb +22 -0
- data/lib/restful/apimodel/link.rb +21 -0
- data/lib/restful/apimodel/map.rb +41 -0
- data/lib/restful/apimodel/resource.rb +23 -0
- data/lib/restful/converters/active_record.rb +160 -0
- data/lib/restful/rails.rb +22 -0
- data/lib/restful/rails/action_controller.rb +14 -0
- data/lib/restful/rails/active_record/configuration.rb +219 -0
- data/lib/restful/rails/active_record/metadata_tools.rb +102 -0
- data/lib/restful/serializers/atom_like_serializer.rb +51 -0
- data/lib/restful/serializers/base.rb +58 -0
- data/lib/restful/serializers/hash_serializer.rb +46 -0
- data/lib/restful/serializers/json_serializer.rb +18 -0
- data/lib/restful/serializers/params_serializer.rb +46 -0
- data/lib/restful/serializers/xml_serializer.rb +160 -0
- data/rails/init.rb +1 -0
- data/restful.gemspec +17 -0
- data/test/converters/active_record_converter_test.rb +147 -0
- data/test/converters/basic_types_converter_test.rb +99 -0
- data/test/fixtures/models/paginated_collection.rb +3 -0
- data/test/fixtures/models/person.rb +29 -0
- data/test/fixtures/models/pet.rb +5 -0
- data/test/fixtures/models/wallet.rb +5 -0
- data/test/fixtures/people.json.yaml +107 -0
- data/test/fixtures/people.xml.yaml +117 -0
- data/test/fixtures/pets.json.yaml +20 -0
- data/test/fixtures/pets.xml.yaml +31 -0
- data/test/rails/active_record_metadata_test.rb +23 -0
- data/test/rails/configuration_test.rb +47 -0
- data/test/rails/restful_publish_test.rb +54 -0
- data/test/serializers/atom_serializer_test.rb +33 -0
- data/test/serializers/json_serializer_test.rb +90 -0
- data/test/serializers/params_serializer_test.rb +76 -0
- data/test/serializers/xml_serializer_test.rb +51 -0
- data/test/test_helper.rb +154 -0
- metadata +106 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'restful/serializers/base'
|
2
|
+
|
3
|
+
#
|
4
|
+
# Vanilla Hash.
|
5
|
+
#
|
6
|
+
module Restful
|
7
|
+
module Serializers
|
8
|
+
class HashSerializer < Base
|
9
|
+
|
10
|
+
serializer_name :hash
|
11
|
+
|
12
|
+
def serialize(obj, options = {})
|
13
|
+
case obj.type
|
14
|
+
when :link then obj.value
|
15
|
+
when :simple_attribute then serialize(obj.value)
|
16
|
+
when :collection then serialize_collection(obj)
|
17
|
+
when :map then serialize_array_of_apimodels(obj.values)
|
18
|
+
when :resource then serialize_array_of_apimodels(obj.values, { "restful_url" => obj.full_url })
|
19
|
+
else
|
20
|
+
formatted_ruby_type(obj)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def serialize_collection(collection)
|
27
|
+
if entries = collection.total_entries
|
28
|
+
{ :total_entries => entries, collection.name => serialize_unpaginated_collection(collection) }
|
29
|
+
else
|
30
|
+
serialize_unpaginated_collection(collection)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def serialize_unpaginated_collection(collection)
|
35
|
+
collection.value.map { |r| serialize(r) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def serialize_array_of_apimodels(apimodels, defaults = {})
|
39
|
+
apimodels.inject(defaults) do |memo, apimodel|
|
40
|
+
memo[apimodel.name.to_s.underscore.to_sym] = serialize(apimodel)
|
41
|
+
memo
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'restful/serializers/base'
|
2
|
+
require 'yajl'
|
3
|
+
|
4
|
+
#
|
5
|
+
# AR params hash.
|
6
|
+
#
|
7
|
+
module Restful
|
8
|
+
module Serializers
|
9
|
+
class JsonSerializer < Base
|
10
|
+
|
11
|
+
serializer_name :json
|
12
|
+
|
13
|
+
def serialize(resource, options = {})
|
14
|
+
Yajl::Encoder.encode HashSerializer.new.serialize(resource, options)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'restful/serializers/base'
|
2
|
+
require 'builder'
|
3
|
+
|
4
|
+
#
|
5
|
+
# AR params hash.
|
6
|
+
#
|
7
|
+
module Restful
|
8
|
+
module Serializers
|
9
|
+
class ParamsSerializer < Base
|
10
|
+
|
11
|
+
serializer_name :params
|
12
|
+
|
13
|
+
def serialize(resource, options = {})
|
14
|
+
params = {}
|
15
|
+
resource.values.each do |value|
|
16
|
+
if value.type == :collection # serialize the stuffs
|
17
|
+
resources = value.value
|
18
|
+
next if resources.empty?
|
19
|
+
name = resources.first.name.pluralize
|
20
|
+
|
21
|
+
array = []
|
22
|
+
resources.each do |resource|
|
23
|
+
array << serialize(resource)
|
24
|
+
end
|
25
|
+
|
26
|
+
params["#{paramify_keys(value.name)}_attributes".to_sym] = array
|
27
|
+
elsif value.type == :link
|
28
|
+
params[paramify_keys(value.name).to_sym] = Restful::Rails.tools.dereference(value.value)
|
29
|
+
elsif value.type == :resource
|
30
|
+
params["#{paramify_keys(value.name)}_attributes".to_sym] = serialize(value)
|
31
|
+
else # plain ole
|
32
|
+
params[paramify_keys(value.name).to_sym] = value.value # no need to format dates etc - just pass objects through.
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
params
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def paramify_keys(original_key)
|
42
|
+
original_key.to_s.tr("-", "_")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,160 @@
|
|
1
|
+
require 'restful/serializers/base'
|
2
|
+
require "rexml/document"
|
3
|
+
require 'builder'
|
4
|
+
|
5
|
+
#
|
6
|
+
# Converts an APIModel to and from XML.
|
7
|
+
#
|
8
|
+
module Restful
|
9
|
+
module Serializers
|
10
|
+
class XMLSerializer < Base
|
11
|
+
|
12
|
+
serializer_name :xml
|
13
|
+
|
14
|
+
def serialize(resource, options = {})
|
15
|
+
|
16
|
+
xml = options[:builder] || Builder::XmlMarkup.new(:indent => 2)
|
17
|
+
xml.instruct! unless options[:instruct].is_a?(FalseClass)
|
18
|
+
|
19
|
+
raise NotImplementedError.new("xml serialization of maps has not been implemented. ") if resource.class == Restful::ApiModel::Map
|
20
|
+
|
21
|
+
if resource.is_a?(Restful::ApiModel::Collection)
|
22
|
+
add_collection(resource, xml, show_as_array = false)
|
23
|
+
else
|
24
|
+
xml.tag!(*root_element(resource)) do
|
25
|
+
add_link_to(resource, xml, :self => true)
|
26
|
+
|
27
|
+
resource.values.each do |value|
|
28
|
+
if value.type == :collection # serialize the stuffs
|
29
|
+
add_collection(value, xml)
|
30
|
+
elsif value.type == :link
|
31
|
+
add_link_to(value, xml)
|
32
|
+
elsif value.type == :resource
|
33
|
+
serialize(value, {:instruct => false, :builder => xml})
|
34
|
+
else # plain ole
|
35
|
+
add_tag(xml, value)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# returns a resource, or collection of resources.
|
43
|
+
def deserialize(xml, options = {})
|
44
|
+
build_resource(REXML::Document.new(xml).root)
|
45
|
+
end
|
46
|
+
|
47
|
+
protected
|
48
|
+
|
49
|
+
def add_collection(value, xml, show_as_array = true)
|
50
|
+
resources = value.value
|
51
|
+
if first_resource = resources.first
|
52
|
+
xml.tag!(first_resource.name.pluralize, (show_as_array ? collections_decorations : {})) do
|
53
|
+
resources.each do |resource|
|
54
|
+
serialize(resource, { :instruct => false, :builder => xml })
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_link_to(resource, builder, options = {})
|
61
|
+
is_self = !!options[:self]
|
62
|
+
|
63
|
+
attributes = {:type => "link"}
|
64
|
+
attributes.merge!(:nil => "true") if resource.full_url.blank?
|
65
|
+
builder.tag!((is_self ? "restful-url" : transform_link_name(resource.name)), resource.full_url, attributes)
|
66
|
+
end
|
67
|
+
|
68
|
+
def add_tag(builder, value)
|
69
|
+
|
70
|
+
if value.extended_type == :hash
|
71
|
+
build_hash(builder, value)
|
72
|
+
else
|
73
|
+
builder.tag!(value.name.to_s.dasherize, serialize_attribute(value), decorations(value))
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def build_hash(builder, value)
|
78
|
+
builder.tag!(value.name.to_s.dasherize) do
|
79
|
+
value.value.each do |k, v|
|
80
|
+
builder.tag! k.to_s.dasherize, v
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def decorations(value)
|
86
|
+
decorations = {}
|
87
|
+
|
88
|
+
if value.extended_type == :binary
|
89
|
+
decorations[:encoding] = 'base64'
|
90
|
+
end
|
91
|
+
|
92
|
+
if value.extended_type != :string and value.extended_type != :notype
|
93
|
+
decorations[:type] = value.extended_type
|
94
|
+
end
|
95
|
+
|
96
|
+
if value.extended_type == :datetime
|
97
|
+
decorations[:type] = :datetime
|
98
|
+
end
|
99
|
+
|
100
|
+
if value.value.nil?
|
101
|
+
decorations[:nil] = true
|
102
|
+
end
|
103
|
+
|
104
|
+
if value.value.is_a?(FalseClass) || value.value.is_a?(TrueClass)
|
105
|
+
decorations[:type] = :boolean
|
106
|
+
end
|
107
|
+
|
108
|
+
decorations
|
109
|
+
end
|
110
|
+
|
111
|
+
def collections_decorations
|
112
|
+
{ :type => "array" }
|
113
|
+
end
|
114
|
+
|
115
|
+
def root_element(resource, options = {})
|
116
|
+
[resource.name]
|
117
|
+
end
|
118
|
+
|
119
|
+
# turns a rexml node into a Resource
|
120
|
+
def build_resource(node)
|
121
|
+
resource = root_resource(node)
|
122
|
+
|
123
|
+
node.elements.each do |el|
|
124
|
+
type = calculate_node_type(el)
|
125
|
+
resource.values << case type
|
126
|
+
|
127
|
+
when :link : build_link(el, type)
|
128
|
+
when :datetime
|
129
|
+
Restful.attr(el.name, DateTime.parse(el.text), type)
|
130
|
+
when :resource
|
131
|
+
build_resource(el)
|
132
|
+
when :array
|
133
|
+
Restful.collection(el.name, el.elements.map { |child| build_resource(child) }, type)
|
134
|
+
else
|
135
|
+
Restful.attr(el.name, el.text, type)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
resource
|
140
|
+
end
|
141
|
+
|
142
|
+
def calculate_node_type(el)
|
143
|
+
if el.children.size > 1 && el.attributes["type"].blank?
|
144
|
+
return :resource
|
145
|
+
else
|
146
|
+
(el.attributes["type"] || "string").to_sym
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def build_link(el, type)
|
151
|
+
Restful.link(revert_link_name(el.name), nil, el.text, type)
|
152
|
+
end
|
153
|
+
|
154
|
+
def root_resource(node)
|
155
|
+
url = node.delete_element("restful-url").try(:text)
|
156
|
+
Restful.resource(node.name, :url => url)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'restful'
|
data/restful.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "restful"
|
3
|
+
s.version = "0.2.20"
|
4
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
5
|
+
s.authors = ["Daniel Bornkessel", "Rany Keddo"]
|
6
|
+
s.date = "2009-08-11"
|
7
|
+
s.email = "M4SSIVE@m4ssive.com"
|
8
|
+
s.extra_rdoc_files = %w{ README.markdown }
|
9
|
+
s.files = %w{ CHANGES.markdown init.rb lib/restful/apimodel/attribute.rb lib/restful/apimodel/collection.rb lib/restful/apimodel/link.rb lib/restful/apimodel/map.rb lib/restful/apimodel/resource.rb lib/restful/converters/active_record.rb lib/restful/rails/action_controller.rb lib/restful/rails/active_record/configuration.rb lib/restful/rails/active_record/metadata_tools.rb lib/restful/rails.rb lib/restful/serializers/atom_like_serializer.rb lib/restful/serializers/base.rb lib/restful/serializers/hash_serializer.rb lib/restful/serializers/json_serializer.rb lib/restful/serializers/params_serializer.rb lib/restful/serializers/xml_serializer.rb lib/restful.rb LICENSE.markdown rails/init.rb Rakefile README.markdown restful.gemspec test/converters/active_record_converter_test.rb test/converters/basic_types_converter_test.rb test/fixtures/models/paginated_collection.rb test/fixtures/models/person.rb test/fixtures/models/pet.rb test/fixtures/models/wallet.rb test/fixtures/people.json.yaml test/fixtures/people.xml.yaml test/fixtures/pets.json.yaml test/fixtures/pets.xml.yaml test/rails/active_record_metadata_test.rb test/rails/configuration_test.rb test/rails/restful_publish_test.rb test/serializers/atom_serializer_test.rb test/serializers/json_serializer_test.rb test/serializers/params_serializer_test.rb test/serializers/xml_serializer_test.rb test/test_helper.rb TODO.markdown }
|
10
|
+
s.has_rdoc = true
|
11
|
+
s.rdoc_options = ["--line-numbers", "--inline-source"]
|
12
|
+
s.homepage = "http://github.com/M4SSIVE/restful"
|
13
|
+
s.require_paths = %w{ lib }
|
14
|
+
s.requirements = %w{ brianmario-yajl-ruby }
|
15
|
+
s.rubygems_version = "1.3.1"
|
16
|
+
s.summary = "api niceness. "
|
17
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper.rb'
|
2
|
+
|
3
|
+
#
|
4
|
+
# FIXME: remove xml serialzation here and test resource directly.
|
5
|
+
#
|
6
|
+
context "active record converter" do
|
7
|
+
setup do
|
8
|
+
Person.restful_publish(:name, :wallet, :current_location, :pets => [:name, :species])
|
9
|
+
Pet.restful_publish(:person_id, :name) # person_id gets converted to a link automagically.
|
10
|
+
|
11
|
+
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree", :birthday => "1976-04-03")
|
12
|
+
@wallet = @person.wallet = Wallet.create!(:contents => "something in the wallet")
|
13
|
+
@pet = @person.pets.create(:name => "Mietze", :species => "cat")
|
14
|
+
end
|
15
|
+
|
16
|
+
teardown do
|
17
|
+
reset_config
|
18
|
+
end
|
19
|
+
|
20
|
+
specify "should publish link and not resource when :oldest_pet_restful_url, where oldest_pet is a defined method" do
|
21
|
+
Person.restful_publish(:oldest_pet_restful_url)
|
22
|
+
@person.to_restful.links.size.should.== 1
|
23
|
+
@person.to_restful.links.first.name.should.== "oldest-pet-restful-url"
|
24
|
+
end
|
25
|
+
|
26
|
+
specify "should publish link and not a nested resource with :wallet_restful_url" do
|
27
|
+
Person.restful_publish(:wallet_restful_url)
|
28
|
+
@person.to_restful.links.size.should.== 1
|
29
|
+
@person.to_restful.links.first.name.should.== "wallet-restful-url"
|
30
|
+
@person.to_restful.links.first.value.should.== @wallet.restful_url
|
31
|
+
end
|
32
|
+
|
33
|
+
specify "should be able to force expansion. force expanded attributes can never be collapsed. " do
|
34
|
+
Wallet.restful_publish(:contents)
|
35
|
+
Person.restful_publish(:name, :wallet, :current_location, { :pets => [:name, :species], :restful_options => { :force_expand => :wallet } })
|
36
|
+
Pet.restful_publish(:owner, :name)
|
37
|
+
|
38
|
+
@pet.to_restful
|
39
|
+
end
|
40
|
+
|
41
|
+
specify "should return link attributes from a model" do
|
42
|
+
@pet.to_restful.links.map { |node| node.name }.sort.should.equal [:person_id]
|
43
|
+
end
|
44
|
+
|
45
|
+
specify "should convert a NULL inner association such as person.wallet to a link with a null value" do
|
46
|
+
@person.wallet = nil
|
47
|
+
|
48
|
+
wallet = @person.to_restful(:restful_options => { :expansion => :collapsed }).links.select { |link| link.name == "wallet-restful-url" }.first
|
49
|
+
wallet.should.not.== nil
|
50
|
+
wallet.value.should.== nil
|
51
|
+
end
|
52
|
+
|
53
|
+
specify "should return plain attributes from a model" do
|
54
|
+
@pet.to_restful.simple_attributes.map { |node| node.name }.should.equal [:name]
|
55
|
+
end
|
56
|
+
|
57
|
+
specify "should return collections attributes from a model" do
|
58
|
+
restful = @person.to_restful
|
59
|
+
restful.collections.map { |node| node.name }.sort.should.equal [:pets]
|
60
|
+
end
|
61
|
+
|
62
|
+
specify "should set correct type for date" do
|
63
|
+
restful = @person.to_restful :birthday
|
64
|
+
restful.simple_attributes.detect { |node| node.name == :birthday }.extended_type.should.== :date
|
65
|
+
end
|
66
|
+
|
67
|
+
specify "should be able to convert themselves to an apimodel containing all and only the attributes exposed by Model.publish_api" do
|
68
|
+
resource = @person.to_restful
|
69
|
+
|
70
|
+
resource.simple_attributes.select { |node| node.name == :name }.should.not.blank
|
71
|
+
resource.simple_attributes.select { |node| node.name == :biography }.should.blank
|
72
|
+
|
73
|
+
mietze = @person.to_restful.collections .select { |node| node.name == :pets }.first.value.first
|
74
|
+
mietze.simple_attributes.size.should.== 2
|
75
|
+
mietze.simple_attributes.select { |node| node.name == :name }.should.not.blank
|
76
|
+
mietze.simple_attributes.select { |node| node.name == :species }.should.not.blank
|
77
|
+
end
|
78
|
+
|
79
|
+
specify "should be able to convert themselves to an apimodel containing all and only the attributes exposed by Model.publish_api. this holds true if to_restful is called with some configuration options. " do
|
80
|
+
resource = @person.to_restful(:restful_options => { :nested => false })
|
81
|
+
resource.simple_attributes.select { |node| node.name == :name }.should.not.blank
|
82
|
+
resource.simple_attributes.select { |node| node.name == :biography }.should.blank
|
83
|
+
|
84
|
+
mietze = resource.collections .select { |node| node.name == :pets }.first.value.first
|
85
|
+
mietze.simple_attributes.size.should.== 2
|
86
|
+
mietze.simple_attributes.select { |node| node.name == :name }.should.not.blank
|
87
|
+
mietze.simple_attributes.select { |node| node.name == :species }.should.not.blank
|
88
|
+
end
|
89
|
+
|
90
|
+
specify "should be able to override to_restful published fields by passing them into the method" do
|
91
|
+
api = @person.to_restful(:pets)
|
92
|
+
|
93
|
+
api.simple_attributes.should.blank?
|
94
|
+
api.collections.map { |node| node.name }.sort.should.equal [:pets]
|
95
|
+
end
|
96
|
+
|
97
|
+
specify "should be able to handle relations that are nil/null" do
|
98
|
+
@person.wallet = nil
|
99
|
+
@person.save!
|
100
|
+
@person.reload
|
101
|
+
|
102
|
+
assert_nothing_raised do
|
103
|
+
@person.to_restful
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
specify "should be able to expand a :belongs_to relationship" do
|
108
|
+
xml_should_eql_fixture(@pet.to_restful_xml(:owner), "pets", :nameless_pet)
|
109
|
+
end
|
110
|
+
|
111
|
+
specify "should return collapsed resources by default when :expansion => :collapsed is passed" do
|
112
|
+
Person.restful_publish(:name, :wallet, :restful_options => { :expansion => :collapsed })
|
113
|
+
xml_should_eql_fixture(@person.to_restful_xml, "people", :joe_bloggs)
|
114
|
+
end
|
115
|
+
|
116
|
+
specify "should be able to export content generated by methods that return strings" do
|
117
|
+
xml_should_eql_fixture(@person.to_restful_xml(:location_sentence), "people", :no_wallet)
|
118
|
+
end
|
119
|
+
|
120
|
+
specify "should be able to export content generated by methods (not attributes) and compute the correct style" do
|
121
|
+
xml_should_eql_fixture(@person.to_restful_xml(:oldest_pet), "people", :with_oldest_pet)
|
122
|
+
end
|
123
|
+
|
124
|
+
specify "should be able to export content generated by methods (not attributes) while filtering with a nested configuration" do
|
125
|
+
xml_should_eql_fixture(@person.to_restful_xml(:oldest_pet => [:species]), "people", :with_oldest_pet_species)
|
126
|
+
end
|
127
|
+
|
128
|
+
specify "should create element with nil='true' attribute if no relation is set" do
|
129
|
+
@person.wallet = nil
|
130
|
+
@person.save
|
131
|
+
|
132
|
+
xml_should_eql_fixture(@person.to_restful_xml(:wallet), "people", :joe_with_zwiebelleder)
|
133
|
+
end
|
134
|
+
|
135
|
+
specify "should include attributes when include parameter is passed to to_restful" do
|
136
|
+
Person.restful_publish(:name)
|
137
|
+
Pet.restful_publish(:name)
|
138
|
+
|
139
|
+
@person = Person.create
|
140
|
+
@pet = @person.pets.create(:name => "Mietze")
|
141
|
+
|
142
|
+
@pet.to_restful(:include => :owner).values.map(&:name).should.include :owner
|
143
|
+
Pet.restful_config.whitelisted.include?(:owner).should.equal false
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper.rb'
|
2
|
+
|
3
|
+
context "basic types converter" do
|
4
|
+
|
5
|
+
teardown { reset_config }
|
6
|
+
|
7
|
+
specify "should be able to convert a hash to a resource map" do
|
8
|
+
Person.restful_publish(:name)
|
9
|
+
resource = { "zeperson" => @person = Person.create(:name => "fuddzle") }.to_restful
|
10
|
+
resource.should.is_a?(Restful::ApiModel::Map)
|
11
|
+
|
12
|
+
attrs = resource.simple_attributes
|
13
|
+
attrs.size.should.== 1
|
14
|
+
attrs.first.name.should.== "zeperson"
|
15
|
+
|
16
|
+
attrs.first.value.values.first.value.== "fuddzle"
|
17
|
+
end
|
18
|
+
|
19
|
+
specify "should raise exception if not all array contents respond to .to_restful" do
|
20
|
+
Person.restful_publish(:name)
|
21
|
+
|
22
|
+
should.raise(TypeError) do
|
23
|
+
[""].to_restful
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
specify "should convert an empty array to a restful collection" do
|
28
|
+
collection = [].to_restful
|
29
|
+
collection.name.should.== "nil-classes"
|
30
|
+
end
|
31
|
+
|
32
|
+
specify "should infer array name from first element class" do
|
33
|
+
collection = [Pet.new].to_restful
|
34
|
+
collection.name.should.== "pets"
|
35
|
+
end
|
36
|
+
|
37
|
+
specify "should infer array name from first element base_class if it is an active_record object" do
|
38
|
+
collection = [Emu.new, Pet.new].to_restful
|
39
|
+
collection.name.should.== "pets"
|
40
|
+
end
|
41
|
+
|
42
|
+
specify "should convert an array to a restful collection" do
|
43
|
+
Person.restful_publish(:name)
|
44
|
+
|
45
|
+
collection = [Person.create(:name => "Joe Bloggs")].to_restful
|
46
|
+
collection.name.should.== "people"
|
47
|
+
collection.value.size.should.== 1
|
48
|
+
collection.value.first.simple_attributes.first.value.should.== "Joe Bloggs"
|
49
|
+
end
|
50
|
+
|
51
|
+
specify "should set total_entries on the restful collection if the array responds to this" do
|
52
|
+
Person.restful_publish(:name)
|
53
|
+
people = PaginatedCollection.new([Person.create(:name => "Joe Bloggs")])
|
54
|
+
people.total_entries = 1001
|
55
|
+
|
56
|
+
collection = people.to_restful
|
57
|
+
collection.total_entries.should.== 1001
|
58
|
+
end
|
59
|
+
|
60
|
+
specify "should set name on collection if array responds to .name and has this set" do
|
61
|
+
Person.restful_publish(:name)
|
62
|
+
people = PaginatedCollection.new()
|
63
|
+
people.total_entries = 0
|
64
|
+
people.name = "people"
|
65
|
+
|
66
|
+
collection = people.to_restful
|
67
|
+
collection.name.should.== "people"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "basic types converter :includes" do
|
72
|
+
|
73
|
+
specify "should include extra attributes for hashes" do
|
74
|
+
Person.restful_publish(:name)
|
75
|
+
Pet.restful_publish(:name)
|
76
|
+
|
77
|
+
@person = Person.create
|
78
|
+
@pet = @person.pets.create(:name => "Mietze")
|
79
|
+
|
80
|
+
map = { :pet => @pet }.to_restful(:include => :owner)
|
81
|
+
map.values.first.name.should.== :pet
|
82
|
+
map.values.first.value.values.map(&:name).should.include :owner
|
83
|
+
|
84
|
+
Pet.restful_config.whitelisted.include?(:owner).should.equal false
|
85
|
+
end
|
86
|
+
|
87
|
+
specify "should include extra attributes for arrays" do
|
88
|
+
Person.restful_publish(:name)
|
89
|
+
Pet.restful_publish(:name)
|
90
|
+
|
91
|
+
@person = Person.create
|
92
|
+
@pet = @person.pets.create(:name => "Mietze")
|
93
|
+
|
94
|
+
collection = [@pet].to_restful(:include => :owner)
|
95
|
+
collection.value.first.values.map(&:name).should.include :owner
|
96
|
+
|
97
|
+
Pet.restful_config.whitelisted.include?(:owner).should.equal false
|
98
|
+
end
|
99
|
+
end
|