wrest 0.0.6-java → 0.0.7-java
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.rdoc +51 -19
- data/Rakefile +2 -3
- data/VERSION.yml +1 -1
- data/lib/wrest.rb +11 -2
- data/lib/wrest/components.rb +1 -2
- data/lib/wrest/components/attributes_container.rb +31 -69
- data/lib/wrest/components/attributes_container/typecaster.rb +121 -0
- data/lib/wrest/components/mutators.rb +18 -1
- data/lib/wrest/components/mutators/base.rb +52 -39
- data/lib/wrest/components/mutators/camel_to_snake_case.rb +7 -5
- data/lib/wrest/components/mutators/xml_mini_type_caster.rb +43 -0
- data/lib/wrest/components/mutators/xml_simple_type_caster.rb +22 -20
- data/lib/wrest/components/translators.rb +20 -17
- data/lib/wrest/components/translators/content_types.rb +2 -2
- data/lib/wrest/components/translators/json.rb +11 -8
- data/lib/wrest/components/translators/xml.rb +9 -12
- data/lib/wrest/core_ext/hash/conversions.rb +1 -1
- data/lib/wrest/resource/base.rb +25 -13
- data/lib/wrest/resource/state.rb +6 -0
- data/lib/wrest/response.rb +4 -0
- data/lib/wrest/uri.rb +5 -1
- data/lib/wrest/version.rb +1 -1
- data/spec/spec.opts +1 -1
- data/spec/spec_helper.rb +8 -1
- data/spec/wrest/components/attributes_container/typecaster_spec.rb +63 -0
- data/spec/wrest/components/attributes_container_spec.rb +6 -61
- data/spec/wrest/components/mutators/base_spec.rb +5 -1
- data/spec/wrest/components/mutators/xml_mini_type_caster_spec.rb +75 -0
- data/spec/wrest/components/mutators_spec.rb +21 -0
- data/spec/wrest/components/translators/xml_spec.rb +1 -1
- data/spec/wrest/components/translators_spec.rb +9 -0
- data/spec/wrest/uri_spec.rb +16 -4
- metadata +14 -15
- data/lib/wrest/components/typecast_helpers.rb +0 -41
data/README.rdoc
CHANGED
@@ -40,30 +40,56 @@ You can launch the interactive Wrest shell by running bin/wrest if you have the
|
|
40
40
|
)
|
41
41
|
=== Basic Http Calls
|
42
42
|
|
43
|
-
====
|
43
|
+
==== GET
|
44
44
|
|
45
|
-
A couple of ways to get the Yahoo news as hash map
|
45
|
+
A couple of ways to get the Yahoo news as hash map.
|
46
46
|
|
47
47
|
* This example simply does a get on a uri and figures out the appropriate deserialiser using the content-type (in this case 'text/javascript', which uses Wrest::Translators::Json). See content_types.rb under lib/wrest/mappers/translators.
|
48
48
|
"http://search.yahooapis.com/NewsSearchService/V1/newsSearch?appid=YahooDemo&output=json&query=India&results=3&start=1".to_uri.get.deserialise
|
49
49
|
|
50
50
|
* This example does a get on a base uri with several parameters passed to it, resulting in a uri essentially the same as the one above. It also shows how you can specify a custom deserialiser to produce a hash-map from the response, as well as a hash mutator to clean up the deserialised hash.
|
51
|
-
|
52
|
-
|
51
|
+
require 'rubygems'
|
52
|
+
require 'wrest'
|
53
|
+
include Wrest::Components
|
54
|
+
y "http://search.yahooapis.com/NewsSearchService/V1/newsSearch".to_uri.get(
|
55
|
+
:appid => 'YahooDemo',
|
56
|
+
:output => 'xml',
|
57
|
+
:query => 'India',
|
58
|
+
:results=> '3',
|
59
|
+
:start => '1'
|
60
|
+
).deserialise_using(
|
61
|
+
Translators::Xml
|
62
|
+
).mutate_using(
|
63
|
+
Mutators::XmlSimpleTypeCaster.new
|
64
|
+
)
|
65
|
+
|
66
|
+
==== OPTIONS
|
67
|
+
|
68
|
+
To find out what actions are permitted on a URI:
|
69
|
+
|
70
|
+
'http://www.yahoo.com'.to_uri.options.headers['allow']
|
71
|
+
|
72
|
+
|
73
|
+
=== Attributes Container
|
74
|
+
|
75
|
+
Allows any class to hold an attributes hash, somewhat like ActiveResource. It also supports several extensions to this base fuctionality such as support for typecasting attribute values.
|
76
|
+
|
77
|
+
Example:
|
78
|
+
|
79
|
+
class Demon
|
80
|
+
include Wrest::Components::AttributesContainer
|
81
|
+
include Wrest::Components::AttributesContainer::Typecaster
|
53
82
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
:query => 'India',
|
59
|
-
:results=> '3',
|
60
|
-
:start => '1'
|
61
|
-
).deserialise_using(
|
62
|
-
Translators::Xml
|
63
|
-
).mutate_using(
|
64
|
-
Mutators::XmlSimpleTypeCaster.new
|
65
|
-
)
|
83
|
+
always_has :id
|
84
|
+
typecast :age => as_integer,
|
85
|
+
:chi => lambda{|chi| Chi.new(chi)}
|
86
|
+
end
|
66
87
|
|
88
|
+
kai_wren = Demon.new('id => '1', 'age' => '1500', 'chi' => '1024', 'teacher' => 'Viss')
|
89
|
+
kai_wren.id # => '1'
|
90
|
+
kai_wren.age # => 1500
|
91
|
+
kai_wren.chi # => #<Chi:0x113af8c @count="1024">
|
92
|
+
kai_wren.teacher # => 'Viss'
|
67
93
|
|
68
94
|
=== Logging
|
69
95
|
|
@@ -80,9 +106,14 @@ Wrest RDocs can be found at http://wrest.rubyforge.org
|
|
80
106
|
|
81
107
|
== Wrest::Resource
|
82
108
|
|
83
|
-
Wrest::Resource is an alternative to ActiveResource. It targets Rails REST services and is currently under development.
|
109
|
+
Wrest::Resource is an alternative to ActiveResource. It targets Rails REST (well, POX - turns out Rails isn't really REST) services and is currently under development.
|
84
110
|
|
85
|
-
* No more pretending that REST resources are the same as database
|
111
|
+
* No more pretending that REST resources are the same as records in a database (yeah, no more freaking ActiveResource::Connection)
|
112
|
+
* Treat put as 'create or update,' not just 'update'
|
113
|
+
* Response codes result in user defined state transitions; favours state transitions based on response code over arbitrary ones
|
114
|
+
* Supports moving toward hypermedia links as opposed to client server collusion through URI templates
|
115
|
+
* The header is now exposed as metadata, rather being than something you have no control over
|
116
|
+
* Out of the box support for If-Unmodified-Since/If-Match+Etag
|
86
117
|
* Out of the box support for collections
|
87
118
|
* Out of the box support for collection pagination (including support for WillPaginate), both header based and xml attribute based
|
88
119
|
* Out of the box support for operations on all the records on the collection
|
@@ -92,14 +123,15 @@ Wrest::Resource is an alternative to ActiveResource. It targets Rails REST servi
|
|
92
123
|
* More natural mapping of deserialised entities to existing classes
|
93
124
|
* No communication via exceptions for http error status codes
|
94
125
|
* Better extensibility - allows access to request/response objects, avoids class variables, favours symbols over strings etc.
|
126
|
+
* Consider support for OPTIONS and response codes 100/417
|
95
127
|
|
96
128
|
== Dependencies
|
97
129
|
|
98
130
|
=== Source
|
99
131
|
* gems
|
100
|
-
* xmlsimple
|
101
132
|
* json (json-jruby on JRuby)
|
102
133
|
* active_support
|
134
|
+
* ruby-libxml (Recommended, will fall back to REXML if absent; be aware that Wrest uses ActiveSupport::XmlMini, so if you're using Wrest as a plugin in a Rails application, all xml parsing across the application will switch to using libxml if it's available. You're free to change this by hand by using the ActiveSupport::XmlMini.backend= method.)
|
103
135
|
|
104
136
|
=== Build
|
105
137
|
* rspec
|
data/Rakefile
CHANGED
@@ -67,12 +67,11 @@ begin
|
|
67
67
|
gemspec.homepage = "http://github.com/kaiwren/wrest"
|
68
68
|
gemspec.has_rdoc = true
|
69
69
|
gemspec.rubyforge_project = 'wrest'
|
70
|
-
gemspec.executables = ['wrest']
|
70
|
+
gemspec.executables = ['wrest', 'jwrest']
|
71
71
|
gemspec.require_path = "lib"
|
72
72
|
gemspec.files.exclude 'spec/wrest/meh_spec.rb'
|
73
73
|
gemspec.test_files.exclude 'spec/wrest/meh_spec.rb'
|
74
|
-
gemspec.add_dependency('activesupport', '>= 2.
|
75
|
-
gemspec.add_dependency('xml-simple', '>= 1.0.11')
|
74
|
+
gemspec.add_dependency('activesupport', '>= 2.3.2')
|
76
75
|
case RUBY_PLATFORM
|
77
76
|
when /java/
|
78
77
|
gemspec.add_dependency('json-jruby', '>= 1.1.3')
|
data/VERSION.yml
CHANGED
data/lib/wrest.rb
CHANGED
@@ -7,6 +7,8 @@
|
|
7
7
|
# See the License for the specific language governing permissions and limitations under the License.
|
8
8
|
|
9
9
|
require 'rubygems'
|
10
|
+
gem 'activesupport', '>= 2.3.2'
|
11
|
+
|
10
12
|
require 'net/http'
|
11
13
|
require 'net/https'
|
12
14
|
require 'forwardable'
|
@@ -19,7 +21,7 @@ require 'active_support'
|
|
19
21
|
|
20
22
|
WREST_ROOT = File.dirname(__FILE__)
|
21
23
|
|
22
|
-
module Wrest
|
24
|
+
module Wrest #:nodoc:
|
23
25
|
def self.logger=(logger)
|
24
26
|
@logger = logger
|
25
27
|
end
|
@@ -29,9 +31,16 @@ module Wrest
|
|
29
31
|
end
|
30
32
|
end
|
31
33
|
|
32
|
-
Wrest.logger =
|
34
|
+
Wrest.logger = ActiveSupport::BufferedLogger.new(STDOUT)
|
33
35
|
Wrest.logger.level = Logger::DEBUG
|
34
36
|
|
37
|
+
begin
|
38
|
+
gem 'libxml-ruby', '>= 1.1.3'
|
39
|
+
ActiveSupport::XmlMini.backend='LibXML'
|
40
|
+
rescue Gem::LoadError
|
41
|
+
Wrest.logger.warn "LibXML >= 1.1.3 not found, falling back to #{ActiveSupport::XmlMini.backend}. To install LibXML run `sudo gem install ruby-libxml`"
|
42
|
+
end
|
43
|
+
|
35
44
|
source_dirs = ["/wrest/core_ext/*.rb", "/wrest/*.rb"]
|
36
45
|
|
37
46
|
source_dirs.each{|directory|
|
data/lib/wrest/components.rb
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest
|
10
|
+
module Wrest
|
11
11
|
# A component is a building block that can
|
12
12
|
# be used while building an object oriented wrapper
|
13
13
|
# around a REST service
|
@@ -15,7 +15,6 @@ module Wrest #:nodoc:
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
require "#{WREST_ROOT}/wrest/components/typecast_helpers"
|
19
18
|
require "#{WREST_ROOT}/wrest/components/attributes_container"
|
20
19
|
require "#{WREST_ROOT}/wrest/components/mutators"
|
21
20
|
require "#{WREST_ROOT}/wrest/components/translators"
|
@@ -7,16 +7,23 @@
|
|
7
7
|
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
8
|
# See the License for the specific language governing permissions and limitations under the License.
|
9
9
|
|
10
|
-
module Wrest
|
10
|
+
module Wrest
|
11
|
+
module Components::AttributesContainer
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
require "#{WREST_ROOT}/wrest/components/attributes_container/typecaster"
|
16
|
+
|
17
|
+
module Wrest::Components
|
11
18
|
|
12
19
|
# Adds behaviour allowing a class to
|
13
20
|
# contain attributes and providing support
|
14
21
|
# for dynamic getters, setters and query methods.
|
15
22
|
# These methods are added at runtime, on the first
|
16
|
-
# invocation and on a per instance basis.
|
17
|
-
# <tt>respond_to?</tt> however will respond as though
|
23
|
+
# invocation and on a per instance basis.
|
24
|
+
# <tt>respond_to?</tt> however will respond as though
|
18
25
|
# they are all already present.
|
19
|
-
# This means that two different instances of the same
|
26
|
+
# This means that two different instances of the same
|
20
27
|
# AttributesContainer could well have
|
21
28
|
# different attribute getters/setters/query methods.
|
22
29
|
#
|
@@ -30,99 +37,60 @@ module Wrest::Components #:nodoc:
|
|
30
37
|
# In situations where this is a problem, such as a client consuming Rails
|
31
38
|
# REST services where <tt>id</tt> is a common attribute and clashes with
|
32
39
|
# Object#id, it is recommended to create getter/setter/query methods
|
33
|
-
# on the class (which affects all instances) using the +
|
40
|
+
# on the class (which affects all instances) using the +always_has+ macro.
|
34
41
|
#
|
35
42
|
# If you're implementing your own initialize method
|
36
|
-
# remember to delegate to the default initialize
|
43
|
+
# remember to delegate to the default initialize
|
37
44
|
# of AttributesContainer by invoking <tt>super(attributes)</tt>
|
38
45
|
#
|
39
46
|
# Example:
|
40
47
|
# class ShenCoin
|
41
48
|
# include Wrest::Components::AttributesContainer
|
49
|
+
# include Wrest::Components::AttributesContainer::Typecaster
|
42
50
|
#
|
43
|
-
#
|
44
|
-
# typecast
|
45
|
-
# end
|
51
|
+
# always_has :id
|
52
|
+
# typecast :id => as_integer
|
53
|
+
# end
|
46
54
|
# coin = ShenCoin.new(:id => '5', :chi_count => 500, :owner => 'Kai Wren')
|
47
55
|
# coin.id # => 5
|
48
56
|
# coin.owner # => 'Kai Wren'
|
49
57
|
module AttributesContainer
|
50
58
|
def self.included(klass) #:nodoc:
|
51
59
|
klass.extend AttributesContainer::ClassMethods
|
52
|
-
klass.extend TypecastHelpers
|
53
60
|
klass.class_eval{ include AttributesContainer::InstanceMethods }
|
54
61
|
end
|
55
|
-
|
62
|
+
|
56
63
|
def self.build_attribute_getter(attribute_name) #:nodoc:
|
57
64
|
"def #{attribute_name};@attributes[:#{attribute_name}];end;"
|
58
65
|
end
|
59
|
-
|
66
|
+
|
60
67
|
def self.build_attribute_setter(attribute_name) #:nodoc:
|
61
68
|
"def #{attribute_name}=(value);@attributes[:#{attribute_name}] = value;end;"
|
62
69
|
end
|
63
|
-
|
70
|
+
|
64
71
|
def self.build_attribute_queryer(attribute_name) #:nodoc:
|
65
72
|
"def #{attribute_name}?;not @attributes[:#{attribute_name}].nil?;end;"
|
66
73
|
end
|
67
|
-
|
74
|
+
|
68
75
|
module ClassMethods
|
69
76
|
# This macro explicitly creates getter, setter and query methods on
|
70
|
-
# a class, overriding any exisiting methods with the same names.
|
77
|
+
# a class, overriding any exisiting methods with the same names.
|
71
78
|
# This can be used when attribute names clash with method names;
|
72
79
|
# an example would be Rails REST services which frequently make use
|
73
80
|
# an attribute named <tt>id</tt> which clashes with Object#id. Also,
|
74
81
|
# this can be used as a performance optimisation if the incoming
|
75
82
|
# attributes are known beforehand.
|
76
|
-
def
|
83
|
+
def always_has(*attribute_names)
|
77
84
|
attribute_names.each do |attribute_name|
|
78
85
|
self.class_eval(
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
)
|
86
|
+
AttributesContainer.build_attribute_getter(attribute_name) +
|
87
|
+
AttributesContainer.build_attribute_setter(attribute_name) +
|
88
|
+
AttributesContainer.build_attribute_queryer(attribute_name)
|
89
|
+
)
|
83
90
|
end
|
84
91
|
end
|
85
|
-
|
86
|
-
# Accepts a set of attribute-name/lambda pairs which are used
|
87
|
-
# to typecast string values injected through the constructor.
|
88
|
-
# Typically needed when populating an +AttributesContainer+
|
89
|
-
# directly from request params. Typecasting kicks in for
|
90
|
-
# a given value _only_ if it is a string.
|
91
|
-
#
|
92
|
-
# Typcast information is inherited by subclasses; however be
|
93
|
-
# aware that explicitly invoking +typecast+ in a subclass will
|
94
|
-
# discard inherited typecast information leaving only the casts
|
95
|
-
# defined in the subclass.
|
96
|
-
#
|
97
|
-
# Common typecasts such as integer, float, datetime etc. are
|
98
|
-
# available through predefined helpers. See TypecastHelpers
|
99
|
-
# for a full list.
|
100
|
-
#
|
101
|
-
# Example:
|
102
|
-
#
|
103
|
-
# class Demon
|
104
|
-
# include Wrest::Components::AttributesContainer
|
105
|
-
# typecast :age => as_integer,
|
106
|
-
# :chi => lambda{|chi| Chi.new(chi)}
|
107
|
-
# end
|
108
|
-
# kai_wren = Demon.new('age' => '1500', 'chi' => '1024')
|
109
|
-
# kai_wren.age # => 1500
|
110
|
-
# kai_wren.chi # => #<Chi:0x113af8c @count="1024">
|
111
|
-
def typecast(cast_map)
|
112
|
-
@typecast_map = @typecast_map ? @typecast_map.merge(cast_map.symbolize_keys) : cast_map.symbolize_keys
|
113
|
-
end
|
114
|
-
|
115
|
-
def typecast_map #:nodoc:
|
116
|
-
if defined?(@typecast_map)
|
117
|
-
@typecast_map
|
118
|
-
elsif superclass != Object && superclass.respond_to?(:typecast_map)
|
119
|
-
superclass.typecast_map
|
120
|
-
else
|
121
|
-
{}
|
122
|
-
end
|
123
|
-
end
|
124
92
|
end
|
125
|
-
|
93
|
+
|
126
94
|
module InstanceMethods
|
127
95
|
# Sets up any class to act like
|
128
96
|
# an attributes container by creating
|
@@ -132,22 +100,18 @@ module Wrest::Components #:nodoc:
|
|
132
100
|
# own class.
|
133
101
|
def initialize(attributes = {})
|
134
102
|
@attributes = attributes.symbolize_keys
|
135
|
-
self.class.typecast_map.each do |key, typecaster|
|
136
|
-
value = @attributes[key]
|
137
|
-
@attributes[key] = typecaster.call(value) if value.is_a?(String)
|
138
|
-
end
|
139
103
|
@interface = Module.new
|
140
104
|
self.extend @interface
|
141
105
|
end
|
142
|
-
|
106
|
+
|
143
107
|
def [](key)
|
144
108
|
@attributes[key.to_sym]
|
145
109
|
end
|
146
|
-
|
110
|
+
|
147
111
|
def []=(key, value)
|
148
112
|
@attributes[key.to_sym] = value
|
149
113
|
end
|
150
|
-
|
114
|
+
|
151
115
|
def respond_to?(method_name, include_private = false)
|
152
116
|
super(method_name, include_private) ? true : @attributes.include?(method_name.to_s.gsub(/(\?$)|(=$)/, '').to_sym)
|
153
117
|
end
|
@@ -157,7 +121,6 @@ module Wrest::Components #:nodoc:
|
|
157
121
|
def method_missing(method_sym, *arguments)
|
158
122
|
method_name = method_sym.to_s
|
159
123
|
attribute_name = method_name.gsub(/(\?$)|(=$)/, '')
|
160
|
-
|
161
124
|
if @attributes.include?(attribute_name.to_sym) || method_name.last == '='
|
162
125
|
case method_name.last
|
163
126
|
when '='
|
@@ -172,7 +135,6 @@ module Wrest::Components #:nodoc:
|
|
172
135
|
super(method_sym, *arguments)
|
173
136
|
end
|
174
137
|
end
|
175
|
-
|
176
138
|
end
|
177
139
|
end
|
178
140
|
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
# Copyright 2009 Sidu Ponnappa
|
2
|
+
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
|
6
|
+
# Unless required by applicable law or agreed to in writing, software distributed under the License
|
7
|
+
# is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
8
|
+
# See the License for the specific language governing permissions and limitations under the License.
|
9
|
+
|
10
|
+
module Wrest
|
11
|
+
module Components::AttributesContainer
|
12
|
+
# An extension to AttributesContainer that adds support for
|
13
|
+
# specifying how the values associated with certain attribute keys
|
14
|
+
# should be typecast.
|
15
|
+
#
|
16
|
+
# This extension can be used in situations where the attributes
|
17
|
+
# hash consists of just strings with no associated tup information.
|
18
|
+
# For example, params recieved from a web browser may contain
|
19
|
+
# attributes like
|
20
|
+
# 'id' => '4', 'dateofbirth' => '1984-04-05'
|
21
|
+
# and we'd like to have these cast to an integer and a date
|
22
|
+
# respectively, rather than have to deal with them as strings.
|
23
|
+
module Typecaster
|
24
|
+
def self.included(klass) #:nodoc:
|
25
|
+
klass.extend Typecaster::ClassMethods
|
26
|
+
klass.class_eval{ include Typecaster::InstanceMethods }
|
27
|
+
klass.alias_method_chain :initialize, :typecasting
|
28
|
+
end
|
29
|
+
|
30
|
+
module ClassMethods
|
31
|
+
# Accepts a set of attribute-name/lambda pairs which are used
|
32
|
+
# to typecast string values injected through the constructor.
|
33
|
+
# Typically needed when populating an +AttributesContainer+
|
34
|
+
# directly from request params. Typecasting kicks in for
|
35
|
+
# a given value _only_ if it is a string.
|
36
|
+
#
|
37
|
+
# Typecast information is inherited by subclasses; however be
|
38
|
+
# aware that explicitly invoking +typecast+ in a subclass will
|
39
|
+
# discard inherited typecast information leaving only the casts
|
40
|
+
# defined in the subclass.
|
41
|
+
#
|
42
|
+
# Common typecasts such as integer, float, datetime etc. are
|
43
|
+
# available through predefined helpers. See TypecastHelpers
|
44
|
+
# for a full list.
|
45
|
+
#
|
46
|
+
# Example:
|
47
|
+
#
|
48
|
+
# class Demon
|
49
|
+
# include Wrest::Components::AttributesContainer
|
50
|
+
# include Wrest::Components::AttributesContainer::Typecaster
|
51
|
+
#
|
52
|
+
# typecast :age => as_integer,
|
53
|
+
# :chi => lambda{|chi| Chi.new(chi)}
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# kai_wren = Demon.new('age' => '1500', 'chi' => '1024')
|
57
|
+
# kai_wren.age # => 1500
|
58
|
+
# kai_wren.chi # => #<Chi:0x113af8c @count="1024">
|
59
|
+
def typecast(cast_map)
|
60
|
+
@typecast_map = @typecast_map ? @typecast_map.merge(cast_map.symbolize_keys) : cast_map.symbolize_keys
|
61
|
+
end
|
62
|
+
|
63
|
+
def typecast_map #:nodoc:
|
64
|
+
if defined?(@typecast_map)
|
65
|
+
@typecast_map
|
66
|
+
elsif superclass != Object && superclass.respond_to?(:typecast_map)
|
67
|
+
superclass.typecast_map
|
68
|
+
else
|
69
|
+
{}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def as_base64Binary
|
74
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['base64Binary']
|
75
|
+
end
|
76
|
+
|
77
|
+
def as_boolean
|
78
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['boolean']
|
79
|
+
end
|
80
|
+
|
81
|
+
def as_decimal
|
82
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['decimal']
|
83
|
+
end
|
84
|
+
|
85
|
+
def as_date
|
86
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['date']
|
87
|
+
end
|
88
|
+
|
89
|
+
def as_datetime
|
90
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['datetime']
|
91
|
+
end
|
92
|
+
|
93
|
+
def as_float
|
94
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['float']
|
95
|
+
end
|
96
|
+
|
97
|
+
def as_integer
|
98
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['integer']
|
99
|
+
end
|
100
|
+
|
101
|
+
def as_symbol
|
102
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['symbol']
|
103
|
+
end
|
104
|
+
|
105
|
+
def as_yaml
|
106
|
+
ActiveSupport::CoreExtensions::Hash::Conversions::XML_PARSING['yaml']
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
module InstanceMethods # :nodoc:
|
111
|
+
def initialize_with_typecasting(attributes = {}) # :nodoc:
|
112
|
+
initialize_without_typecasting(attributes)
|
113
|
+
self.class.typecast_map.each do |key, typecaster|
|
114
|
+
value = @attributes[key]
|
115
|
+
@attributes[key] = typecaster.call(value) if value.is_a?(String)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|