activeobject 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGE +10 -0
- data/Interface_desc +21 -0
- data/MIT-LICENSE +20 -0
- data/README +72 -0
- data/Rakefile.rb +9 -0
- data/active-object.gemspec +50 -0
- data/examples/account.rb +69 -0
- data/examples/data.tch +0 -0
- data/examples/light_cloud.yml +18 -0
- data/examples/test.rb +3 -0
- data/examples/user.rb +112 -0
- data/init.rb +4 -0
- data/lib/active-object.rb +23 -0
- data/lib/active_object/adapters/light_cloud.rb +40 -0
- data/lib/active_object/adapters/tokyo_cabinet.rb +48 -0
- data/lib/active_object/adapters/tokyo_tyrant.rb +14 -0
- data/lib/active_object/associations.rb +200 -0
- data/lib/active_object/base.rb +415 -0
- data/lib/active_object/callbacks.rb +180 -0
- data/lib/active_object/observer.rb +180 -0
- data/lib/active_object/serialization.rb +99 -0
- data/lib/active_object/serializers/json_serializer.rb +75 -0
- data/lib/active_object/serializers/xml_serializer.rb +325 -0
- data/lib/active_object/validations.rb +687 -0
- data/lib/active_support/callbacks.rb +303 -0
- data/lib/active_support/core_ext/array/access.rb +53 -0
- data/lib/active_support/core_ext/array/conversions.rb +183 -0
- data/lib/active_support/core_ext/array/extract_options.rb +20 -0
- data/lib/active_support/core_ext/array/grouping.rb +106 -0
- data/lib/active_support/core_ext/array/random_access.rb +12 -0
- data/lib/active_support/core_ext/array.rb +13 -0
- data/lib/active_support/core_ext/blank.rb +58 -0
- data/lib/active_support/core_ext/class/attribute_accessors.rb +54 -0
- data/lib/active_support/core_ext/class/inheritable_attributes.rb +140 -0
- data/lib/active_support/core_ext/class/removal.rb +50 -0
- data/lib/active_support/core_ext/class.rb +3 -0
- data/lib/active_support/core_ext/duplicable.rb +43 -0
- data/lib/active_support/core_ext/enumerable.rb +72 -0
- data/lib/active_support/core_ext/hash/conversions.rb +259 -0
- data/lib/active_support/core_ext/hash/keys.rb +52 -0
- data/lib/active_support/core_ext/hash.rb +8 -0
- data/lib/active_support/core_ext/module/aliasing.rb +74 -0
- data/lib/active_support/core_ext/module/attr_accessor_with_default.rb +31 -0
- data/lib/active_support/core_ext/module/attribute_accessors.rb +58 -0
- data/lib/active_support/core_ext/module.rb +16 -0
- data/lib/active_support/core_ext/object/conversions.rb +14 -0
- data/lib/active_support/core_ext/object/extending.rb +80 -0
- data/lib/active_support/core_ext/object/instance_variables.rb +74 -0
- data/lib/active_support/core_ext/object/metaclass.rb +13 -0
- data/lib/active_support/core_ext/object/misc.rb +43 -0
- data/lib/active_support/core_ext/object.rb +5 -0
- data/lib/active_support/core_ext/string/inflections.rb +167 -0
- data/lib/active_support/core_ext/string.rb +7 -0
- data/lib/active_support/core_ext.rb +4 -0
- data/lib/active_support/inflections.rb +55 -0
- data/lib/active_support/inflector.rb +348 -0
- data/lib/active_support/vendor/builder-2.1.2/blankslate.rb +113 -0
- data/lib/active_support/vendor/builder-2.1.2/builder/blankslate.rb +20 -0
- data/lib/active_support/vendor/builder-2.1.2/builder/css.rb +250 -0
- data/lib/active_support/vendor/builder-2.1.2/builder/xchar.rb +115 -0
- data/lib/active_support/vendor/builder-2.1.2/builder/xmlbase.rb +139 -0
- data/lib/active_support/vendor/builder-2.1.2/builder/xmlevents.rb +63 -0
- data/lib/active_support/vendor/builder-2.1.2/builder/xmlmarkup.rb +328 -0
- data/lib/active_support/vendor/builder-2.1.2/builder.rb +13 -0
- data/lib/active_support/vendor/xml-simple-1.0.11/xmlsimple.rb +1021 -0
- data/lib/active_support/vendor.rb +14 -0
- data/lib/active_support.rb +6 -0
- data/spec/case/association_test.rb +97 -0
- data/spec/case/base_test.rb +74 -0
- data/spec/case/callbacks_observers_test.rb +38 -0
- data/spec/case/callbacks_test.rb +424 -0
- data/spec/case/serialization_test.rb +87 -0
- data/spec/case/validations_test.rb +1482 -0
- data/spec/data.tch +0 -0
- data/spec/helper.rb +15 -0
- data/spec/light_cloud.yml +18 -0
- data/spec/model/account.rb +4 -0
- data/spec/model/topic.rb +26 -0
- data/spec/model/user.rb +8 -0
- metadata +173 -0
@@ -0,0 +1,250 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#--
|
3
|
+
# Copyright 2004, 2005 by Jim Weirich (jim@weirichhouse.org).
|
4
|
+
# Copyright 2005 by Scott Barron (scott@elitists.net).
|
5
|
+
# All rights reserved.
|
6
|
+
#
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#
|
11
|
+
# Much of this is taken from Jim's work in xmlbase.rb and xmlmarkup.rb.
|
12
|
+
# Documentation has also been copied and pasted and modified to reflect
|
13
|
+
# that we're building CSS here instead of XML. Jim is conducting the
|
14
|
+
# orchestra here and I'm just off in the corner playing a flute.
|
15
|
+
#++
|
16
|
+
|
17
|
+
# Provide a flexible and easy to use Builder for creating Cascading
|
18
|
+
# Style Sheets (CSS).
|
19
|
+
|
20
|
+
|
21
|
+
require 'builder/blankslate'
|
22
|
+
|
23
|
+
module Builder
|
24
|
+
|
25
|
+
# Create a Cascading Style Sheet (CSS) using Ruby.
|
26
|
+
#
|
27
|
+
# Example usage:
|
28
|
+
#
|
29
|
+
# css = Builder::CSS.new
|
30
|
+
#
|
31
|
+
# text_color = '#7F7F7F'
|
32
|
+
# preferred_fonts = 'Helvetica, Arial, sans_serif'
|
33
|
+
#
|
34
|
+
# css.comment! 'This is our stylesheet'
|
35
|
+
# css.body {
|
36
|
+
# background_color '#FAFAFA'
|
37
|
+
# font_size 'small'
|
38
|
+
# font_family preferred_fonts
|
39
|
+
# color text_color
|
40
|
+
# }
|
41
|
+
#
|
42
|
+
# css.id!('navbar') {
|
43
|
+
# width '500px'
|
44
|
+
# }
|
45
|
+
#
|
46
|
+
# css.class!('navitem') {
|
47
|
+
# color 'red'
|
48
|
+
# }
|
49
|
+
#
|
50
|
+
# css.a :hover {
|
51
|
+
# text_decoration 'underline'
|
52
|
+
# }
|
53
|
+
#
|
54
|
+
# css.div(:id => 'menu') {
|
55
|
+
# background 'green'
|
56
|
+
# }
|
57
|
+
#
|
58
|
+
# css.div(:class => 'foo') {
|
59
|
+
# background 'red'
|
60
|
+
# }
|
61
|
+
#
|
62
|
+
# This will yield the following stylesheet:
|
63
|
+
#
|
64
|
+
# /* This is our stylesheet */
|
65
|
+
# body {
|
66
|
+
# background_color: #FAFAFA;
|
67
|
+
# font_size: small;
|
68
|
+
# font_family: Helvetica, Arial, sans_serif;
|
69
|
+
# color: #7F7F7F;
|
70
|
+
# }
|
71
|
+
#
|
72
|
+
# #navbar {
|
73
|
+
# width: 500px;
|
74
|
+
# }
|
75
|
+
#
|
76
|
+
# .navitem {
|
77
|
+
# color: red;
|
78
|
+
# }
|
79
|
+
#
|
80
|
+
# a:hover {
|
81
|
+
# text_decoration: underline;
|
82
|
+
# }
|
83
|
+
#
|
84
|
+
# div#menu {
|
85
|
+
# background: green;
|
86
|
+
# }
|
87
|
+
#
|
88
|
+
# div.foo {
|
89
|
+
# background: red;
|
90
|
+
# }
|
91
|
+
#
|
92
|
+
class CSS < BlankSlate
|
93
|
+
|
94
|
+
# Create a CSS builder.
|
95
|
+
#
|
96
|
+
# out:: Object receiving the markup.1 +out+ must respond to
|
97
|
+
# <tt><<</tt>.
|
98
|
+
# indent:: Number of spaces used for indentation (0 implies no
|
99
|
+
# indentation and no line breaks).
|
100
|
+
#
|
101
|
+
def initialize(indent=2)
|
102
|
+
@indent = indent
|
103
|
+
@target = []
|
104
|
+
@parts = []
|
105
|
+
@library = {}
|
106
|
+
end
|
107
|
+
|
108
|
+
def +(part)
|
109
|
+
_join_with_op! '+'
|
110
|
+
self
|
111
|
+
end
|
112
|
+
|
113
|
+
def >>(part)
|
114
|
+
_join_with_op! ''
|
115
|
+
self
|
116
|
+
end
|
117
|
+
|
118
|
+
def >(part)
|
119
|
+
_join_with_op! '>'
|
120
|
+
self
|
121
|
+
end
|
122
|
+
|
123
|
+
def |(part)
|
124
|
+
_join_with_op! ','
|
125
|
+
self
|
126
|
+
end
|
127
|
+
|
128
|
+
# Return the target of the builder
|
129
|
+
def target!
|
130
|
+
@target * ''
|
131
|
+
end
|
132
|
+
|
133
|
+
# Create a comment string in the output.
|
134
|
+
def comment!(comment_text)
|
135
|
+
@target << "/* #{comment_text} */\n"
|
136
|
+
end
|
137
|
+
|
138
|
+
def id!(arg, &block)
|
139
|
+
_start_container('#'+arg.to_s, nil, block_given?)
|
140
|
+
_css_block(block) if block
|
141
|
+
_unify_block
|
142
|
+
self
|
143
|
+
end
|
144
|
+
|
145
|
+
def class!(arg, &block)
|
146
|
+
_start_container('.'+arg.to_s, nil, block_given?)
|
147
|
+
_css_block(block) if block
|
148
|
+
_unify_block
|
149
|
+
self
|
150
|
+
end
|
151
|
+
|
152
|
+
def store!(sym, &block)
|
153
|
+
@library[sym] = block.to_proc
|
154
|
+
end
|
155
|
+
|
156
|
+
def group!(*args, &block)
|
157
|
+
args.each do |arg|
|
158
|
+
if arg.is_a?(Symbol)
|
159
|
+
instance_eval(&@library[arg])
|
160
|
+
else
|
161
|
+
instance_eval(&arg)
|
162
|
+
end
|
163
|
+
_text ', ' unless arg == args.last
|
164
|
+
end
|
165
|
+
if block
|
166
|
+
_css_block(block)
|
167
|
+
_unify_block
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def method_missing(sym, *args, &block)
|
172
|
+
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
173
|
+
if block
|
174
|
+
_start_container(sym, args.first)
|
175
|
+
_css_block(block)
|
176
|
+
_unify_block
|
177
|
+
elsif @in_block
|
178
|
+
_indent
|
179
|
+
_css_line(sym, *args)
|
180
|
+
_newline
|
181
|
+
return self
|
182
|
+
else
|
183
|
+
_start_container(sym, args.first, false)
|
184
|
+
_unify_block
|
185
|
+
end
|
186
|
+
self
|
187
|
+
end
|
188
|
+
|
189
|
+
# "Cargo culted" from Jim who also "cargo culted" it. See xmlbase.rb.
|
190
|
+
def nil?
|
191
|
+
false
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
def _unify_block
|
196
|
+
@target << @parts * ''
|
197
|
+
@parts = []
|
198
|
+
end
|
199
|
+
|
200
|
+
def _join_with_op!(op)
|
201
|
+
rhs, lhs = @target.pop, @target.pop
|
202
|
+
@target << "#{lhs} #{op} #{rhs}"
|
203
|
+
end
|
204
|
+
|
205
|
+
def _text(text)
|
206
|
+
@parts << text
|
207
|
+
end
|
208
|
+
|
209
|
+
def _css_block(block)
|
210
|
+
_newline
|
211
|
+
_nested_structures(block)
|
212
|
+
_end_container
|
213
|
+
_end_block
|
214
|
+
end
|
215
|
+
|
216
|
+
def _end_block
|
217
|
+
_newline
|
218
|
+
_newline
|
219
|
+
end
|
220
|
+
|
221
|
+
def _newline
|
222
|
+
_text "\n"
|
223
|
+
end
|
224
|
+
|
225
|
+
def _indent
|
226
|
+
_text ' ' * @indent
|
227
|
+
end
|
228
|
+
|
229
|
+
def _nested_structures(block)
|
230
|
+
@in_block = true
|
231
|
+
self.instance_eval(&block)
|
232
|
+
@in_block = false
|
233
|
+
end
|
234
|
+
|
235
|
+
def _start_container(sym, atts = {}, with_bracket = true)
|
236
|
+
selector = sym.to_s
|
237
|
+
selector << ".#{atts[:class]}" if atts && atts[:class]
|
238
|
+
selector << '#' + "#{atts[:id]}" if atts && atts[:id]
|
239
|
+
@parts << "#{selector}#{with_bracket ? ' {' : ''}"
|
240
|
+
end
|
241
|
+
|
242
|
+
def _end_container
|
243
|
+
@parts << "}"
|
244
|
+
end
|
245
|
+
|
246
|
+
def _css_line(sym, *args)
|
247
|
+
_text("#{sym.to_s.gsub('_','-')}: #{args * ' '};")
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# The XChar library is provided courtesy of Sam Ruby (See
|
4
|
+
# http://intertwingly.net/stories/2005/09/28/xchar.rb)
|
5
|
+
|
6
|
+
# --------------------------------------------------------------------
|
7
|
+
|
8
|
+
# If the Builder::XChar module is not currently defined, fail on any
|
9
|
+
# name clashes in standard library classes.
|
10
|
+
|
11
|
+
module Builder
|
12
|
+
def self.check_for_name_collision(klass, method_name, defined_constant=nil)
|
13
|
+
if klass.instance_methods.include?(method_name.to_s)
|
14
|
+
fail RuntimeError,
|
15
|
+
"Name Collision: Method '#{method_name}' is already defined in #{klass}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
if ! defined?(Builder::XChar)
|
21
|
+
Builder.check_for_name_collision(String, "to_xs")
|
22
|
+
Builder.check_for_name_collision(Fixnum, "xchr")
|
23
|
+
end
|
24
|
+
|
25
|
+
######################################################################
|
26
|
+
module Builder
|
27
|
+
|
28
|
+
####################################################################
|
29
|
+
# XML Character converter, from Sam Ruby:
|
30
|
+
# (see http://intertwingly.net/stories/2005/09/28/xchar.rb).
|
31
|
+
#
|
32
|
+
module XChar # :nodoc:
|
33
|
+
|
34
|
+
# See
|
35
|
+
# http://intertwingly.net/stories/2004/04/14/i18n.html#CleaningWindows
|
36
|
+
# for details.
|
37
|
+
CP1252 = { # :nodoc:
|
38
|
+
128 => 8364, # euro sign
|
39
|
+
130 => 8218, # single low-9 quotation mark
|
40
|
+
131 => 402, # latin small letter f with hook
|
41
|
+
132 => 8222, # double low-9 quotation mark
|
42
|
+
133 => 8230, # horizontal ellipsis
|
43
|
+
134 => 8224, # dagger
|
44
|
+
135 => 8225, # double dagger
|
45
|
+
136 => 710, # modifier letter circumflex accent
|
46
|
+
137 => 8240, # per mille sign
|
47
|
+
138 => 352, # latin capital letter s with caron
|
48
|
+
139 => 8249, # single left-pointing angle quotation mark
|
49
|
+
140 => 338, # latin capital ligature oe
|
50
|
+
142 => 381, # latin capital letter z with caron
|
51
|
+
145 => 8216, # left single quotation mark
|
52
|
+
146 => 8217, # right single quotation mark
|
53
|
+
147 => 8220, # left double quotation mark
|
54
|
+
148 => 8221, # right double quotation mark
|
55
|
+
149 => 8226, # bullet
|
56
|
+
150 => 8211, # en dash
|
57
|
+
151 => 8212, # em dash
|
58
|
+
152 => 732, # small tilde
|
59
|
+
153 => 8482, # trade mark sign
|
60
|
+
154 => 353, # latin small letter s with caron
|
61
|
+
155 => 8250, # single right-pointing angle quotation mark
|
62
|
+
156 => 339, # latin small ligature oe
|
63
|
+
158 => 382, # latin small letter z with caron
|
64
|
+
159 => 376, # latin capital letter y with diaeresis
|
65
|
+
}
|
66
|
+
|
67
|
+
# See http://www.w3.org/TR/REC-xml/#dt-chardata for details.
|
68
|
+
PREDEFINED = {
|
69
|
+
38 => '&', # ampersand
|
70
|
+
60 => '<', # left angle bracket
|
71
|
+
62 => '>', # right angle bracket
|
72
|
+
}
|
73
|
+
|
74
|
+
# See http://www.w3.org/TR/REC-xml/#charsets for details.
|
75
|
+
VALID = [
|
76
|
+
0x9, 0xA, 0xD,
|
77
|
+
(0x20..0xD7FF),
|
78
|
+
(0xE000..0xFFFD),
|
79
|
+
(0x10000..0x10FFFF)
|
80
|
+
]
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
######################################################################
|
87
|
+
# Enhance the Fixnum class with a XML escaped character conversion.
|
88
|
+
#
|
89
|
+
class Fixnum
|
90
|
+
XChar = Builder::XChar if ! defined?(XChar)
|
91
|
+
|
92
|
+
# XML escaped version of chr
|
93
|
+
def xchr
|
94
|
+
n = XChar::CP1252[self] || self
|
95
|
+
case n when *XChar::VALID
|
96
|
+
XChar::PREDEFINED[n] or (n<128 ? n.chr : "&##{n};")
|
97
|
+
else
|
98
|
+
'*'
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
|
104
|
+
######################################################################
|
105
|
+
# Enhance the String class with a XML escaped character version of
|
106
|
+
# to_s.
|
107
|
+
#
|
108
|
+
class String
|
109
|
+
# XML escaped version of to_s
|
110
|
+
def to_xs
|
111
|
+
unpack('U*').map {|n| n.xchr}.join # ASCII, UTF-8
|
112
|
+
rescue
|
113
|
+
unpack('C*').map {|n| n.xchr}.join # ISO-8859-1, WIN-1252
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'builder/blankslate'
|
4
|
+
|
5
|
+
module Builder
|
6
|
+
|
7
|
+
# Generic error for builder
|
8
|
+
class IllegalBlockError < RuntimeError; end
|
9
|
+
|
10
|
+
# XmlBase is a base class for building XML builders. See
|
11
|
+
# Builder::XmlMarkup and Builder::XmlEvents for examples.
|
12
|
+
class XmlBase < BlankSlate
|
13
|
+
|
14
|
+
# Create an XML markup builder.
|
15
|
+
#
|
16
|
+
# out:: Object receiving the markup. +out+ must respond to
|
17
|
+
# <tt><<</tt>.
|
18
|
+
# indent:: Number of spaces used for indentation (0 implies no
|
19
|
+
# indentation and no line breaks).
|
20
|
+
# initial:: Level of initial indentation.
|
21
|
+
#
|
22
|
+
def initialize(indent=0, initial=0)
|
23
|
+
@indent = indent
|
24
|
+
@level = initial
|
25
|
+
end
|
26
|
+
|
27
|
+
# Create a tag named +sym+. Other than the first argument which
|
28
|
+
# is the tag name, the arguments are the same as the tags
|
29
|
+
# implemented via <tt>method_missing</tt>.
|
30
|
+
def tag!(sym, *args, &block)
|
31
|
+
method_missing(sym.to_sym, *args, &block)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create XML markup based on the name of the method. This method
|
35
|
+
# is never invoked directly, but is called for each markup method
|
36
|
+
# in the markup block.
|
37
|
+
def method_missing(sym, *args, &block)
|
38
|
+
text = nil
|
39
|
+
attrs = nil
|
40
|
+
sym = "#{sym}:#{args.shift}" if args.first.kind_of?(Symbol)
|
41
|
+
args.each do |arg|
|
42
|
+
case arg
|
43
|
+
when Hash
|
44
|
+
attrs ||= {}
|
45
|
+
attrs.merge!(arg)
|
46
|
+
else
|
47
|
+
text ||= ''
|
48
|
+
text << arg.to_s
|
49
|
+
end
|
50
|
+
end
|
51
|
+
if block
|
52
|
+
unless text.nil?
|
53
|
+
raise ArgumentError, "XmlMarkup cannot mix a text argument with a block"
|
54
|
+
end
|
55
|
+
_indent
|
56
|
+
_start_tag(sym, attrs)
|
57
|
+
_newline
|
58
|
+
_nested_structures(block)
|
59
|
+
_indent
|
60
|
+
_end_tag(sym)
|
61
|
+
_newline
|
62
|
+
elsif text.nil?
|
63
|
+
_indent
|
64
|
+
_start_tag(sym, attrs, true)
|
65
|
+
_newline
|
66
|
+
else
|
67
|
+
_indent
|
68
|
+
_start_tag(sym, attrs)
|
69
|
+
text! text
|
70
|
+
_end_tag(sym)
|
71
|
+
_newline
|
72
|
+
end
|
73
|
+
@target
|
74
|
+
end
|
75
|
+
|
76
|
+
# Append text to the output target. Escape any markup. May be
|
77
|
+
# used within the markup brackets as:
|
78
|
+
#
|
79
|
+
# builder.p { |b| b.br; b.text! "HI" } #=> <p><br/>HI</p>
|
80
|
+
def text!(text)
|
81
|
+
_text(_escape(text))
|
82
|
+
end
|
83
|
+
|
84
|
+
# Append text to the output target without escaping any markup.
|
85
|
+
# May be used within the markup brackets as:
|
86
|
+
#
|
87
|
+
# builder.p { |x| x << "<br/>HI" } #=> <p><br/>HI</p>
|
88
|
+
#
|
89
|
+
# This is useful when using non-builder enabled software that
|
90
|
+
# generates strings. Just insert the string directly into the
|
91
|
+
# builder without changing the inserted markup.
|
92
|
+
#
|
93
|
+
# It is also useful for stacking builder objects. Builders only
|
94
|
+
# use <tt><<</tt> to append to the target, so by supporting this
|
95
|
+
# method/operation builders can use other builders as their
|
96
|
+
# targets.
|
97
|
+
def <<(text)
|
98
|
+
_text(text)
|
99
|
+
end
|
100
|
+
|
101
|
+
# For some reason, nil? is sent to the XmlMarkup object. If nil?
|
102
|
+
# is not defined and method_missing is invoked, some strange kind
|
103
|
+
# of recursion happens. Since nil? won't ever be an XML tag, it
|
104
|
+
# is pretty safe to define it here. (Note: this is an example of
|
105
|
+
# cargo cult programming,
|
106
|
+
# cf. http://fishbowl.pastiche.org/2004/10/13/cargo_cult_programming).
|
107
|
+
def nil?
|
108
|
+
false
|
109
|
+
end
|
110
|
+
|
111
|
+
private
|
112
|
+
|
113
|
+
require 'builder/xchar'
|
114
|
+
def _escape(text)
|
115
|
+
text.to_xs
|
116
|
+
end
|
117
|
+
|
118
|
+
def _escape_quote(text)
|
119
|
+
_escape(text).gsub(%r{"}, '"') # " WART
|
120
|
+
end
|
121
|
+
|
122
|
+
def _newline
|
123
|
+
return if @indent == 0
|
124
|
+
text! "\n"
|
125
|
+
end
|
126
|
+
|
127
|
+
def _indent
|
128
|
+
return if @indent == 0 || @level == 0
|
129
|
+
text!(" " * (@level * @indent))
|
130
|
+
end
|
131
|
+
|
132
|
+
def _nested_structures(block)
|
133
|
+
@level += 1
|
134
|
+
block.call(self)
|
135
|
+
ensure
|
136
|
+
@level -= 1
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
#--
|
4
|
+
# Copyright 2004 by Jim Weirich (jim@weirichhouse.org).
|
5
|
+
# All rights reserved.
|
6
|
+
|
7
|
+
# Permission is granted for use, copying, modification, distribution,
|
8
|
+
# and distribution of modified versions of this work as long as the
|
9
|
+
# above copyright notice is included.
|
10
|
+
#++
|
11
|
+
|
12
|
+
require 'builder/xmlmarkup'
|
13
|
+
|
14
|
+
module Builder
|
15
|
+
|
16
|
+
# Create a series of SAX-like XML events (e.g. start_tag, end_tag)
|
17
|
+
# from the markup code. XmlEvent objects are used in a way similar
|
18
|
+
# to XmlMarkup objects, except that a series of events are generated
|
19
|
+
# and passed to a handler rather than generating character-based
|
20
|
+
# markup.
|
21
|
+
#
|
22
|
+
# Usage:
|
23
|
+
# xe = Builder::XmlEvents.new(handler)
|
24
|
+
# xe.title("HI") # Sends start_tag/end_tag/text messages to the handler.
|
25
|
+
#
|
26
|
+
# Indentation may also be selected by providing value for the
|
27
|
+
# indentation size and initial indentation level.
|
28
|
+
#
|
29
|
+
# xe = Builder::XmlEvents.new(handler, indent_size, initial_indent_level)
|
30
|
+
#
|
31
|
+
# == XML Event Handler
|
32
|
+
#
|
33
|
+
# The handler object must expect the following events.
|
34
|
+
#
|
35
|
+
# [<tt>start_tag(tag, attrs)</tt>]
|
36
|
+
# Announces that a new tag has been found. +tag+ is the name of
|
37
|
+
# the tag and +attrs+ is a hash of attributes for the tag.
|
38
|
+
#
|
39
|
+
# [<tt>end_tag(tag)</tt>]
|
40
|
+
# Announces that an end tag for +tag+ has been found.
|
41
|
+
#
|
42
|
+
# [<tt>text(text)</tt>]
|
43
|
+
# Announces that a string of characters (+text+) has been found.
|
44
|
+
# A series of characters may be broken up into more than one
|
45
|
+
# +text+ call, so the client cannot assume that a single
|
46
|
+
# callback contains all the text data.
|
47
|
+
#
|
48
|
+
class XmlEvents < XmlMarkup
|
49
|
+
def text!(text)
|
50
|
+
@target.text(text)
|
51
|
+
end
|
52
|
+
|
53
|
+
def _start_tag(sym, attrs, end_too=false)
|
54
|
+
@target.start_tag(sym, attrs)
|
55
|
+
_end_tag(sym) if end_too
|
56
|
+
end
|
57
|
+
|
58
|
+
def _end_tag(sym)
|
59
|
+
@target.end_tag(sym)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|