blankslate 2.1.2.4 → 3.1.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.
@@ -0,0 +1,31 @@
1
+ = Builder 1.2.4 Released.
2
+
3
+ Added a "CDATA" method to the XML Markup builder (from Josh Knowles).
4
+
5
+ == What is Builder?
6
+
7
+ Builder::XmlMarkup allows easy programmatic creation of XML markup.
8
+ For example:
9
+
10
+ builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)
11
+ builder.person { |b| b.name("Jim"); b.phone("555-1234") }
12
+ puts builder.target!
13
+
14
+ will generate:
15
+
16
+ <person>
17
+ <name>Jim</name>
18
+ <phone>555-1234</phone>
19
+ </person>
20
+
21
+ == Availability
22
+
23
+ The easiest way to get and install builder is via RubyGems ...
24
+
25
+ gem install builder (you may need root/admin privileges)
26
+
27
+ == Thanks
28
+
29
+ * Josh Knowles for the cdata! patch.
30
+
31
+ -- Jim Weirich
@@ -0,0 +1,46 @@
1
+ = Builder 2.0.0 Released.
2
+
3
+ == Changes in 2.0.0
4
+
5
+ * UTF-8 characters in data are now correctly translated to their XML
6
+ equivalents. (Thanks to Sam Ruby)
7
+
8
+ * Attribute values are now escaped by default. See the README
9
+ file for details.
10
+
11
+ <b>NOTE:</b> The escaping attribute values by default is different
12
+ than in previous releases of Builder. This makes version 2.0.0
13
+ somewhat incompatible with the 1.x series of Builder. If you use "&",
14
+ "<", or ">" in attributes values, you may have to change your
15
+ code. (Essentially you remove the manual escaping. The new way is
16
+ easier, believe me).
17
+
18
+ == What is Builder?
19
+
20
+ Builder::XmlMarkup is a library that allows easy programmatic creation
21
+ of XML markup. For example:
22
+
23
+ builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)
24
+ builder.person { |b| b.name("Jim"); b.phone("555-1234") }
25
+
26
+ will generate:
27
+
28
+ <person>
29
+ <name>Jim</name>
30
+ <phone>555-1234</phone>
31
+ </person>
32
+
33
+ == Availability
34
+
35
+ The easiest way to get and install builder is via RubyGems ...
36
+
37
+ gem install builder (you may need root/admin privileges)
38
+
39
+ == Thanks
40
+
41
+ * Sam Ruby for the XChar module and the related UTF-8 translation
42
+ tools.
43
+ * Also to Sam Ruby for gently persuading me to start quoting attribute
44
+ values.
45
+
46
+ -- Jim Weirich
@@ -0,0 +1,58 @@
1
+ = Builder 2.1.1 Released.
2
+
3
+ Release 2.1.1 of Builder is mainly a bug fix release.
4
+
5
+ == Changes in 2.1.1
6
+
7
+ * Added <tt>reveal</tt> capability to BlankSlate.
8
+
9
+ * Fixed a bug in BlankSlate where including a module into Object could
10
+ cause methods to leak into BlankSlate.
11
+
12
+ * Fixed typo in XmlMarkup class docs (from Martin Fowler).
13
+
14
+ * Fixed test on private methods to differentiate between targetted and
15
+ untargetted private methods.
16
+
17
+ * Removed legacy capture of @self in XmlBase (@self was used back when
18
+ we used instance eval).
19
+
20
+ * Added additional tests for global functions (both direct and
21
+ included).
22
+
23
+ * Several misc internal cleanups, including rearranging the source
24
+ code tree.
25
+
26
+ <b>NOTE:</b> The escaping attribute values by default is different
27
+ than in previous releases of Builder. This makes version 2.0.x
28
+ somewhat incompatible with the 1.x series of Builder. If you use "&",
29
+ "<", or ">" in attributes values, you may have to change your
30
+ code. (Essentially you remove the manual escaping. The new way is
31
+ easier, believe me).
32
+
33
+ == What is Builder?
34
+
35
+ Builder::XmlMarkup is a library that allows easy programmatic creation
36
+ of XML markup. For example:
37
+
38
+ builder = Builder::XmlMarkup.new(:target=>STDOUT, :indent=>2)
39
+ builder.person { |b| b.name("Jim"); b.phone("555-1234") }
40
+
41
+ will generate:
42
+
43
+ <person>
44
+ <name>Jim</name>
45
+ <phone>555-1234</phone>
46
+ </person>
47
+
48
+ == Availability
49
+
50
+ The easiest way to get and install builder is via RubyGems ...
51
+
52
+ gem install builder (you may need root/admin privileges)
53
+
54
+ == Thanks
55
+
56
+ * Martin Fowler for spotting some typos in the documentation.
57
+
58
+ -- Jim Weirich
@@ -8,6 +8,30 @@
8
8
  # above copyright notice is included.
