zeng 0.0.1 → 0.0.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.md +67 -0
- data/Rakefile +21 -19
- data/book.rb +23 -0
- data/{init.rb → lib/zeng.rb} +5 -1
- data/lib/{cute_kv → zeng}/adapters/tokyo_cabinet.rb +7 -6
- data/lib/zeng/adapters/tokyo_tyrant.rb +30 -0
- data/lib/zeng/connector.rb +28 -0
- data/lib/{cute_kv → zeng}/document.rb +7 -12
- data/lib/{cute_kv → zeng}/indexer.rb +2 -2
- data/spec/case/document_test.rb +174 -174
- data/spec/case/indexer_test.rb +31 -31
- data/spec/helper.rb +12 -14
- data/spec/model/Account.rb +3 -3
- data/spec/model/Book.rb +2 -2
- data/spec/model/Friend.rb +3 -3
- data/spec/model/Icon.rb +3 -3
- data/spec/model/Project.rb +2 -2
- data/spec/model/User.rb +3 -4
- metadata +26 -49
- data/README.rdoc +0 -89
- data/lib/cute_kv/adapters/light_cloud.rb +0 -22
- data/lib/cute_kv/adapters/tokyo_tyrant.rb +0 -22
- data/lib/cute_kv/associations.rb +0 -285
- data/lib/cute_kv/connector.rb +0 -27
- data/lib/cute_kv/ext/string.rb +0 -34
- data/lib/cute_kv/ext/symbol.rb +0 -9
- data/lib/cute_kv/serialization.rb +0 -95
- data/lib/cute_kv/serializers/json_serializer.rb +0 -75
- data/lib/cute_kv/serializers/xml_serializer.rb +0 -325
- data/lib/cute_kv/timestamp.rb +0 -56
- data/lib/cute_kv/validations.rb +0 -68
- data/lib/cutekv.rb +0 -17
- data/spec/asso.yml +0 -23
- data/spec/asso_sin_plural.yml +0 -36
- data/spec/case/associations_test.rb +0 -313
- data/spec/case/document_docking_test.rb +0 -103
- data/spec/case/serialization_test.rb +0 -78
- data/spec/case/sin_plu_dic_test.rb +0 -29
- data/spec/case/symmetry_test.rb +0 -80
- data/spec/case/timestamp_test.rb +0 -65
- data/spec/case/validations_test.rb +0 -74
- data/spec/light_cloud.yml +0 -9
- data/spec/model/Topic.rb +0 -26
- data/tags +0 -322
data/lib/cute_kv/connector.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
module CuteKV
|
2
|
-
class Connector
|
3
|
-
def self.config(adapter)
|
4
|
-
case adapter.to_sym
|
5
|
-
when :TC
|
6
|
-
require 'cute_kv/adapters/tokyo_cabinet'
|
7
|
-
include CuteKV::Adapters::TokyoCabinet
|
8
|
-
when :TT
|
9
|
-
require 'cute_kv/adapters/tokyo_tyrant'
|
10
|
-
include CuteKV::Adapters::TokyoTyrant
|
11
|
-
when :LC
|
12
|
-
require 'cute_kv/adapters/light_cloud'
|
13
|
-
include CuteKV::Adapters::TokyoCloud
|
14
|
-
else
|
15
|
-
raise ConfigError,'没有指定数据库类型!'
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def initialize(adapter, conf)
|
20
|
-
@adapter = adapter
|
21
|
-
self.class.config(adapter)
|
22
|
-
establish(conf)
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
data/lib/cute_kv/ext/string.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
class String
|
2
|
-
|
3
|
-
def plural?
|
4
|
-
(Dic::PLU_WORDS.include?(self) || self.pluralize == self) && !Dic::SIN_WORDS.include?(self)
|
5
|
-
end
|
6
|
-
|
7
|
-
def singular?
|
8
|
-
(Dic::SIN_WORDS.include?(self) || self.singularize == self) && !Dic::PLU_WORDS.include?(self)
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
module WordAct
|
14
|
-
def add(words)
|
15
|
-
if words.is_a? Array
|
16
|
-
words.each {|w| self.add(w.to_s)}
|
17
|
-
else
|
18
|
-
self << words.to_s
|
19
|
-
Dic::Mirror[self].delete(words.to_s)
|
20
|
-
self.uniq!
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def hash
|
25
|
-
self.object_id
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
module Dic
|
30
|
-
(SIN_WORDS = []).extend(WordAct)
|
31
|
-
(PLU_WORDS = []).extend(WordAct)
|
32
|
-
Mirror = {SIN_WORDS=>PLU_WORDS, PLU_WORDS=>SIN_WORDS}
|
33
|
-
end
|
34
|
-
|
data/lib/cute_kv/ext/symbol.rb
DELETED
@@ -1,95 +0,0 @@
|
|
1
|
-
module CuteKV#:nodoc:
|
2
|
-
module Serialization
|
3
|
-
class Serializer #:nodoc:
|
4
|
-
attr_reader :options
|
5
|
-
|
6
|
-
def initialize(object, options = {})
|
7
|
-
@object, @options = object, options.dup
|
8
|
-
end
|
9
|
-
|
10
|
-
# To replicate the behavior in ActiveObject#attributes,
|
11
|
-
# <tt>:except</tt> takes precedence over <tt>:only</tt>. If <tt>:only</tt> is not set
|
12
|
-
# for a N level model but is set for the N+1 level models,
|
13
|
-
# then because <tt>:except</tt> is set to a default value, the second
|
14
|
-
# level model can have both <tt>:except</tt> and <tt>:only</tt> set. So if
|
15
|
-
# <tt>:only</tt> is set, always delete <tt>:except</tt>.
|
16
|
-
def serializable_attribute_names
|
17
|
-
attribute_names = @object.assigned_attributes.collect {|n| n.to_s} << "id"
|
18
|
-
|
19
|
-
if options[:only]
|
20
|
-
options.delete(:except)
|
21
|
-
attribute_names = attribute_names & Array(options[:only]).collect { |n| n.to_s }
|
22
|
-
else
|
23
|
-
options[:except] = Array(options[:except])
|
24
|
-
attribute_names = attribute_names - options[:except].collect { |n| n.to_s }
|
25
|
-
end
|
26
|
-
|
27
|
-
attribute_names
|
28
|
-
end
|
29
|
-
|
30
|
-
def serializable_method_names
|
31
|
-
Array(options[:methods]).inject([]) do |method_attributes, name|
|
32
|
-
method_attributes << name if @object.respond_to?(name.to_s)
|
33
|
-
method_attributes
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def serializable_names
|
38
|
-
serializable_attribute_names + serializable_method_names
|
39
|
-
end
|
40
|
-
|
41
|
-
# Add associations specified via the <tt>:includes</tt> option.
|
42
|
-
# Expects a block that takes as arguments:
|
43
|
-
# +association+ - name of the association
|
44
|
-
# +objects+ - the association object(s) to be serialized
|
45
|
-
# +opts+ - options for the association objects
|
46
|
-
def add_includes(&block)
|
47
|
-
if include_associations = options.delete(:include)
|
48
|
-
base_only_or_except = { :except => options[:except],
|
49
|
-
:only => options[:only] }
|
50
|
-
|
51
|
-
include_has_options = include_associations.is_a?(Hash)
|
52
|
-
associations = include_has_options ? include_associations.keys : Array(include_associations)
|
53
|
-
|
54
|
-
for association in associations
|
55
|
-
objects = @object.send association
|
56
|
-
|
57
|
-
unless objects.nil?
|
58
|
-
association_options = include_has_options ? include_associations[association] : base_only_or_except
|
59
|
-
opts = options.merge(association_options)
|
60
|
-
yield(association, objects, opts)
|
61
|
-
end
|
62
|
-
end
|
63
|
-
|
64
|
-
options[:include] = include_associations
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
def serializable_object
|
69
|
-
returning(serializable_object = {}) do
|
70
|
-
serializable_names.each { |name| serializable_object[name] = @object.send(name) }
|
71
|
-
|
72
|
-
add_includes do |association, objects, opts|
|
73
|
-
if objects.is_a?(Enumerable)
|
74
|
-
serializable_object[association] = objects.collect { |r| self.class.new(r, opts).serializable_object }
|
75
|
-
else
|
76
|
-
serializable_object[association] = self.class.new(objects, opts).serializable_object
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def serialize
|
84
|
-
# overwrite to implement
|
85
|
-
end
|
86
|
-
|
87
|
-
def to_s(&block)
|
88
|
-
serialize(&block)
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
require 'cute_kv/serializers/xml_serializer'
|
95
|
-
require 'cute_kv/serializers/json_serializer'
|
@@ -1,75 +0,0 @@
|
|
1
|
-
module CuteKV#:nodoc:
|
2
|
-
module Serialization
|
3
|
-
def self.included(base)
|
4
|
-
base.cattr_accessor :include_root_in_json, :instance_writer => false
|
5
|
-
base.extend ClassMethods
|
6
|
-
end
|
7
|
-
|
8
|
-
# Returns a JSON string representing the model. Some configuration is
|
9
|
-
# available through +options+.
|
10
|
-
#
|
11
|
-
# Without any +options+, the returned JSON string will include all
|
12
|
-
# the model's attributes. For example:
|
13
|
-
#
|
14
|
-
# konata = User.find(1)
|
15
|
-
# konata.to_json
|
16
|
-
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
17
|
-
# "created_at": "2006/08/01", "awesome": true}
|
18
|
-
#
|
19
|
-
# The <tt>:only</tt> and <tt>:except</tt> options can be used to limit the attributes
|
20
|
-
# included, and work similar to the +attributes+ method. For example:
|
21
|
-
#
|
22
|
-
# konata.to_json(:only => [ :id, :name ])
|
23
|
-
# # => {"id": 1, "name": "Konata Izumi"}
|
24
|
-
#
|
25
|
-
# konata.to_json(:except => [ :id, :created_at, :age ])
|
26
|
-
# # => {"name": "Konata Izumi", "awesome": true}
|
27
|
-
#
|
28
|
-
# To include any methods on the model, use <tt>:methods</tt>.
|
29
|
-
#
|
30
|
-
# konata.to_json(:methods => :permalink)
|
31
|
-
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
32
|
-
# "created_at": "2006/08/01", "awesome": true,
|
33
|
-
# "permalink": "1-konata-izumi"}
|
34
|
-
#
|
35
|
-
# To include associations, use <tt>:include</tt>.
|
36
|
-
#
|
37
|
-
# konata.to_json(:include => :posts)
|
38
|
-
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
39
|
-
# "created_at": "2006/08/01", "awesome": true,
|
40
|
-
# "posts": [{"id": 1, "author_id": 1, "title": "Welcome to the weblog"},
|
41
|
-
# {"id": 2, author_id: 1, "title": "So I was thinking"}]}
|
42
|
-
#
|
43
|
-
# 2nd level and higher order associations work as well:
|
44
|
-
#
|
45
|
-
# konata.to_json(:include => { :posts => {
|
46
|
-
# :include => { :comments => {
|
47
|
-
# :only => :body } },
|
48
|
-
# :only => :title } })
|
49
|
-
# # => {"id": 1, "name": "Konata Izumi", "age": 16,
|
50
|
-
# "created_at": "2006/08/01", "awesome": true,
|
51
|
-
# "posts": [{"comments": [{"body": "1st post!"}, {"body": "Second!"}],
|
52
|
-
# "title": "Welcome to the weblog"},
|
53
|
-
# {"comments": [{"body": "Don't think too hard"}],
|
54
|
-
# "title": "So I was thinking"}]}
|
55
|
-
def to_json(options = {})
|
56
|
-
if include_root_in_json
|
57
|
-
"{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
|
58
|
-
else
|
59
|
-
JsonSerializer.new(self, options).to_s
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
class JsonSerializer < CuteKV::Serialization::Serializer #:nodoc:
|
64
|
-
def serialize
|
65
|
-
serializable_object.to_json
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
module ClassMethods
|
70
|
-
def json_class_name
|
71
|
-
@json_class_name ||= name.demodulize.underscore.inspect
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
@@ -1,325 +0,0 @@
|
|
1
|
-
module CuteKV#:nodoc:
|
2
|
-
module Serialization
|
3
|
-
# Builds an XML document to represent the model. Some configuration is
|
4
|
-
# available through +options+. However more complicated cases should
|
5
|
-
# override ActiveObject::Base#to_xml.
|
6
|
-
#
|
7
|
-
# By default the generated XML document will include the processing
|
8
|
-
# instruction and all the object's attributes. For example:
|
9
|
-
#
|
10
|
-
# <?xml version="1.0" encoding="UTF-8"?>
|
11
|
-
# <topic>
|
12
|
-
# <title>The First Topic</title>
|
13
|
-
# <author-name>David</author-name>
|
14
|
-
# <id type="integer">1</id>
|
15
|
-
# <approved type="boolean">false</approved>
|
16
|
-
# <replies-count type="integer">0</replies-count>
|
17
|
-
# <bonus-time type="datetime">2000-01-01T08:28:00+12:00</bonus-time>
|
18
|
-
# <written-on type="datetime">2003-07-16T09:28:00+1200</written-on>
|
19
|
-
# <content>Have a nice day</content>
|
20
|
-
# <author-email-address>david@loudthinking.com</author-email-address>
|
21
|
-
# <parent-id></parent-id>
|
22
|
-
# <last-read type="date">2004-04-15</last-read>
|
23
|
-
# </topic>
|
24
|
-
#
|
25
|
-
# This behavior can be controlled with <tt>:only</tt>, <tt>:except</tt>,
|
26
|
-
# <tt>:skip_instruct</tt>, <tt>:skip_types</tt> and <tt>:dasherize</tt>.
|
27
|
-
# The <tt>:only</tt> and <tt>:except</tt> options are the same as for the
|
28
|
-
# +attributes+ method. The default is to dasherize all column names, but you
|
29
|
-
# can disable this setting <tt>:dasherize</tt> to +false+. To not have the
|
30
|
-
# column type included in the XML output set <tt>:skip_types</tt> to +true+.
|
31
|
-
#
|
32
|
-
# For instance:
|
33
|
-
#
|
34
|
-
# topic.to_xml(:skip_instruct => true, :except => [ :id, :bonus_time, :written_on, :replies_count ])
|
35
|
-
#
|
36
|
-
# <topic>
|
37
|
-
# <title>The First Topic</title>
|
38
|
-
# <author-name>David</author-name>
|
39
|
-
# <approved type="boolean">false</approved>
|
40
|
-
# <content>Have a nice day</content>
|
41
|
-
# <author-email-address>david@loudthinking.com</author-email-address>
|
42
|
-
# <parent-id></parent-id>
|
43
|
-
# <last-read type="date">2004-04-15</last-read>
|
44
|
-
# </topic>
|
45
|
-
#
|
46
|
-
# To include first level associations use <tt>:include</tt>:
|
47
|
-
#
|
48
|
-
# firm.to_xml :include => [ :account, :clients ]
|
49
|
-
#
|
50
|
-
# <?xml version="1.0" encoding="UTF-8"?>
|
51
|
-
# <firm>
|
52
|
-
# <id type="integer">1</id>
|
53
|
-
# <rating type="integer">1</rating>
|
54
|
-
# <name>37signals</name>
|
55
|
-
# <clients type="array">
|
56
|
-
# <client>
|
57
|
-
# <rating type="integer">1</rating>
|
58
|
-
# <name>Summit</name>
|
59
|
-
# </client>
|
60
|
-
# <client>
|
61
|
-
# <rating type="integer">1</rating>
|
62
|
-
# <name>Microsoft</name>
|
63
|
-
# </client>
|
64
|
-
# </clients>
|
65
|
-
# <account>
|
66
|
-
# <id type="integer">1</id>
|
67
|
-
# <credit-limit type="integer">50</credit-limit>
|
68
|
-
# </account>
|
69
|
-
# </firm>
|
70
|
-
#
|
71
|
-
# To include deeper levels of associations pass a hash like this:
|
72
|
-
#
|
73
|
-
# firm.to_xml :include => {:account => {}, :clients => {:include => :address}}
|
74
|
-
# <?xml version="1.0" encoding="UTF-8"?>
|
75
|
-
# <firm>
|
76
|
-
# <id type="integer">1</id>
|
77
|
-
# <rating type="integer">1</rating>
|
78
|
-
# <name>37signals</name>
|
79
|
-
# <clients type="array">
|
80
|
-
# <client>
|
81
|
-
# <rating type="integer">1</rating>
|
82
|
-
# <name>Summit</name>
|
83
|
-
# <address>
|
84
|
-
# ...
|
85
|
-
# </address>
|
86
|
-
# </client>
|
87
|
-
# <client>
|
88
|
-
# <rating type="integer">1</rating>
|
89
|
-
# <name>Microsoft</name>
|
90
|
-
# <address>
|
91
|
-
# ...
|
92
|
-
# </address>
|
93
|
-
# </client>
|
94
|
-
# </clients>
|
95
|
-
# <account>
|
96
|
-
# <id type="integer">1</id>
|
97
|
-
# <credit-limit type="integer">50</credit-limit>
|
98
|
-
# </account>
|
99
|
-
# </firm>
|
100
|
-
#
|
101
|
-
# To include any methods on the model being called use <tt>:methods</tt>:
|
102
|
-
#
|
103
|
-
# firm.to_xml :methods => [ :calculated_earnings, :real_earnings ]
|
104
|
-
#
|
105
|
-
# <firm>
|
106
|
-
# # ... normal attributes as shown above ...
|
107
|
-
# <calculated-earnings>100000000000000000</calculated-earnings>
|
108
|
-
# <real-earnings>5</real-earnings>
|
109
|
-
# </firm>
|
110
|
-
#
|
111
|
-
# To call any additional Procs use <tt>:procs</tt>. The Procs are passed a
|
112
|
-
# modified version of the options hash that was given to +to_xml+:
|
113
|
-
#
|
114
|
-
# proc = Proc.new { |options| options[:builder].tag!('abc', 'def') }
|
115
|
-
# firm.to_xml :procs => [ proc ]
|
116
|
-
#
|
117
|
-
# <firm>
|
118
|
-
# # ... normal attributes as shown above ...
|
119
|
-
# <abc>def</abc>
|
120
|
-
# </firm>
|
121
|
-
#
|
122
|
-
# Alternatively, you can yield the builder object as part of the +to_xml+ call:
|
123
|
-
#
|
124
|
-
# firm.to_xml do |xml|
|
125
|
-
# xml.creator do
|
126
|
-
# xml.first_name "David"
|
127
|
-
# xml.last_name "Heinemeier Hansson"
|
128
|
-
# end
|
129
|
-
# end
|
130
|
-
#
|
131
|
-
# <firm>
|
132
|
-
# # ... normal attributes as shown above ...
|
133
|
-
# <creator>
|
134
|
-
# <first_name>David</first_name>
|
135
|
-
# <last_name>Heinemeier Hansson</last_name>
|
136
|
-
# </creator>
|
137
|
-
# </firm>
|
138
|
-
#
|
139
|
-
# As noted above, you may override +to_xml+ in your ActiveObject::Base
|
140
|
-
# subclasses to have complete control about what's generated. The general
|
141
|
-
# form of doing this is:
|
142
|
-
#
|
143
|
-
# class IHaveMyOwnXML < ActiveObject::Base
|
144
|
-
# def to_xml(options = {})
|
145
|
-
# options[:indent] ||= 2
|
146
|
-
# xml = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
147
|
-
# xml.instruct! unless options[:skip_instruct]
|
148
|
-
# xml.level_one do
|
149
|
-
# xml.tag!(:second_level, 'content')
|
150
|
-
# end
|
151
|
-
# end
|
152
|
-
# end
|
153
|
-
def to_xml(options = {}, &block)
|
154
|
-
serializer = XmlSerializer.new(self, options)
|
155
|
-
block_given? ? serializer.to_s(&block) : serializer.to_s
|
156
|
-
end
|
157
|
-
|
158
|
-
end
|
159
|
-
|
160
|
-
class XmlSerializer < CuteKV::Serialization::Serializer #:nodoc:
|
161
|
-
def builder
|
162
|
-
@builder ||= begin
|
163
|
-
options[:indent] ||= 2
|
164
|
-
builder = options[:builder] ||= Builder::XmlMarkup.new(:indent => options[:indent])
|
165
|
-
|
166
|
-
unless options[:skip_instruct]
|
167
|
-
builder.instruct!
|
168
|
-
options[:skip_instruct] = true
|
169
|
-
end
|
170
|
-
|
171
|
-
builder
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
|
-
def root
|
176
|
-
root = (options[:root] || @object.class.to_s.underscore).to_s
|
177
|
-
dasherize? ? root.dasherize : root
|
178
|
-
end
|
179
|
-
|
180
|
-
def dasherize?
|
181
|
-
!options.has_key?(:dasherize) || options[:dasherize]
|
182
|
-
end
|
183
|
-
|
184
|
-
def serializable_attributes
|
185
|
-
serializable_attribute_names.collect { |name| Attribute.new(name.to_s, @object) }
|
186
|
-
end
|
187
|
-
|
188
|
-
def serializable_method_attributes
|
189
|
-
Array(options[:methods]).inject([]) do |method_attributes, name|
|
190
|
-
method_attributes << MethodAttribute.new(name.to_s, @object) if @object.respond_to?(name.to_s)
|
191
|
-
method_attributes
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def add_attributes
|
196
|
-
(serializable_attributes + serializable_method_attributes).each do |attribute|
|
197
|
-
add_tag(attribute)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
def add_procs
|
202
|
-
if procs = options.delete(:procs)
|
203
|
-
[ *procs ].each do |proc|
|
204
|
-
proc.call(options)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
end
|
208
|
-
|
209
|
-
def add_tag(attribute)
|
210
|
-
builder.tag!(
|
211
|
-
dasherize? ? attribute.name.dasherize : attribute.name,
|
212
|
-
attribute.value.to_s,
|
213
|
-
attribute.decorations(!options[:skip_types])
|
214
|
-
)
|
215
|
-
end
|
216
|
-
|
217
|
-
def add_associations(association, objects, opts)
|
218
|
-
if objects.is_a?(Enumerable)
|
219
|
-
tag = association.to_s
|
220
|
-
tag = tag.dasherize if dasherize?
|
221
|
-
if objects.empty?
|
222
|
-
builder.tag!(tag, :type => :array)
|
223
|
-
else
|
224
|
-
builder.tag!(tag, :type => :array) do
|
225
|
-
association_name = association.to_s.singularize
|
226
|
-
objects.each do |object|
|
227
|
-
object.to_xml opts.merge(
|
228
|
-
:root => association_name,
|
229
|
-
:type => (object.class.to_s.underscore == association_name ? nil : object.class.name)
|
230
|
-
)
|
231
|
-
end
|
232
|
-
end
|
233
|
-
end
|
234
|
-
else
|
235
|
-
if object = @object.send(association)
|
236
|
-
object.to_xml(opts.merge(:root => association))
|
237
|
-
end
|
238
|
-
end
|
239
|
-
end
|
240
|
-
|
241
|
-
def serialize
|
242
|
-
args = [root]
|
243
|
-
if options[:namespace]
|
244
|
-
args << {:xmlns=>options[:namespace]}
|
245
|
-
end
|
246
|
-
|
247
|
-
if options[:type]
|
248
|
-
args << {:type=>options[:type]}
|
249
|
-
end
|
250
|
-
|
251
|
-
builder.tag!(*args) do
|
252
|
-
add_attributes
|
253
|
-
procs = options.delete(:procs)
|
254
|
-
add_includes { |association, objects, opts| add_associations(association, objects, opts) }
|
255
|
-
options[:procs] = procs
|
256
|
-
add_procs
|
257
|
-
yield builder if block_given?
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
class Attribute #:nodoc:
|
262
|
-
attr_reader :name, :value, :type
|
263
|
-
|
264
|
-
def initialize(name, object)
|
265
|
-
@name, @object = name, object
|
266
|
-
|
267
|
-
@type = compute_type
|
268
|
-
@value = compute_value
|
269
|
-
end
|
270
|
-
|
271
|
-
# There is a significant speed improvement if the value
|
272
|
-
# does not need to be escaped, as <tt>tag!</tt> escapes all values
|
273
|
-
# to ensure that valid XML is generated. For known binary
|
274
|
-
# values, it is at least an order of magnitude faster to
|
275
|
-
# Base64 encode binary values and directly put them in the
|
276
|
-
# output XML than to pass the original value or the Base64
|
277
|
-
# encoded value to the <tt>tag!</tt> method. It definitely makes
|
278
|
-
# no sense to Base64 encode the value and then give it to
|
279
|
-
# <tt>tag!</tt>, since that just adds additional overhead.
|
280
|
-
def needs_encoding?
|
281
|
-
![ :binary, :date, :datetime, :boolean, :float, :integer ].include?(type)
|
282
|
-
end
|
283
|
-
|
284
|
-
def decorations(include_types = true)
|
285
|
-
decorations = {}
|
286
|
-
|
287
|
-
if type == :binary
|
288
|
-
decorations[:encoding] = 'base64'
|
289
|
-
end
|
290
|
-
|
291
|
-
if include_types && type != :string
|
292
|
-
decorations[:type] = type
|
293
|
-
end
|
294
|
-
|
295
|
-
if value.nil?
|
296
|
-
decorations[:nil] = true
|
297
|
-
end
|
298
|
-
|
299
|
-
decorations
|
300
|
-
end
|
301
|
-
|
302
|
-
protected
|
303
|
-
def compute_type
|
304
|
-
type = @object.send(name).class
|
305
|
-
end
|
306
|
-
|
307
|
-
def compute_value
|
308
|
-
value = @object.send(name)
|
309
|
-
|
310
|
-
if formatter = Hash::XML_FORMATTING[type.to_s]
|
311
|
-
value ? formatter.call(value) : nil
|
312
|
-
else
|
313
|
-
value
|
314
|
-
end
|
315
|
-
end
|
316
|
-
end
|
317
|
-
|
318
|
-
class MethodAttribute < Attribute #:nodoc:
|
319
|
-
protected
|
320
|
-
def compute_type
|
321
|
-
Hash::XML_TYPE_NAMES[@object.send(name).class.name] || :string
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|