purzelrakete-restful 0.2.1 → 0.2.2
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/README.markdown +14 -6
- data/TODO.markdown +3 -2
- data/init.rb +1 -1
- data/lib/restful/converters/active_record.rb +8 -7
- data/lib/restful/rails/active_record/configuration.rb +9 -3
- data/lib/restful/serializers/base.rb +14 -0
- data/lib/restful/serializers/hash_serializer.rb +14 -12
- data/lib/restful/serializers/params_serializer.rb +12 -6
- data/lib/restful/serializers/xml_serializer.rb +16 -10
- data/restful.gemspec +1 -1
- data/test/converters/active_record_converter_test.rb +14 -1
- data/test/fixtures/models/person.rb +12 -0
- data/test/fixtures/people.json.yaml +53 -0
- data/test/fixtures/people.xml.yaml +20 -2
- data/test/serializers/json_serializer_test.rb +43 -1
- data/test/serializers/params_serializer_test.rb +33 -1
- data/test/serializers/xml_serializer_test.rb +10 -1
- data/test/test_helper.rb +18 -1
- metadata +1 -1
data/README.markdown
CHANGED
@@ -31,8 +31,7 @@ Some example configurations:
|
|
31
31
|
restful_publish :name, :pets, :restful_options => { :expansion => :expanded } # default on level 1-2: expanded. default above: collapsed.
|
32
32
|
restful_publish :name, :pets, :wallet => :contents, :restful_options => { :expansion => :expanded } # combined options and expansion rules
|
33
33
|
restful_publish :name, :pets, :restful_options => { :collapsed => :pets } # collapsed pets, even though they are on the second level.
|
34
|
-
restful_publish :name, :pets, :restful_options => { :
|
35
|
-
restful_publish :name, :pets, :restful_options => { :pets_page => 1, :pets_per_page => 100, :collapsed => :pets }
|
34
|
+
restful_publish :name, :pets, :restful_options => { :force_expanded => [:pets, :wallet] }
|
36
35
|
|
37
36
|
# Pet
|
38
37
|
restful_publish :name, :person # expands person per default because it is on the second level. Does not expand person.pets.first.person, since this is higher than second level.
|
@@ -42,7 +41,9 @@ Rails-like
|
|
42
41
|
|
43
42
|
This format sticks to xml_simple, adding links as `<association-name-restful-url>` nodes of type "link".
|
44
43
|
|
45
|
-
|
44
|
+
|
45
|
+
`Person.last.to_restful.serialize(:xml)` OR
|
46
|
+
`Person.last.to_restful_xml` results in something like...
|
46
47
|
|
47
48
|
<?xml version="1.0" encoding="UTF-8"?>
|
48
49
|
<person>
|
@@ -66,7 +67,8 @@ This format sticks to xml_simple, adding links as `<association-name-restful-url
|
|
66
67
|
Atom-like
|
67
68
|
=========
|
68
69
|
|
69
|
-
`Person.last.to_restful.serialize(:atom_like)`
|
70
|
+
`Person.last.to_restful.serialize(:atom_like)` OR
|
71
|
+
`Person.last.to_restful_atom_like` results in something like...
|
70
72
|
|
71
73
|
<?xml version="1.0" encoding="UTF-8"?>
|
72
74
|
<person xml:base="http://example.com:3000">
|
@@ -89,13 +91,19 @@ Atom-like
|
|
89
91
|
Params-like
|
90
92
|
===========
|
91
93
|
|
92
|
-
`Person.last.to_restful.serialize(:params)`
|
94
|
+
`Person.last.to_restful.serialize(:params)` OR
|
95
|
+
`Person.last.to_restful_params` results in something like...
|
93
96
|
|
94
97
|
{:sex_attributes => {:sex=>"male"},
|
95
98
|
:current_location=>"Under a tree",
|
96
99
|
:name=>"Joe Bloggs",
|
97
100
|
:pets_attributes=> [ {:person_id=>1, :name=>nil} ]
|
98
101
|
}
|
102
|
+
|
103
|
+
Other Serializers
|
104
|
+
=================
|
105
|
+
|
106
|
+
Hash. Spits out a plain ole hash, no nested attributes or such like. Useful for further conversions.
|
99
107
|
|
100
108
|
Deserializing
|
101
109
|
=============
|
@@ -105,4 +113,4 @@ Use `Restful.from_atom_like(xml).serialize(:hash)` to convert from an atom-like
|
|
105
113
|
Nested Attributes
|
106
114
|
=================
|
107
115
|
Serializing uses Rails 2.3 notation of nested attributes. For deserializing you will need Rails 2.3 for having nested attributes support and the respective model must have the
|
108
|
-
`accepts_nested_attributes_for :<table name>` set accordingly
|
116
|
+
`accepts_nested_attributes_for :<table name>` set accordingly.
|
data/TODO.markdown
CHANGED
@@ -3,5 +3,6 @@ Refactor this shice. Seriously, this has devolved into some nasty-ass code.
|
|
3
3
|
* the metamodel is kind of weird. make a better metamodel - how about just using activemodel?
|
4
4
|
* remove requirement to call apiable in model classes; replace with restful_publish with no args (or with args.)
|
5
5
|
* move configuration object out of rails folder - this is general stuff.
|
6
|
-
* remove xml
|
7
|
-
* get rid of to_a warning
|
6
|
+
* remove xml serialization here and test resource directly (in active_record_converter_test)
|
7
|
+
* get rid of to_a warning
|
8
|
+
* convert underscores to dashes (or not) in serializers instead of converter
|
data/init.rb
CHANGED
@@ -1 +1 @@
|
|
1
|
-
require File.dirname(__FILE__) + "/rails/init"
|
1
|
+
require File.dirname(__FILE__) + "/rails/init"
|
@@ -15,7 +15,6 @@ module Restful
|
|
15
15
|
:path => model.restful_path,
|
16
16
|
:url => model.restful_url
|
17
17
|
})
|
18
|
-
|
19
18
|
|
20
19
|
# simple attributes
|
21
20
|
resource.values += Restful::Rails.tools.simple_attributes_on(model).map do |attribute|
|
@@ -41,7 +40,7 @@ module Restful
|
|
41
40
|
end
|
42
41
|
elsif model.class.reflections[key].macro == :has_one or model.class.reflections[key].macro == :belongs_to
|
43
42
|
|
44
|
-
if(config.expanded?
|
43
|
+
if(config.expanded?(key, nested))
|
45
44
|
convert_to_collection(model, key, nested_config, published) do |key, resources, extended_type|
|
46
45
|
returning(resources.first) do |res|
|
47
46
|
res.name = key
|
@@ -74,18 +73,18 @@ module Restful
|
|
74
73
|
resource.values += (model.public_methods - Restful::Rails.tools.simple_attributes_on(model).keys.map(&:to_s)).map do |method_name|
|
75
74
|
if config.published?(method_name.to_sym) and not published.include?(method_name.to_sym)
|
76
75
|
value = model.send(method_name.to_sym)
|
77
|
-
|
76
|
+
sanitized_method_name = method_name.tr("!?", "").tr("_", "-").to_sym
|
78
77
|
|
79
78
|
if value.is_a? ::ActiveRecord::Base
|
80
|
-
if config.expanded?
|
79
|
+
if config.expanded?(method_name.to_sym, nested)
|
81
80
|
returning Restful::Rails.tools.expand(value, config.nested(method_name.to_sym)) do |expanded|
|
82
|
-
expanded.name =
|
81
|
+
expanded.name = sanitized_method_name
|
83
82
|
end
|
84
83
|
else
|
85
|
-
Restful.link("#{
|
84
|
+
Restful.link("#{ sanitized_method_name }-restful-url", Restful::Rails.api_hostname, value ? value.restful_path : "", compute_extended_type(model, key))
|
86
85
|
end
|
87
86
|
else
|
88
|
-
Restful.attr(
|
87
|
+
Restful.attr(sanitized_method_name, value, compute_extended_type(model, method_name))
|
89
88
|
end
|
90
89
|
end
|
91
90
|
end.compact
|
@@ -119,6 +118,8 @@ module Restful
|
|
119
118
|
:string
|
120
119
|
when :time
|
121
120
|
:datetime
|
121
|
+
when :date
|
122
|
+
:date
|
122
123
|
else
|
123
124
|
type_symbol
|
124
125
|
end
|
@@ -42,6 +42,7 @@ module Restful
|
|
42
42
|
end
|
43
43
|
|
44
44
|
config.whitelisted = self.class.restful_config.whitelisted if config.whitelisted.empty?
|
45
|
+
config.restful_options.merge! self.class.restful_config.restful_options
|
45
46
|
|
46
47
|
Restful::Converters::ActiveRecord.convert(self, config)
|
47
48
|
end
|
@@ -75,9 +76,14 @@ module Restful
|
|
75
76
|
@whitelisted.include?(key) || !!@whitelisted.select { |field| field.is_a?(Hash) && field.keys.include?(key) }.first
|
76
77
|
end
|
77
78
|
|
78
|
-
def expanded? # if nothing was set, this defaults to true.
|
79
|
-
@restful_options[:expansion] != :collapsed
|
80
|
-
end
|
79
|
+
def expanded?(key, nested = false) # if nothing was set, this defaults to true.
|
80
|
+
force_expanded?(key) || (@restful_options[:expansion] != :collapsed && !nested)
|
81
|
+
end
|
82
|
+
|
83
|
+
def force_expanded?(key)
|
84
|
+
force = [*@restful_options[:force_expand]]
|
85
|
+
force.include?(key)
|
86
|
+
end
|
81
87
|
|
82
88
|
def nested?
|
83
89
|
!!restful_options[:nested]
|
@@ -28,6 +28,20 @@ module Restful
|
|
28
28
|
self.serializers[key] = self
|
29
29
|
end
|
30
30
|
|
31
|
+
def formatted_value(value)
|
32
|
+
return nil if value.value.blank? && value.extended_type != :false_class
|
33
|
+
case value.extended_type
|
34
|
+
when :datetime
|
35
|
+
value.value.xmlschema
|
36
|
+
when :time
|
37
|
+
value.value.xmlschema
|
38
|
+
when :date
|
39
|
+
value.value.to_s(:db)
|
40
|
+
else
|
41
|
+
value.value
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
31
45
|
protected
|
32
46
|
def transform_link_name(name)
|
33
47
|
name.to_s.gsub /_id$/, "-restful-url"
|
@@ -8,6 +8,7 @@ module Restful
|
|
8
8
|
class HashSerializer < Base
|
9
9
|
|
10
10
|
serializer_name :hash
|
11
|
+
|
11
12
|
|
12
13
|
def serialize(resource, options = {})
|
13
14
|
params = {}
|
@@ -15,31 +16,32 @@ module Restful
|
|
15
16
|
resource.values.each do |value|
|
16
17
|
if value.type == :collection # serialize the stuffs
|
17
18
|
resources = value.value
|
19
|
+
next if resources.empty?
|
18
20
|
name = resources.first.name.pluralize
|
19
21
|
|
20
22
|
array = []
|
21
|
-
resources.each
|
23
|
+
resources.each do |r|
|
24
|
+
array << serialize(r)
|
25
|
+
end
|
22
26
|
|
23
|
-
params[
|
27
|
+
params[hashify_key(value.name)] = array
|
24
28
|
elsif value.type == :link
|
25
|
-
params[value.name] = Restful::Rails.tools.dereference(value.value)
|
29
|
+
params[hashify_key(value.name)] = Restful::Rails.tools.dereference(value.value)
|
26
30
|
elsif value.type == :resource
|
27
|
-
params[
|
31
|
+
params[hashify_key(value.name)] = serialize(value)
|
28
32
|
else # plain ole
|
29
|
-
|
30
|
-
when :datetime
|
31
|
-
value.value.xmlschema
|
32
|
-
else
|
33
|
-
value.value
|
34
|
-
end
|
35
|
-
|
36
|
-
params[value.name] = string_value
|
33
|
+
params[hashify_key(value.name)] = formatted_value(value)
|
37
34
|
end
|
38
35
|
end
|
39
36
|
|
40
37
|
params["restful_url"] = resource.full_url
|
41
38
|
params
|
42
39
|
end
|
40
|
+
|
41
|
+
private
|
42
|
+
def hashify_key(original_key)
|
43
|
+
original_key.to_s.tr("-", "_").to_sym
|
44
|
+
end
|
43
45
|
end
|
44
46
|
end
|
45
47
|
end
|
@@ -12,10 +12,10 @@ module Restful
|
|
12
12
|
|
13
13
|
def serialize(resource, options = {})
|
14
14
|
params = {}
|
15
|
-
|
16
15
|
resource.values.each do |value|
|
17
16
|
if value.type == :collection # serialize the stuffs
|
18
17
|
resources = value.value
|
18
|
+
next if resources.empty?
|
19
19
|
name = resources.first.name.pluralize
|
20
20
|
|
21
21
|
array = []
|
@@ -23,18 +23,24 @@ module Restful
|
|
23
23
|
array << serialize(resource)
|
24
24
|
end
|
25
25
|
|
26
|
-
params["#{value.name
|
26
|
+
params["#{paramify_keys(value.name)}_attributes".to_sym] = array
|
27
27
|
elsif value.type == :link
|
28
|
-
params[value.name] = Restful::Rails.tools.dereference(value.value)
|
28
|
+
params[paramify_keys(value.name).to_sym] = Restful::Rails.tools.dereference(value.value)
|
29
29
|
elsif value.type == :resource
|
30
|
-
params["#{value.name
|
30
|
+
params["#{paramify_keys(value.name)}_attributes".to_sym] = serialize(value)
|
31
31
|
else # plain ole
|
32
|
-
params[value.name] = value.value
|
32
|
+
params[paramify_keys(value.name).to_sym] = value.value # no need to format dates etc - just pass objects through.
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
params
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def paramify_keys(original_key)
|
42
|
+
original_key.to_s.tr("-", "_")
|
43
|
+
end
|
44
|
+
end
|
39
45
|
end
|
40
46
|
end
|
@@ -58,18 +58,20 @@ module Restful
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def add_tag(builder, value)
|
61
|
-
|
62
|
-
|
63
|
-
value
|
61
|
+
|
62
|
+
if value.extended_type == :hash
|
63
|
+
build_hash(builder, value)
|
64
64
|
else
|
65
|
-
|
65
|
+
builder.tag!(value.name.to_s.dasherize, formatted_value(value), decorations(value))
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def build_hash(builder, value)
|
70
|
+
builder.tag!(value.name.to_s.dasherize) do
|
71
|
+
value.value.each do |k, v|
|
72
|
+
builder.tag! k.to_s.dasherize, v
|
73
|
+
end
|
66
74
|
end
|
67
|
-
|
68
|
-
builder.tag!(
|
69
|
-
value.name.to_s.dasherize,
|
70
|
-
string_value,
|
71
|
-
decorations(value)
|
72
|
-
)
|
73
75
|
end
|
74
76
|
|
75
77
|
def decorations(value)
|
@@ -91,6 +93,10 @@ module Restful
|
|
91
93
|
decorations[:nil] = true
|
92
94
|
end
|
93
95
|
|
96
|
+
if value.value.is_a?(FalseClass) || value.value.is_a?(TrueClass)
|
97
|
+
decorations[:type] = :boolean
|
98
|
+
end
|
99
|
+
|
94
100
|
decorations
|
95
101
|
end
|
96
102
|
|
data/restful.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = "restful"
|
3
|
-
s.version = "0.2.
|
3
|
+
s.version = "0.2.2"
|
4
4
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
5
5
|
s.authors = ["Daniel Bornkessel", "Rany Keddo"]
|
6
6
|
s.date = "2009-08-11"
|
@@ -8,7 +8,7 @@ context "active record converter" do
|
|
8
8
|
Person.restful_publish(:name, :wallet, :current_location, :pets => [:name, :species])
|
9
9
|
Pet.restful_publish(:person_id, :name) # person_id gets converted to a link automagically.
|
10
10
|
|
11
|
-
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree")
|
11
|
+
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree", :birthday => "1976-04-03")
|
12
12
|
@wallet = @person.wallet = Wallet.create!(:contents => "something in the wallet")
|
13
13
|
@pet = @person.pets.create(:name => "Mietze", :species => "cat")
|
14
14
|
end
|
@@ -17,6 +17,14 @@ context "active record converter" do
|
|
17
17
|
reset_config
|
18
18
|
end
|
19
19
|
|
20
|
+
specify "should be able to force expansion. force expanded attributes can never be collapsed. " do
|
21
|
+
Wallet.restful_publish(:contents)
|
22
|
+
Person.restful_publish(:name, :wallet, :current_location, { :pets => [:name, :species], :restful_options => { :force_expand => :wallet } })
|
23
|
+
Pet.restful_publish(:owner, :name)
|
24
|
+
|
25
|
+
@pet.to_restful
|
26
|
+
end
|
27
|
+
|
20
28
|
specify "should return link attributes from a model" do
|
21
29
|
@pet.to_restful.links.map { |node| node.name }.sort.should.equal [:person_id]
|
22
30
|
end
|
@@ -38,6 +46,11 @@ context "active record converter" do
|
|
38
46
|
restful.collections.map { |node| node.name }.sort.should.equal [:pets]
|
39
47
|
end
|
40
48
|
|
49
|
+
specify "should set correct type for date" do
|
50
|
+
restful = @person.to_restful :birthday
|
51
|
+
restful.simple_attributes.detect { |node| node.name == :birthday }.extended_type.should.== :date
|
52
|
+
end
|
53
|
+
|
41
54
|
specify "should be able to convert themselves to an apimodel containing all and only the attributes exposed by Model.publish_api" do
|
42
55
|
resource = @person.to_restful
|
43
56
|
|
@@ -13,5 +13,17 @@ class Person < ActiveRecord::Base
|
|
13
13
|
"Hi. I'm currently in #{ current_location }"
|
14
14
|
end
|
15
15
|
|
16
|
+
def has_pets
|
17
|
+
pets.size > 0
|
18
|
+
end
|
19
|
+
|
20
|
+
def pets_ages_hash
|
21
|
+
returning pets_hash = {} do
|
22
|
+
pets.each do |pet|
|
23
|
+
pets_hash[pet.name] = pet.age
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
16
28
|
apiable
|
17
29
|
end
|
@@ -13,4 +13,57 @@ bloggs:
|
|
13
13
|
"name": "mietze"
|
14
14
|
}],
|
15
15
|
"created_at": "<%= @person.created_at.xmlschema %>"
|
16
|
+
}
|
17
|
+
|
18
|
+
bloggs_with_oldest_pet:
|
19
|
+
|
|
20
|
+
{
|
21
|
+
"restful_url": "http://example.com:3000/people/<%= @person.to_param %>",
|
22
|
+
"oldest_pet": {
|
23
|
+
"restful_url": "http://example.com:3000/pets/<%= @person.pets.first.to_param %>",
|
24
|
+
"name": "mietze"
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
bloggs_with_birthday:
|
29
|
+
|
|
30
|
+
{
|
31
|
+
"restful_url": "http://example.com:3000/people/<%= @person.to_param %>",
|
32
|
+
"birthday": "<%= @person.birthday.to_s(:db) %>"
|
33
|
+
}
|
34
|
+
|
35
|
+
bloggs_with_pets_ages_hash:
|
36
|
+
|
|
37
|
+
{
|
38
|
+
"restful_url": "http://example.com:3000/people/<%= @person.to_param %>",
|
39
|
+
"pets_ages_hash": {
|
40
|
+
"mietze": 200,
|
41
|
+
"motze": 100
|
42
|
+
}
|
43
|
+
}
|
44
|
+
bloggs_with_has_pets:
|
45
|
+
|
|
46
|
+
{
|
47
|
+
"restful_url": "http://example.com:3000/people/<%= @person.to_param %>",
|
48
|
+
"has_pets": true
|
49
|
+
}
|
50
|
+
bloggs_with_hasno_pets:
|
51
|
+
|
|
52
|
+
{
|
53
|
+
"restful_url": "http://example.com:3000/people/<%= @person.to_param %>",
|
54
|
+
"has_pets": false
|
55
|
+
}
|
56
|
+
|
57
|
+
|
58
|
+
bloggs_da_pet_hater:
|
59
|
+
|
|
60
|
+
{
|
61
|
+
"restful_url": "http://example.com:3000/people/<%= @person.to_param %>",
|
62
|
+
"wallet": {
|
63
|
+
"restful_url": "http://example.com:3000/wallets/<%= @person.wallet.to_param %>",
|
64
|
+
"contents": "an old photo, 5 euros in coins"
|
65
|
+
},
|
66
|
+
"current_location": "Under a tree",
|
67
|
+
"name": "Joe Bloggs",
|
68
|
+
"created_at": "<%= @person.created_at.xmlschema %>"
|
16
69
|
}
|
@@ -37,7 +37,15 @@ with_oldest_pet_species:
|
|
37
37
|
<species type="integer"><%= @person.oldest_pet.species %></species>
|
38
38
|
</oldest-pet>
|
39
39
|
</person>
|
40
|
-
|
40
|
+
|
41
|
+
joe_with_birthday:
|
42
|
+
|
|
43
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
44
|
+
<person>
|
45
|
+
<restful-url type="link">http://example.com:3000/people/<%= @person.id %></restful-url>
|
46
|
+
<birthday type="date"><%= @person.birthday.to_s(:db) %></birthday>
|
47
|
+
</person>
|
48
|
+
|
41
49
|
joe_with_zwiebelleder:
|
42
50
|
|
|
43
51
|
<?xml version="1.0" encoding="UTF-8"?>
|
@@ -102,4 +110,14 @@ with_pets_and_expanded_wallet:
|
|
102
110
|
<contents>an old photo, 5 euros in coins</contents>
|
103
111
|
</wallet>
|
104
112
|
</person>
|
105
|
-
|
113
|
+
|
114
|
+
hashy_person:
|
115
|
+
|
|
116
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
117
|
+
<person>
|
118
|
+
<restful-url type="link">http://example.com:3000/people/<%= @person.id %></restful-url>
|
119
|
+
<pets-ages-hash>
|
120
|
+
<mietze>200</mietze>
|
121
|
+
<motze>100</motze>
|
122
|
+
</pets-ages-hash>
|
123
|
+
</person>
|
@@ -7,7 +7,7 @@ context "json serializer" do
|
|
7
7
|
Pet.restful_publish(:name)
|
8
8
|
Wallet.restful_publish(:contents)
|
9
9
|
|
10
|
-
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree")
|
10
|
+
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree", :birthday => "2009-09-19")
|
11
11
|
@pet = @person.pets.create(:species => "cat", :age => 200, :name => "mietze")
|
12
12
|
@wallet = @person.wallet = Wallet.new(:contents => "an old photo, 5 euros in coins")
|
13
13
|
@person.save
|
@@ -18,4 +18,46 @@ context "json serializer" do
|
|
18
18
|
specify "serialize to json" do
|
19
19
|
json_should_eql_fixture(@person.to_restful_json, "people", :bloggs)
|
20
20
|
end
|
21
|
+
|
22
|
+
specify "should be able to serialize objects with empty collections" do
|
23
|
+
@person.pets = []
|
24
|
+
assert_nothing_raised do
|
25
|
+
json_should_eql_fixture(@person.to_restful_json, "people", :bloggs_da_pet_hater)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
specify "should serialize date type correctly" do
|
30
|
+
json_should_eql_fixture(@person.to_restful_json(:birthday), "people", :bloggs_with_birthday)
|
31
|
+
end
|
32
|
+
|
33
|
+
specify "should not bug out on nil values in date fields" do
|
34
|
+
person = Person.create :created_at => nil, :birthday => nil, :last_login => nil
|
35
|
+
person.created_at = nil
|
36
|
+
expected = "{\"birthday\":null,\"restful_url\":\"http://example.com:3000/people/#{person.to_param}\",\"last_login\":null,\"created_at\":null}"
|
37
|
+
assert_nothing_raised do
|
38
|
+
actual = person.to_restful_json([:created_at, :birthday, :last_login])
|
39
|
+
json_should_eql(actual, expected)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
specify "should serialize hashes correctly" do
|
44
|
+
@person.pets.create(:species => "cat", :age => 100, :name => "motze")
|
45
|
+
json_should_eql_fixture(@person.to_restful_json(:pets_ages_hash), "people", :bloggs_with_pets_ages_hash)
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "should render boolean values correctly" do
|
49
|
+
json_should_eql_fixture(@person.to_restful_json(:has_pets), "people", :bloggs_with_has_pets)
|
50
|
+
@person.pets = []
|
51
|
+
@person.save!
|
52
|
+
json_should_eql_fixture(@person.to_restful_json(:has_pets), "people", :bloggs_with_hasno_pets)
|
53
|
+
end
|
54
|
+
|
55
|
+
specify "should not ever use dashes as hash keys but underscores" do
|
56
|
+
assert_nothing_raised do
|
57
|
+
json_should_eql_fixture(@person.to_restful_json(:oldest_pet), "people", :bloggs_with_oldest_pet)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
|
21
63
|
end
|
@@ -7,7 +7,7 @@ context "params serializer" do
|
|
7
7
|
Pet.restful_publish(:name)
|
8
8
|
Wallet.restful_publish(:contents)
|
9
9
|
|
10
|
-
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree")
|
10
|
+
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree", :birthday => "1942-01-11")
|
11
11
|
@pet = @person.pets.create(:species => "cat", :age => 200, :name => "mietze")
|
12
12
|
@wallet = @person.wallet = Wallet.new(:contents => "an old photo, 5 euros in coins")
|
13
13
|
@person.save
|
@@ -17,6 +17,30 @@ context "params serializer" do
|
|
17
17
|
reset_config
|
18
18
|
end
|
19
19
|
|
20
|
+
specify "should be able to serialize objects empty collections" do
|
21
|
+
@person.pets = []
|
22
|
+
expected =
|
23
|
+
{
|
24
|
+
:name => "Joe Bloggs",
|
25
|
+
:current_location => "Under a tree",
|
26
|
+
:created_at => @person.created_at,
|
27
|
+
:wallet_attributes=>{:contents=>"an old photo, 5 euros in coins"}
|
28
|
+
}
|
29
|
+
|
30
|
+
assert_nothing_raised do
|
31
|
+
actual = @person.to_restful.serialize :params
|
32
|
+
actual.should.== expected
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
specify "should render correct date" do
|
37
|
+
actual = @person.to_restful(:birthday).serialize(:params)
|
38
|
+
|
39
|
+
expected = { :birthday => @person.birthday.to_s(:db) }
|
40
|
+
|
41
|
+
Person.create(expected).birthday.should.== @person.birthday
|
42
|
+
end
|
43
|
+
|
20
44
|
specify "serialize to params" do
|
21
45
|
actual = @person.to_restful.serialize(:params)
|
22
46
|
|
@@ -32,6 +56,14 @@ context "params serializer" do
|
|
32
56
|
actual.should.== expected
|
33
57
|
end
|
34
58
|
|
59
|
+
specify "use correct key names for method that include '-' character" do
|
60
|
+
actual = @person.to_restful(:oldest_pet).serialize(:params)
|
61
|
+
|
62
|
+
expected = { :oldest_pet_attributes => {:name => "mietze"} }
|
63
|
+
|
64
|
+
actual.should.== expected
|
65
|
+
end
|
66
|
+
|
35
67
|
specify "serialize to an ar params hash" do
|
36
68
|
input = xml_fixture("pets")[:gracie]
|
37
69
|
params = Restful.from_xml(input).serialize(:params)
|
@@ -6,7 +6,7 @@ context "params serializer" do
|
|
6
6
|
Pet.restful_publish(:name)
|
7
7
|
Wallet.restful_publish(:contents)
|
8
8
|
|
9
|
-
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree")
|
9
|
+
@person = Person.create(:name => "Joe Bloggs", :current_location => "Under a tree", :birthday => "1990-03-09")
|
10
10
|
@pet = @person.pets.create(:species => "cat", :age => 200, :name => "mietze")
|
11
11
|
@wallet = @person.wallet = Wallet.new(:contents => "an old photo, 5 euros in coins")
|
12
12
|
@person.save
|
@@ -26,6 +26,10 @@ context "params serializer" do
|
|
26
26
|
xml_should_eql(expected, actual)
|
27
27
|
end
|
28
28
|
|
29
|
+
specify "should serialize date type correctly" do
|
30
|
+
xml_should_eql_fixture(@person.to_restful_xml(:birthday), "people", :joe_with_birthday)
|
31
|
+
end
|
32
|
+
|
29
33
|
specify "should convert a NULL inner association such as person.wallet to a link with a null value" do
|
30
34
|
@person.wallet = nil
|
31
35
|
|
@@ -35,4 +39,9 @@ context "params serializer" do
|
|
35
39
|
specify "serialize to xml, rails style" do
|
36
40
|
xml_should_eql_fixture(@person.to_restful_xml, "people", :with_pets_and_expanded_wallet)
|
37
41
|
end
|
42
|
+
|
43
|
+
specify "should serialize hashes correctly" do
|
44
|
+
@person.pets.create(:species => "cat", :age => 100, :name => "motze")
|
45
|
+
xml_should_eql_fixture(@person.to_restful_xml(:pets_ages_hash), "people", :hashy_person)
|
46
|
+
end
|
38
47
|
end
|
data/test/test_helper.rb
CHANGED
@@ -43,6 +43,8 @@ silence_stream(STDOUT) do
|
|
43
43
|
t.string :name
|
44
44
|
t.string :current_location
|
45
45
|
t.string :biography
|
46
|
+
t.date :birthday
|
47
|
+
t.datetime :last_login
|
46
48
|
|
47
49
|
t.timestamp :created_at
|
48
50
|
t.timestamp :updated_at
|
@@ -90,10 +92,25 @@ end
|
|
90
92
|
def json_cmp(actual, expected)
|
91
93
|
actual = Yajl::Parser.parse(actual)
|
92
94
|
expected = Yajl::Parser.parse(expected)
|
93
|
-
|
95
|
+
puts_hash_diff actual, expected
|
94
96
|
actual == expected
|
95
97
|
end
|
96
98
|
|
99
|
+
def puts_hash_diff(hash1, hash2, indent = 0)
|
100
|
+
return if hash1 == hash2
|
101
|
+
|
102
|
+
(hash1.keys + hash2.keys).uniq.each do |key|
|
103
|
+
next if hash1[key] == hash2[key]
|
104
|
+
print " "*indent
|
105
|
+
if hash1[key].is_a? Hash or hash2[key].is_a? Hash
|
106
|
+
puts "=== #{key} is a Hash ==="
|
107
|
+
puts_hash_diff(hash1[key] || {}, hash2[key] || {}, indent+2)
|
108
|
+
else
|
109
|
+
printf "%-#{20-indent}s %#{50-indent}s != %-50s\n", key[0..19], hash1[key], hash2[key]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
97
114
|
def xml_should_eql_fixture(actual, name, key)
|
98
115
|
expected = Hpricot(xml_fixture(name)[key])
|
99
116
|
actual = Hpricot(actual)
|