9
9
  #++
10
10
 
11
+ class String
12
+ if instance_methods.first.is_a?(Symbol)
13
+ def _blankslate_as_name
14
+ to_sym
15
+ end
16
+ else
17
+ def _blankslate_as_name
18
+ self
19
+ end
20
+ end
21
+ end
22
+
23
+ class Symbol
24
+ if instance_methods.first.is_a?(Symbol)
25
+ def _blankslate_as_name
26
+ self
27
+ end
28
+ else
29
+ def _blankslate_as_name
30
+ to_s
31
+ end
32
+ end
33
+ end
34
+
11
35
  ######################################################################
12
36
  # BlankSlate provides an abstract base class with no predefined
13
37
  # methods (except for <tt>\_\_send__</tt> and <tt>\_\_id__</tt>).
@@ -16,12 +40,12 @@
16
40
  #
17
41
  class BlankSlate
18
42
  class << self
19
-
43
+
20
44
  # Hide the method named +name+ in the BlankSlate class. Don't
21
45
  # hide +instance_eval+ or any method beginning with "__".
22
46
  def hide(name)
23
- if instance_methods.map(&:to_sym).include?(name.to_sym) and
24
- name !~ /^(__|instance_eval|object_id)/
47
+ if instance_methods.include?(name._blankslate_as_name) and
48
+ name !~ /^(__|instance_eval$)/
25
49
  @hidden_methods ||= {}
26
50
  @hidden_methods[name.to_sym] = instance_method(name)
27
51
  undef_method name
@@ -41,7 +65,7 @@ class BlankSlate
41
65
  define_method(name, hidden_method)
42
66
  end
43
67
  end
44
-
68
+
45
69
  instance_methods.each { |m| hide(m) }
46
70
  end
47
71
 
@@ -106,4 +130,4 @@ class Module
106
130
  end
107
131
  result
108
132
  end
