restfulie 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +10 -5
- data/Rakefile +5 -2
- data/lib/restfulie.rb +10 -5
- data/lib/restfulie/client.rb +13 -9
- data/lib/restfulie/client/base.rb +24 -65
- data/lib/restfulie/client/configuration.rb +62 -64
- data/lib/restfulie/client/entry_point.rb +36 -0
- data/lib/restfulie/client/ext/atom_ext.rb +12 -0
- data/lib/restfulie/client/ext/http_ext.rb +22 -0
- data/lib/restfulie/client/ext/json_ext.rb +12 -0
- data/lib/restfulie/client/ext/xml_ext.rb +4 -0
- data/lib/restfulie/client/http.rb +25 -13
- data/lib/restfulie/client/http/cache.rb +22 -22
- data/lib/restfulie/client/http/error.rb +70 -70
- data/lib/restfulie/client/http/link_request_builder.rb +15 -0
- data/lib/restfulie/client/http/request_adapter.rb +209 -0
- data/lib/restfulie/client/http/request_builder.rb +107 -0
- data/lib/restfulie/client/http/request_builder_executor.rb +24 -0
- data/lib/restfulie/client/http/request_executor.rb +17 -0
- data/lib/restfulie/client/http/request_follow.rb +42 -0
- data/lib/restfulie/client/http/request_follow_executor.rb +10 -0
- data/lib/restfulie/client/http/request_history.rb +69 -0
- data/lib/restfulie/client/http/request_history_executor.rb +10 -0
- data/lib/restfulie/client/http/request_marshaller.rb +127 -0
- data/lib/restfulie/client/http/request_marshaller_executor.rb +10 -0
- data/lib/restfulie/client/http/response.rb +23 -0
- data/lib/restfulie/client/http/response_handler.rb +67 -0
- data/lib/restfulie/client/http/response_holder.rb +9 -0
- data/lib/restfulie/client/mikyung.rb +17 -14
- data/lib/restfulie/client/mikyung/concatenator.rb +15 -12
- data/lib/restfulie/client/mikyung/core.rb +65 -39
- data/lib/restfulie/client/mikyung/languages.rb +8 -26
- data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
- data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
- data/lib/restfulie/client/mikyung/rest_process_model.rb +184 -107
- data/lib/restfulie/client/mikyung/steady_state_walker.rb +34 -28
- data/lib/restfulie/client/mikyung/then_condition.rb +33 -27
- data/lib/restfulie/client/mikyung/when_condition.rb +53 -49
- data/lib/restfulie/common.rb +7 -12
- data/lib/restfulie/common/converter.rb +20 -9
- data/lib/restfulie/common/converter/atom.rb +8 -83
- data/lib/restfulie/common/converter/atom/base.rb +89 -0
- data/lib/restfulie/common/converter/atom/builder.rb +101 -99
- data/lib/restfulie/common/converter/atom/helpers.rb +16 -8
- data/lib/restfulie/common/converter/json.rb +12 -0
- data/lib/restfulie/common/converter/json/base.rb +84 -0
- data/lib/restfulie/common/converter/json/builder.rb +102 -0
- data/lib/restfulie/common/converter/json/helpers.rb +17 -0
- data/lib/restfulie/common/converter/values.rb +30 -26
- data/lib/restfulie/common/converter/xml.rb +14 -0
- data/lib/restfulie/common/converter/xml/base.rb +61 -0
- data/lib/restfulie/common/converter/xml/builder.rb +112 -0
- data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
- data/lib/restfulie/common/converter/xml/link.rb +25 -0
- data/lib/restfulie/common/converter/xml/links.rb +25 -0
- data/lib/restfulie/common/core_ext.rb +1 -5
- data/lib/restfulie/common/core_ext/hash.rb +12 -0
- data/lib/restfulie/common/error.rb +19 -0
- data/lib/restfulie/common/logger.rb +17 -9
- data/lib/restfulie/common/representation.rb +9 -10
- data/lib/restfulie/common/representation/atom.rb +15 -47
- data/lib/restfulie/common/representation/atom/base.rb +122 -365
- data/lib/restfulie/common/representation/atom/category.rb +41 -0
- data/lib/restfulie/common/representation/atom/entry.rb +52 -100
- data/lib/restfulie/common/representation/atom/factory.rb +43 -0
- data/lib/restfulie/common/representation/atom/feed.rb +103 -99
- data/lib/restfulie/common/representation/atom/link.rb +68 -0
- data/lib/restfulie/common/representation/atom/person.rb +48 -0
- data/lib/restfulie/common/representation/atom/source.rb +59 -0
- data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
- data/lib/restfulie/common/representation/atom/xml.rb +95 -0
- data/lib/restfulie/common/representation/generic.rb +30 -29
- data/lib/restfulie/common/representation/json.rb +10 -22
- data/lib/restfulie/common/representation/json/base.rb +27 -0
- data/lib/restfulie/common/representation/json/keys_as_methods.rb +72 -0
- data/lib/restfulie/common/representation/json/link.rb +29 -0
- data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
- data/lib/restfulie/common/representation/xml.rb +18 -227
- data/lib/restfulie/server.rb +9 -10
- data/lib/restfulie/server/action_controller.rb +10 -12
- data/lib/restfulie/server/action_controller/base.rb +18 -15
- data/lib/restfulie/server/action_controller/{routing/patch.rb → patch.rb} +0 -0
- data/lib/restfulie/server/action_controller/restful_responder.rb +43 -35
- data/lib/restfulie/server/action_view.rb +8 -6
- data/lib/restfulie/server/action_view/helpers.rb +47 -41
- data/lib/restfulie/server/action_view/template_handlers.rb +24 -12
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +17 -12
- data/lib/restfulie/server/configuration.rb +22 -19
- data/lib/restfulie/server/{restfulie_controller.rb → controller.rb} +1 -10
- data/lib/restfulie/server/core_ext.rb +1 -1
- data/lib/restfulie/version.rb +14 -0
- metadata +52 -16
- data/lib/restfulie/client/http/adapter.rb +0 -502
- data/lib/restfulie/client/http/atom_ext.rb +0 -4
- data/lib/restfulie/client/http/core_ext.rb +0 -6
- data/lib/restfulie/client/http/core_ext/http.rb +0 -19
- data/lib/restfulie/client/http/marshal.rb +0 -145
- data/lib/restfulie/client/http/xml_ext.rb +0 -7
- data/lib/restfulie/common/core_ext/proc.rb +0 -48
- data/lib/restfulie/common/errors.rb +0 -15
- data/lib/restfulie/server/action_controller/routing.rb +0 -12
- data/lib/restfulie/server/action_controller/routing/restful_route.rb +0 -14
@@ -1,32 +1,38 @@
|
|
1
1
|
# A steady walker that tries 3 times each step
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
2
|
+
module Restfulie
|
3
|
+
module Client
|
4
|
+
module Mikyung
|
5
|
+
class SteadyStateWalker
|
6
|
+
def move(goal, current, mikyung)
|
7
|
+
step = goal.next_step(current, mikyung)
|
8
|
+
raise UnableToAchieveGoalError, "No step was found for #{current}" unless step
|
9
|
+
Common::Logger.logger.debug "Mikyung > next step will be #{step}"
|
10
|
+
step = step.new if step.kind_of? Class
|
11
|
+
try_to_execute(step, current, 3, mikyung)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def try_to_execute(step, current, max_attempts, mikyung)
|
17
|
+
raise "Unable to proceed when trying to #{step}" if max_attempts == 0
|
18
|
+
|
19
|
+
resource = step
|
20
|
+
raise "Step returned 'give up'" if resource.nil?
|
21
|
+
|
22
|
+
if step.respond_to?(:execute)
|
23
|
+
resource = step.execute(current, mikyung)
|
24
|
+
end
|
19
25
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
# TODO: should it really retry if it is not 200? Or only if it is on the 50x family?
|
27
|
+
# for instance the result could be a 302 redirection
|
28
|
+
unless resource.response.code == 200
|
29
|
+
try_to_execute(step, current, max_attempts-1, mikyung)
|
30
|
+
else
|
31
|
+
Common::Logger.logger.debug resource.response.body
|
32
|
+
resource
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
29
36
|
end
|
30
37
|
end
|
31
|
-
|
32
|
-
end
|
38
|
+
end
|
@@ -1,33 +1,39 @@
|
|
1
1
|
# A conclusion to a step.
|
2
2
|
#
|
3
3
|
# Whenever a step rule matches, there are a series of conditions to be executed.
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
4
|
+
module Restfulie
|
5
|
+
module Client
|
6
|
+
module Mikyung
|
7
|
+
class ThenCondition
|
8
|
+
attr_reader :description
|
9
|
+
|
10
|
+
# creates a new result, based on this description
|
11
|
+
def initialize(description)
|
12
|
+
@description = description
|
13
|
+
end
|
14
|
+
|
15
|
+
# finds the rule for this result and executes it
|
16
|
+
def execute(resource, goal, mikyung)
|
17
|
+
goal.then_rules.each do |rule|
|
18
|
+
if (matches = Regexp.new(rule[0]).match(@description))
|
19
|
+
return invoke_rule(rule[1], resource, matches, mikyung)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
def invoke_rule(rule, resource, matches, mikyung)
|
27
|
+
case rule.arity
|
28
|
+
when 1
|
29
|
+
rule.call(resource)
|
30
|
+
when 2
|
31
|
+
rule.call(resource, matches)
|
32
|
+
else
|
33
|
+
rule.call(resource, matches, mikyung)
|
34
|
+
end
|
35
|
+
end
|
18
36
|
end
|
19
37
|
end
|
20
|
-
nil
|
21
|
-
end
|
22
|
-
|
23
|
-
private
|
24
|
-
def invoke_rule(rule, resource, matches, mikyung)
|
25
|
-
if rule.arity==1
|
26
|
-
rule.call(resource)
|
27
|
-
elsif rule.arity==2
|
28
|
-
rule.call(resource, matches)
|
29
|
-
else
|
30
|
-
rule.call(resource, matches, mikyung)
|
31
|
-
end
|
32
38
|
end
|
33
|
-
end
|
39
|
+
end
|
@@ -1,53 +1,57 @@
|
|
1
1
|
# Checks whether one or more rule holds and is capable of executing results.
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
2
|
+
module Restfulie
|
3
|
+
module Client
|
4
|
+
module Mikyung
|
5
|
+
# Creates a conditional execution based on a description.
|
6
|
+
# Its rule is an array where its first element represents a rule name and second a lambda that returns true or false
|
7
|
+
# Its params are extra params that might be passed to the rule
|
8
|
+
# Example
|
9
|
+
# WhenCondition.new("when running", ["", lambda { |resource| resource.human.state=='running' }], "")
|
10
|
+
class WhenCondition
|
11
|
+
def initialize(description, rule, params)
|
12
|
+
@description = description
|
13
|
+
@results = []
|
14
|
+
@extra = []
|
15
|
+
@rule = rule
|
16
|
+
@params = params
|
17
|
+
end
|
18
|
+
|
19
|
+
# will execute the first attached result
|
20
|
+
def execute(resource, goal, mikyung)
|
21
|
+
@results.each do |result|
|
22
|
+
Restfulie::Common::Logger.logger.info("will '#{result.description}'")
|
23
|
+
return result.execute(resource, goal, mikyung)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# checks whether this step should execute for a specific resource
|
28
|
+
def should_run_for(resource, goal)
|
29
|
+
if @rule[1].arity == 2
|
30
|
+
rule_accepts = @rule[1].call(resource, @params)
|
31
|
+
else
|
32
|
+
rule_accepts = @rule[1].call(resource)
|
33
|
+
end
|
34
|
+
return false unless rule_accepts
|
35
|
+
!@extra.find do |condition|
|
36
|
+
!condition.should_run_for(resource, goal)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# adds an extra condition to this step
|
41
|
+
def and(condition)
|
42
|
+
@extra << condition
|
43
|
+
end
|
44
|
+
|
45
|
+
# adds an extra condition to this step
|
46
|
+
def but(condition)
|
47
|
+
@extra << condition
|
48
|
+
end
|
49
|
+
|
50
|
+
# adds an extra result to this step
|
51
|
+
def results_on(result)
|
52
|
+
@results << result
|
53
|
+
end
|
54
|
+
end
|
35
55
|
end
|
36
56
|
end
|
37
|
-
|
38
|
-
# adds an extra condition to this step
|
39
|
-
def and(condition)
|
40
|
-
@extra << condition
|
41
|
-
end
|
42
|
-
|
43
|
-
# adds an extra condition to this step
|
44
|
-
def but(condition)
|
45
|
-
@extra << condition
|
46
|
-
end
|
47
|
-
|
48
|
-
# adds an extra result to this step
|
49
|
-
def results_on(result)
|
50
|
-
@results << result
|
51
|
-
end
|
52
|
-
|
53
57
|
end
|
data/lib/restfulie/common.rb
CHANGED
@@ -4,19 +4,14 @@ require 'uri'
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'active_support'
|
6
6
|
require 'action_controller'
|
7
|
+
require 'restfulie/common/core_ext'
|
7
8
|
|
8
9
|
module Restfulie
|
9
|
-
module Common
|
10
|
+
module Common
|
11
|
+
autoload :Error, 'restfulie/common/error'
|
12
|
+
autoload :Logger, 'restfulie/common/logger'
|
13
|
+
autoload :Representation, 'restfulie/common/representation'
|
14
|
+
autoload :Converter, 'restfulie/common/converter'
|
15
|
+
end
|
10
16
|
end
|
11
17
|
|
12
|
-
%w(
|
13
|
-
errors
|
14
|
-
logger
|
15
|
-
core_ext
|
16
|
-
representation
|
17
|
-
converter
|
18
|
-
).each do |file|
|
19
|
-
require "restfulie/common/#{file}"
|
20
|
-
end
|
21
|
-
|
22
|
-
include ActiveSupport::CoreExtensions::Hash
|
@@ -1,11 +1,22 @@
|
|
1
|
-
|
2
|
-
module
|
1
|
+
module Restfulie
|
2
|
+
module Common
|
3
|
+
module Converter
|
4
|
+
autoload :Values, 'restfulie/common/converter/values'
|
5
|
+
autoload :Atom, 'restfulie/common/converter/atom'
|
6
|
+
autoload :Json, 'restfulie/common/converter/json'
|
7
|
+
autoload :Xml, 'restfulie/common/converter/xml'
|
3
8
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
).
|
10
|
-
|
9
|
+
# Returns the default root element name for an item or collection
|
10
|
+
def self.root_element_for(obj)
|
11
|
+
if obj.kind_of?(Hash) && obj.size==1
|
12
|
+
obj.keys.first.to_s
|
13
|
+
elsif obj.kind_of?(Array) && !obj.empty?
|
14
|
+
root_element_for(obj.first).to_s.underscore.pluralize
|
15
|
+
else
|
16
|
+
obj.class.to_s.underscore
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
11
21
|
end
|
22
|
+
|
@@ -1,87 +1,12 @@
|
|
1
|
-
module Restfulie
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
@@headers = {
|
10
|
-
:get => { 'Accept' => media_type_name },
|
11
|
-
:post => { 'Content-Type' => media_type_name }
|
12
|
-
}
|
13
|
-
|
14
|
-
mattr_reader :recipes
|
15
|
-
@@recipes = {}
|
16
|
-
|
17
|
-
class << self
|
18
|
-
|
19
|
-
def helper
|
20
|
-
Restfulie::Common::Converter::Atom::Helpers
|
1
|
+
module Restfulie
|
2
|
+
module Common
|
3
|
+
module Converter
|
4
|
+
module Atom
|
5
|
+
autoload :Base, 'restfulie/common/converter/atom/base'
|
6
|
+
autoload :Builder, 'restfulie/common/converter/atom/builder'
|
7
|
+
autoload :Helpers, 'restfulie/common/converter/atom/helpers'
|
8
|
+
extend Base::ClassMethods
|
21
9
|
end
|
22
|
-
|
23
|
-
def describe_recipe(recipe_name, options={}, &block)
|
24
|
-
raise 'Undefined recipe' unless block_given?
|
25
|
-
raise 'Undefined recipe_name' unless recipe_name
|
26
|
-
@@recipes[recipe_name] = block
|
27
|
-
end
|
28
|
-
|
29
|
-
def to_atom(obj = nil, options = {}, &block)
|
30
|
-
# just instantiate the string with the atom factory
|
31
|
-
return Restfulie::Common::Representation::Atom::Factory.create(obj) if obj.kind_of?(String)
|
32
|
-
|
33
|
-
if block_given?
|
34
|
-
recipe = block
|
35
|
-
elsif options[:recipe]
|
36
|
-
recipe = @@recipes[options[:recipe]]
|
37
|
-
else
|
38
|
-
return obj if obj.respond_to?(:atom_type) && (obj.atom_type == "feed" || obj.atom_type == "entry")
|
39
|
-
raise Restfulie::Common::Error::ConverterError.new("Recipe required")
|
40
|
-
end
|
41
|
-
|
42
|
-
# execute with the builder if a recipe is set (even if the obj is an atom)
|
43
|
-
options[:atom_type] ||= obj.respond_to?(:each) ? :feed : :entry
|
44
|
-
raise Restfulie::Common::Error::ConverterError.new("Undefined atom type #{options[:atom_type]}") unless [:entry,:feed].include?(options[:atom_type])
|
45
|
-
|
46
|
-
# Create representation and proxy
|
47
|
-
builder = Builder.new(options[:atom_type], obj)
|
48
|
-
|
49
|
-
# Check recipe arity size before calling it
|
50
|
-
recipe.call(*[builder, obj, options][0,recipe.arity])
|
51
|
-
|
52
|
-
builder.representation
|
53
|
-
end
|
54
|
-
|
55
|
-
alias_method :unmarshal, :to_atom
|
56
|
-
|
57
|
-
def to_hash(obj)
|
58
|
-
return obj if obj.kind_of?(Hash)
|
59
|
-
|
60
|
-
xml = nil
|
61
|
-
|
62
|
-
if obj.kind_of?(::String)
|
63
|
-
xml = obj
|
64
|
-
elsif obj.respond_to?(:to_xml)
|
65
|
-
xml = obj.to_xml
|
66
|
-
end
|
67
|
-
|
68
|
-
Hash.from_xml(xml).with_indifferent_access unless xml.nil?
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
def to_s(obj)
|
73
|
-
return obj if obj.kind_of?(String)
|
74
|
-
if obj.respond_to?(:to_xml)
|
75
|
-
obj.to_xml.to_s
|
76
|
-
else
|
77
|
-
obj.to_s
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
def marshal(obj, options = nil)
|
82
|
-
to_atom(obj, options).to_xml
|
83
|
-
end
|
84
|
-
|
85
10
|
end
|
86
11
|
end
|
87
12
|
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Common
|
3
|
+
module Converter
|
4
|
+
module Atom
|
5
|
+
module Base
|
6
|
+
module ClassMethods
|
7
|
+
mattr_reader :media_type_name
|
8
|
+
@@media_type_name = 'application/atom+xml'
|
9
|
+
|
10
|
+
mattr_reader :headers
|
11
|
+
@@headers = {
|
12
|
+
:get => { 'Accept' => media_type_name },
|
13
|
+
:post => { 'Content-Type' => media_type_name }
|
14
|
+
}
|
15
|
+
|
16
|
+
mattr_reader :recipes
|
17
|
+
@@recipes = {}
|
18
|
+
|
19
|
+
def helper
|
20
|
+
Restfulie::Common::Converter::Atom::Helpers
|
21
|
+
end
|
22
|
+
|
23
|
+
def describe_recipe(recipe_name, options={}, &block)
|
24
|
+
raise 'Undefined recipe' unless block_given?
|
25
|
+
raise 'Undefined recipe_name' unless recipe_name
|
26
|
+
@@recipes[recipe_name] = block
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_atom(obj = nil, options = {}, &block)
|
30
|
+
# just instantiate the string with the atom factory
|
31
|
+
return Restfulie::Common::Representation::Atom::Factory.create(obj) if obj.kind_of?(String)
|
32
|
+
|
33
|
+
if block_given?
|
34
|
+
recipe = block
|
35
|
+
elsif options[:recipe]
|
36
|
+
recipe = @@recipes[options[:recipe]]
|
37
|
+
else
|
38
|
+
return obj if obj.respond_to?(:atom_type) && (obj.atom_type == "feed" || obj.atom_type == "entry")
|
39
|
+
raise Restfulie::Common::Error::ConverterError.new("Recipe required")
|
40
|
+
end
|
41
|
+
|
42
|
+
# execute with the builder if a recipe is set (even if the obj is an atom)
|
43
|
+
options[:atom_type] ||= obj.respond_to?(:each) ? :feed : :entry
|
44
|
+
raise Restfulie::Common::Error::ConverterError.new("Undefined atom type #{options[:atom_type]}") unless [:entry,:feed].include?(options[:atom_type])
|
45
|
+
|
46
|
+
# Create representation and proxy
|
47
|
+
builder = Builder.new(options[:atom_type], obj)
|
48
|
+
|
49
|
+
# Check recipe arity size before calling it
|
50
|
+
recipe.call(*[builder, obj, options][0,recipe.arity])
|
51
|
+
|
52
|
+
builder.representation
|
53
|
+
end
|
54
|
+
|
55
|
+
alias_method :unmarshal, :to_atom
|
56
|
+
|
57
|
+
def to_hash(obj)
|
58
|
+
return obj if obj.kind_of?(Hash)
|
59
|
+
|
60
|
+
xml = nil
|
61
|
+
|
62
|
+
if obj.kind_of?(::String)
|
63
|
+
xml = obj
|
64
|
+
elsif obj.respond_to?(:to_xml)
|
65
|
+
xml = obj.to_xml
|
66
|
+
end
|
67
|
+
|
68
|
+
Hash.from_xml(xml).with_indifferent_access unless xml.nil?
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
def to_s(obj)
|
73
|
+
return obj if obj.kind_of?(String)
|
74
|
+
if obj.respond_to?(:to_xml)
|
75
|
+
obj.to_xml.to_s
|
76
|
+
else
|
77
|
+
obj.to_s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def marshal(obj, options = nil)
|
82
|
+
to_atom(obj, options).to_xml
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|