109
- end
133
+ end
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org).
5
+ # Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net).
6
+ # All rights reserved.
7
+
8
+ # Permission is granted for use, copying, modification, distribution,
9
+ # and distribution of modified versions of this work as long as the
10
+ # above copyright notice is included.
11
+ #++
12
+
13
+ require 'test/unit'
14
+ require 'test/preload'
15
+ require 'blankslate'
16
+ require 'stringio'
17
+
18
+ # Methods to be introduced into the Object class late.
19
+ module LateObject
20
+ def late_object
21
+ 33
22
+ end
23
+ def LateObject.included(mod)
24
+ # Modules defining an included method should not prevent blank
25
+ # slate erasure!
26
+ end
27
+ end
28
+
29
+ # Methods to be introduced into the Kernel module late.
30
+ module LateKernel
31
+ def late_kernel
32
+ 44
33
+ end
34
+ def LateKernel.included(mod)
35
+ # Modules defining an included method should not prevent blank
36
+ # slate erasure!
37
+ end
38
+ end
39
+
40
+ # Introduce some late methods (both module and direct) into the Kernel
41
+ # module.
42
+ module Kernel
43
+ include LateKernel
44
+
45
+ def late_addition
46
+ 1234
47
+ end
48
+
49
+ def double_late_addition
50
+ 11
51
+ end
52
+
53
+ def double_late_addition
54
+ 22
55
+ end
56
+ end
57
+
58
+
59
+ # Introduce some late methods (both module and direct) into the Object
60
+ # class.
61
+ class Object
62
+ include LateObject
63
+ def another_late_addition
64
+ 4321
65
+ end
66
+ end
67
+
68
+ # Introduce some late methods by inclusion.
69
+ module GlobalModule
70
+ def global_inclusion
71
+ 42
72
+ end
73
+ end
74
+ include GlobalModule
75
+
76
+ def direct_global
77
+ 43
78
+ end
79
+
80
+ ######################################################################
81
+ # Test case for blank slate.
82
+ #
83
+ class TestBlankSlate < Test::Unit::TestCase
84
+ def setup
85
+ @bs = BlankSlate.new
86
+ end
87
+
88
+ def test_undefined_methods_remain_undefined
89
+ assert_raise(NoMethodError) { @bs.no_such_method }
90
+ assert_raise(NoMethodError) { @bs.nil? }
91
+ end
92
+
93
+
94
+ # NOTE: NameError is acceptable because the lack of a '.' means that
95
+ # Ruby can't tell if it is a method or a local variable.
96
+ def test_undefined_methods_remain_undefined_during_instance_eval
97
+ assert_raise(NoMethodError, NameError) do
98
+ @bs.instance_eval do nil? end
99
+ end
100
+ assert_raise(NoMethodError, NameError) do
101
+ @bs.instance_eval do no_such_method end
102
+ end
103
+ end
104
+
105
+ def test_private_methods_are_undefined
106
+ assert_raise(NoMethodError) do
107
+ @bs.puts "HI"
108
+ end
109
+ end
110
+
111
+ def test_targetted_private_methods_are_undefined_during_instance_eval
112
+ assert_raise(NoMethodError, NameError) do
113
+ @bs.instance_eval do self.puts "HI" end
114
+ end
115
+ end
116
+
117
+ def test_untargetted_private_methods_are_defined_during_instance_eval
118
+ oldstdout = $stdout
119
+ $stdout = StringIO.new
120
+ @bs.instance_eval do
121
+ puts "HI"
122
+ end
123
+ ensure
124
+ $stdout = oldstdout
125
+ end
126
+
127
+ def test_methods_added_late_to_kernel_remain_undefined
128
+ assert_equal 1234, nil.late_addition
129
+ assert_raise(NoMethodError) { @bs.late_addition }
130
+ end
131
+
132
+ def test_methods_added_late_to_object_remain_undefined
133
+ assert_equal 4321, nil.another_late_addition
134
+ assert_raise(NoMethodError) { @bs.another_late_addition }
135
+ end
136
+
137
+ def test_methods_added_late_to_global_remain_undefined
138
+ assert_equal 42, global_inclusion
139
+ assert_raise(NoMethodError) { @bs.global_inclusion }
140
+ end
141
+
142
+ def test_preload_method_added
143
+ assert Kernel.k_added_names.include?(:late_addition)
144
+ assert Object.o_added_names.include?(:another_late_addition)
145
+ end
146
+
147
+ def test_method_defined_late_multiple_times_remain_undefined
148
+ assert_equal 22, nil.double_late_addition
149
+ assert_raise(NoMethodError) { @bs.double_late_addition }
150
+ end
151
+
152
+ def test_late_included_module_in_object_is_ok
153
+ assert_equal 33, 1.late_object
154
+ assert_raise(NoMethodError) { @bs.late_object }
155
+ end
156
+
157
+ def test_late_included_module_in_kernel_is_ok
158
+ assert_raise(NoMethodError) { @bs.late_kernel }
159
+ end
160
+
161
+ def test_revealing_previously_hidden_methods_are_callable
162
+ with_to_s = Class.new(BlankSlate) do
163
+ reveal :to_s
164
+ end
165
+ assert_match(/^#<.*>$/, with_to_s.new.to_s)
166
+ end
167
+
168
+ def test_revealing_previously_hidden_methods_are_callable_with_block
169
+ Object.class_eval <<-EOS
170
+ def given_block(&block)
171
+ block
172
+ end
173
+ EOS
174
+
175
+ with_given_block = Class.new(BlankSlate) do
176
+ reveal :given_block
177
+ end
178
+ assert_not_nil with_given_block.new.given_block {}
179
+ end
180
+
181
+ def test_revealing_a_hidden_method_twice_is_ok
182
+ with_to_s = Class.new(BlankSlate) do
183
+ reveal :to_s
184
+ reveal :to_s
185
+ end
186
+ assert_match(/^#<.*>$/, with_to_s.new.to_s)
187
+ end
188
+
189
+ def test_revealing_unknown_hidden_method_is_an_error
190
+ assert_raises(RuntimeError) do
191
+ Class.new(BlankSlate) do
192
+ reveal :xyz
193
+ end
194
+ end
195
+ end
196
+
197
+ def test_global_includes_still_work
198
+ assert_nothing_raised do
199
+ assert_equal 42, global_inclusion
200
+ assert_equal 42, Object.new.global_inclusion
201
+ assert_equal 42, "magic number".global_inclusion
202
+ assert_equal 43, direct_global
203
+ end
204
+ end
205
+
206
+ def test_reveal_should_not_bind_to_an_instance
207
+ with_object_id = Class.new(BlankSlate) do
208
+ reveal(:object_id)
209
+ end
210
+
211
+ obj1 = with_object_id.new
212
+ obj2 = with_object_id.new
213
+
214
+ assert obj1.object_id != obj2.object_id,
215
+ "Revealed methods should not be bound to a particular instance"
216
+ end
217
+ end
@@ -0,0 +1,150 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ #--
4
+ # Portions copyright 2004 by Jim Weirich (jim@weirichhouse.org).
5
+ # Portions copyright 2005 by Sam Ruby (rubys@intertwingly.net).
6
+ # All rights reserved.
7
+
8
+ # Permission is granted for use, copying, modification, distribution,
9
+ # and distribution of modified versions of this work as long as the
10
+ # above copyright notice is included.
11
+ #++
12
+
13
+ require 'test/unit'
14
+ require 'test/preload'
15
+ require 'builder'
16
+ require 'builder/xmlevents'
17
+
18
+ class TestEvents < Test::Unit::TestCase
19
+
20
+ class Target
21
+ attr_reader :events
22
+
23
+ def initialize
24
+ @events = []
25
+ end
26
+
27
+ def start_tag(tag, attrs)
28
+ @events << [:start_tag, tag, attrs]
29
+ end
30
+
31
+ def end_tag(tag)
32
+ @events << [:end_tag, tag]
33
+ end
34
+
35
+ def text(string)
36
+ @events << [:text, string]
37
+ end
38
+
39
+ end
40
+
41
+
42
+ def setup
43
+ @target = Target.new
44
+ @xml = Builder::XmlEvents.new(:target=>@target)
45
+ end
46
+
47
+ def test_simple
48
+ @xml.one
49
+ expect [:start_tag, :one, nil]
50
+ expect [:end_tag, :one]
51
+ expect_done
52
+ end
53
+
54
+ def test_nested
55
+ @xml.one { @xml.two }
56
+ expect [:start_tag, :one, nil]
57
+ expect [:start_tag, :two, nil]
58
+ expect [:end_tag, :two]
59
+ expect [:end_tag, :one]
60
+ expect_done
61
+ end
62
+
63
+ def test_text
64
+ @xml.one("a")
65
+ expect [:start_tag, :one, nil]
66
+ expect [:text, "a"]
67
+ expect [:end_tag, :one]
68
+ expect_done
69
+ end
70
+
71
+ def test_special_text
72
+ @xml.one("H&R")
73
+ expect [:start_tag, :one, nil]
74
+ expect [:text, "H&R"]
75
+ expect [:end_tag, :one]
76
+ expect_done
77
+ end
78
+
79
+ def test_text_with_entity
80
+ @xml.one("H&amp;R")
81
+ expect [:start_tag, :one, nil]
82
+ expect [:text, "H&amp;R"]
83
+ expect [:end_tag, :one]
84
+ expect_done
85
+ end
86
+
87
+ def test_attributes
88
+ @xml.a(:b=>"c", :x=>"y")
89
+ expect [:start_tag, :a, {:x => "y", :b => "c"}]
90
+ expect [:end_tag, :a]
91
+ expect_done
92
+ end
93
+
94
+ def test_moderately_complex
95
+ @xml.tag! "address-book" do |x|
96
+ x.entry :id=>"1" do
97
+ x.name {
98
+ x.first "Bill"
99
+ x.last "Smith"
100
+ }
101
+ x.address "Cincinnati"
102
+ end
103
+ x.entry :id=>"2" do
104
+ x.name {
105
+ x.first "John"
106
+ x.last "Doe"
107
+ }
108
+ x.address "Columbus"
109
+ end
110
+ end
111
+ expect [:start_tag, "address-book".intern, nil]
112
+ expect [:start_tag, :entry, {:id => "1"}]
113
+ expect [:start_tag, :name, nil]
114
+ expect [:start_tag, :first, nil]
115
+ expect [:text, "Bill"]
116
+ expect [:end_tag, :first]
117
+ expect [:start_tag, :last, nil]
118
+ expect [:text, "Smith"]
119
+ expect [:end_tag, :last]
120
+ expect [:end_tag, :name]
121
+ expect [:start_tag, :address, nil]
122
+ expect [:text, "Cincinnati"]
123
+ expect [:end_tag, :address]
124
+ expect [:end_tag, :entry]
125
+ expect [:start_tag, :entry, {:id => "2"}]
126
+ expect [:start_tag, :name, nil]
127
+ expect [:start_tag, :first, nil]
128
+ expect [:text, "John"]
129
+ expect [:end_tag, :first]
130
+ expect [:start_tag, :last, nil]
131
+ expect [:text, "Doe"]
132
+ expect [:end_tag, :last]
133
+ expect [:end_tag, :name]
134
+ expect [:start_tag, :address, nil]
135
+ expect [:text, "Columbus"]
136
+ expect [:end_tag, :address]
137
+ expect [:end_tag, :entry]
138
+ expect [:end_tag, "address-book".intern]
139
+ expect_done
140
+ end
141
+
142
+ def expect(value)
143
+ assert_equal value, @target.events.shift
144
+ end
145
+
146
+ def expect_done
147
+ assert_nil @target.events.shift
148
+ end
149
+
150
+ end