blockenspiel 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.rdoc CHANGED
@@ -1,3 +1,11 @@
1
+ === 0.2.2 / 2009-10-28
2
+
3
+ * Support for gemcutter hosting in the build/release scripts.
4
+ * Some clarifications to constant scopes internal in the code.
5
+ * A few documentation updates.
6
+ * Minor changes to the Implementing DSL Blocks paper to deal with
7
+ Why's disappearance.
8
+
1
9
  === 0.2.1 / 2009-04-16
2
10
 
3
11
  * Now compatible with Ruby 1.9.
@@ -1,9 +1,13 @@
1
1
  == Implementing DSL Blocks
2
2
 
3
- by Daniel Azuma, 29 October 2008
3
+ by Daniel Azuma
4
4
 
5
5
  A <em>DSL block</em> is a construct commonly used in Ruby APIs, in which a DSL (domain-specific language) is made available inside a block passed to an API call. In this paper I present an overview of different implementation strategies for this important pattern. I will first describe the features of DSL blocks, utilizing illustrations from several well-known Ruby libraries. I will then survey and critique five implementation strategies that have been put forth. Finally, I will present a new library, {Blockenspiel}[http://virtuoso.rubyforge.org/blockenspiel], designed to be a comprehensive implementation of DSL blocks.
6
6
 
7
+ Originally written on 29 October 2008.
8
+
9
+ Minor modifications on 28 October 2009 to deal with Why's disappearance.
10
+
7
11
  === An illustrative overview of DSL blocks
8
12
 
9
13
  If you've done much Ruby programming, chances are you've run into mini-DSLs (domain-specific languages) that live inside blocks. Perhaps you've encountered them in Ruby standard library calls, such as <tt>File#open</tt>, a call that lets you interact with a stream while performing automatic setup and cleanup for you:
@@ -27,7 +31,7 @@ Perhaps you've used the XML {builder}[http://builder.rubyforge.org/] library, wh
27
31
  end
28
32
  end
29
33
 
30
- The {Markaby}[http://code.whytheluckystiff.net/markaby/] library also uses nested blocks to generate html, but is able to do so more succinctly without requiring you to explicitly reference a builder object:
34
+ The {Markaby}[http://github.com/markaby/markaby] library also uses nested blocks to generate html, but is able to do so more succinctly without requiring you to explicitly reference a builder object:
31
35
 
32
36
  Markaby::Builder.new.html do
33
37
  head { title "Boats.com" }
@@ -366,11 +370,13 @@ The problem gets worse. Changing +self+ affects not only how methods are looked
366
370
 
367
371
  What happened? If we recall, <tt>@set</tt> is used by the +Mapper+ object to point back to the routing +RouteSet+. It is how the proxy knows what it is proxying for. But since we've used <tt>instance_eval</tt>, we now have free access to the +Mapper+ object's internal instance variables, including the ability to clobber them. And that's precisely what we did here. Furthermore, maybe we were actually expecting to access our own <tt>@set</tt> variable, and we haven't done that. Any instance variables from the caller's closure are in fact no longer accessible inside the block.
368
372
 
373
+ Similarly, if you are using Ruby 1.9, constants are also looked up using +self+ as the starting point. So by changing +self+, <tt>instance_eval</tt> affects the availability of constants in surprising ways.
374
+
369
375
  The problem gets even worse. If we think about the cryptic error message we got when we tried to use our +makeurl+ helper method, we begin to realize that we've run into the method lookup ambiguity discussed in the previous section. If +self+ has changed inside the block, and we tried to call +makeurl+, we might expect a +NoMethodError+ to be raised for +makeurl+ on the +Mapper+ class, rather than for "<tt>[]</tt>" on the +Symbol+ class. However, things change when we recall that Rails's routing DSL supports named routes. You do not have to call the specific +connect+ method to create a route. In fact, you can call _any_ method name. Any name is a valid DSL method name. It is thus ambiguous, when we invoke +makeurl+, whether we mean our helper method or a named route called "makeurl". Rails assumed we meant the named route, but in fact that isn't what we had intended.
370
376
 
371
- This all sounds pretty bad. Do we give up on <tt>instance_eval</tt>? Some members of the Ruby community have, and indeed the technique has generally fallen out of favor in many major libraries. Jim Weirich, for instance, {originally}[http://onestepback.org/index.cgi/Tech/Ruby/BuilderObjects.rdoc] utilized <tt>instance_eval</tt> in the XML Builder library illustrated earlier, but later deprecated and removed it because of its surprising behavior. Why's {Markaby}[http://code.whytheluckystiff.net/markaby/] still uses <tt>instance_eval</tt> but includes a caveat in the {documentation}[http://markaby.rubyforge.org/] explaining the issues and recommending caution.
377
+ This all sounds pretty bad. Do we give up on <tt>instance_eval</tt>? Some members of the Ruby community have, and indeed the technique has generally fallen out of favor in many major libraries. Jim Weirich, for instance, {originally}[http://onestepback.org/index.cgi/Tech/Ruby/BuilderObjects.rdoc] utilized <tt>instance_eval</tt> in the XML Builder library illustrated earlier, but later deprecated and removed it because of its surprising behavior. Why's {Markaby}[http://github.com/markaby/markaby] still uses <tt>instance_eval</tt> but includes a caveat in the {documentation}[http://markaby.rubyforge.org/] explaining the issues and recommending caution.
372
378
 
373
- There are, however, a few specific cases when <tt>instance_eval</tt> may be uniquely appropriate. RSpec's DSL is intended as a class-constructive language: it constructs ruby classes behind the scenes. In the RSpec example at the beginning of this paper, you may notice the use of the <tt>@stack</tt> instance variable. In fact, this is intended as an instance variable of the RSpec test story being written, and as such, <tt>instance_eval</tt> is required because of the kind of language that RSpec wants to use. But in more common cases, such as specifying configuration, <tt>instance_eval</tt> does not give us the most desirable behavior. The general consensus now, expressed for example in recent articles from {Why}[http://hackety.org/2008/10/06/mixingOurWayOutOfInstanceEval.html] and {Ola Bini}[http://olabini.com/blog/2008/09/dont-overuse-instance_eval-and-instance_exec/], is that it should be avoided.
379
+ There are, however, a few specific cases when <tt>instance_eval</tt> may be uniquely appropriate. RSpec's DSL is intended as a class-constructive language: it constructs ruby classes behind the scenes. In the RSpec example at the beginning of this paper, you may notice the use of the <tt>@stack</tt> instance variable. In fact, this is intended as an instance variable of the RSpec test story being written, and as such, <tt>instance_eval</tt> is required because of the kind of language that RSpec wants to use. But in more common cases, such as specifying configuration, <tt>instance_eval</tt> does not give us the most desirable behavior. The general consensus now, expressed for example in recent articles from Why (no longer available) and {Ola Bini}[http://olabini.com/blog/2008/09/dont-overuse-instance_eval-and-instance_exec/], is that it should be avoided.
374
380
 
375
381
  So does this mean we're stuck with block parameters for better or worse? Not quite. Several alternatives have been proposed recently, and we'll take a look at them in the next few sections. But first, let's summarize the discussion of <tt>instance_eval</tt>.
376
382
 
@@ -630,7 +636,7 @@ Let us summarize Gray's arity detection technique, and then proceed to an intere
630
636
 
631
637
  === Implementation strategy 5: mixins
632
638
 
633
- One of the most interesting entries into the DSL blocks discussion was proposed by Why The Lucky Stiff in his {blog}[http://hackety.org/2008/10/06/mixingOurWayOutOfInstanceEval.html]. Why observes that the problem with <tt>instance_eval</tt> is that it does too much. Most DSL blocks merely want to be able to intercept and respond to certain method calls, whereas <tt>instance_eval</tt> actually changes +self+, which has the additional side effects of blocking access to other methods and instance variables, and breaking encapsulation. A better solution, he maintains, is not to change +self+, but instead temporarily to add the DSL's methods to the block's context for the duration of the block. That is, instead of having the DSL proxy object delegate back to the block's context object, do the opposite: cause the block's context object to delegate to the DSL proxy object.
639
+ One of the most interesting entries into the DSL blocks discussion was proposed by Why The Lucky Stiff in his blog. Unfortunately, with Why's disappearance, the original article is no longer available, but we can summarize its contents here. Why observes that the problem with <tt>instance_eval</tt> is that it does too much. Most DSL blocks merely want to be able to intercept and respond to certain method calls, whereas <tt>instance_eval</tt> actually changes +self+, which has the additional side effects of blocking access to other methods and instance variables, and breaking encapsulation. A better solution, he maintains, is not to change +self+, but instead temporarily to add the DSL's methods to the block's context for the duration of the block. That is, instead of having the DSL proxy object delegate back to the block's context object, do the opposite: cause the block's context object to delegate to the DSL proxy object.
634
640
 
635
641
  Implementing this is actually harder than it sounds. We need to take the block context object, dynamically add methods to it before calling the block, and then dynamically remove them afterward. We already know how to get the block context object, but adding and removing methods requires some more Ruby metaprogramming wizardry. And now we're stretching our toolbox to the breaking point.
636
642
 
@@ -669,7 +675,7 @@ What we would really like is a way to add methods to just one object temporarily
669
675
  s1.foo # prints "foo called"
670
676
  s2.foo # NameError: s2 is unchanged
671
677
 
672
- Unfortunately, there is no way to remove the module from the object. Ruby has no "unextend" capability. This omission led Why to implement it himself as a Ruby language extension called {Mixico}[http://github.com/why/mixico/tree/master]. The name comes from the library's ability to add and remove "mixins" at will. A similar library exists as a gem called {Mixology}[http://www.somethingnimble.com/bliki/mixology]. The two libraries use different APIs but perform the same basic function. For the discussion below, I will assume Mixico is installed. However, the library I describe in the next section uses a custom implementation that is compatible with MRI 1.9 and JRuby.
678
+ Unfortunately, there is no way to remove the module from the object. Ruby has no "unextend" capability. This omission led Why to implement it himself as a Ruby language extension called {Mixico}[http://github.com/rkh/mixico]. The name comes from the library's ability to add and remove "mixins" at will. A similar library exists as a gem called {Mixology}[http://www.somethingnimble.com/bliki/mixology]. The two libraries use different APIs but perform the same basic function. For the discussion below, I will assume Mixico is installed. However, the library I describe in the next section uses a custom implementation that is compatible with MRI 1.9 and JRuby.
673
679
 
674
680
  Using Mixico, we can now write the +draw+ method like this:
675
681
 
@@ -923,12 +929,12 @@ The Blockenspiel library provides a concrete and robust implementation of DSL bl
923
929
 
924
930
  {Jim Weirich}[http://onestepback.org/], <em>{ruby-core:19153}[http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/19153]</em>, 2008.10.07
925
931
 
926
- {Why The Lucky Stiff}[http://whytheluckystiff.net/], <em>{Markaby}[http://code.whytheluckystiff.net/markaby/]</em> (Ruby library), 2006.
932
+ {Why The Lucky Stiff}[http://en.wikipedia.org/wiki/Why_the_lucky_stiff], <em>{Markaby}[http://github.com/markaby/markaby]</em> (Ruby library), 2006.
927
933
 
928
- {Why The Lucky Stiff}[http://whytheluckystiff.net/], <em>{Mixico}[http://github.com/why/mixico/tree/master]</em> (Ruby library), 2008.
934
+ {Why The Lucky Stiff}[http://en.wikipedia.org/wiki/Why_the_lucky_stiff], <em>{Mixico}[http://github.com/rkh/mixico]</em> (Ruby library), 2008.
929
935
 
930
- {Why The Lucky Stiff}[http://whytheluckystiff.net/], <em>{Mixing Our Way Out Of Instance Eval?}[http://hackety.org/2008/10/06/mixingOurWayOutOfInstanceEval.html]</em>, 2008.10.06.
936
+ {Why The Lucky Stiff}[http://en.wikipedia.org/wiki/Why_the_lucky_stiff], <em>Mixing Our Way Out Of Instance Eval?</em> (no longer online), 2008.10.06.
931
937
 
932
938
  === About the author
933
939
 
934
- Daniel Azuma is Chief Software Architect at Zoodango. He has been working with Ruby for about three years, and finds the language generally pleasant to work with, though he thinks the scoping rules could use some improvement. His home page is at http://www.daniel-azuma.com/
940
+ Daniel Azuma is Chief Software Architect at GeoPage. He has been working with Ruby for about three years, and finds the language generally pleasant to work with, though he thinks the scoping rules could use some improvement. His home page is at http://www.daniel-azuma.com/
data/README.rdoc CHANGED
@@ -284,8 +284,7 @@ concurrently.
284
284
 
285
285
  === Requirements
286
286
 
287
- * Ruby 1.8.7 or later, or JRuby 1.2 or later. Ruby 1.9 compatible.
288
- * Rubygems
287
+ * Ruby 1.8.6 or later (1.8.7 recommended), Ruby 1.9.1 or later, or JRuby 1.2 or later (1.4 recommended).
289
288
 
290
289
  === Installation
291
290
 
@@ -298,11 +297,11 @@ concurrently.
298
297
 
299
298
  === Development and support
300
299
 
301
- Documentation is available at http://virtuoso.rubyforge.org/blockenspiel
300
+ Documentation is available at http://virtuoso.rubyforge.org/blockenspiel/README_rdoc.html
302
301
 
303
- Source code is hosted by Github at http://github.com/dazuma/blockenspiel/tree
302
+ Source code is hosted on Github at http://github.com/dazuma/blockenspiel
304
303
 
305
- Report bugs on RubyForge at http://rubyforge.org/projects/virtuoso
304
+ Report bugs on Github issues at http://github.org/dazuma/blockenspiel/issues
306
305
 
307
306
  Contact the author at dazuma at gmail dot com.
308
307
 
@@ -310,13 +309,13 @@ Contact the author at dazuma at gmail dot com.
310
309
 
311
310
  Blockenspiel is written by Daniel Azuma (http://www.daniel-azuma.com/).
312
311
 
313
- The mixin implementation is based on a concept by Why The Lucky Stiff.
314
- See his 6 October 2008 blog posting,
315
- <em>{Mixing Our Way Out Of Instance Eval?}[http://hackety.org/2008/10/06/mixingOurWayOutOfInstanceEval.html]</em>
316
- for further discussion.
312
+ The mixin implementation is based on a concept by the late Why The Lucky
313
+ Stiff, documented in his 6 October 2008 blog posting entitled "Mixing Our
314
+ Way Out Of Instance Eval?". The original link is gone, but you may find
315
+ copies or mirrors out there.
317
316
 
318
317
  The unmixer code is based on {Mixology}[http://rubyforge.org/projects/mixology],
319
- by Patrick Farley, anonymous z, Dan Manges, and Clint Bishop.
318
+ version 0.1 by Patrick Farley, anonymous z, Dan Manges, and Clint Bishop.
320
319
  The code has been stripped down and modified to support MRI 1.9 and JRuby 1.2.
321
320
 
322
321
  === License
data/Rakefile CHANGED
@@ -39,7 +39,7 @@ require 'rake/testtask'
39
39
  require 'rake/rdoctask'
40
40
  require 'rdoc/generator/darkfish'
41
41
 
42
- require File.expand_path("#{File.dirname(__FILE__)}/lib/blockenspiel/version")
42
+ require ::File.expand_path("#{::File.dirname(__FILE__)}/lib/blockenspiel/version")
43
43
 
44
44
 
45
45
  # Configuration
@@ -47,7 +47,7 @@ extra_rdoc_files_ = ['README.rdoc', 'History.rdoc', 'ImplementingDSLblocks.rdoc'
47
47
 
48
48
 
49
49
  # Default task
50
- task :default => [:clean, :compile, :rdoc, :test]
50
+ task :default => [:clean, :compile, :rdoc, :package, :test]
51
51
 
52
52
 
53
53
  # Clean task
@@ -55,54 +55,54 @@ CLEAN.include(['ext/blockenspiel/Makefile', '**/unmixer.bundle', 'ext/blockenspi
55
55
 
56
56
 
57
57
  # Test task
58
- Rake::TestTask.new('test') do |task_|
58
+ ::Rake::TestTask.new('test') do |task_|
59
59
  task_.pattern = 'tests/tc_*.rb'
60
60
  end
61
61
 
62
62
 
63
63
  # RDoc task
64
- Rake::RDocTask.new do |task_|
64
+ ::Rake::RDocTask.new do |task_|
65
65
  task_.main = 'README.rdoc'
66
66
  task_.rdoc_files.include(*extra_rdoc_files_)
67
67
  task_.rdoc_files.include('lib/blockenspiel/*.rb')
68
68
  task_.rdoc_dir = 'doc'
69
- task_.title = "Blockenspiel #{Blockenspiel::VERSION_STRING} documentation"
69
+ task_.title = "Blockenspiel #{::Blockenspiel::VERSION_STRING} documentation"
70
70
  task_.options << '-f' << 'darkfish'
71
71
  end
72
72
 
73
73
 
74
74
  # Gem task
75
- gemspec_ = Gem::Specification.new do |s_|
75
+ gemspec_ = ::Gem::Specification.new do |s_|
76
76
  s_.name = 'blockenspiel'
77
77
  s_.summary = 'Blockenspiel is a helper library designed to make it easy to implement DSL blocks.'
78
- s_.version = Blockenspiel::VERSION_STRING
78
+ s_.version = ::Blockenspiel::VERSION_STRING
79
79
  s_.author = 'Daniel Azuma'
80
80
  s_.email = 'dazuma@gmail.com'
81
81
  s_.description = 'Blockenspiel is a helper library designed to make it easy to implement DSL blocks. It is designed to be comprehensive and robust, supporting most common usage patterns, and working correctly in the presence of nested blocks and multithreading.'
82
82
  s_.homepage = 'http://virtuoso.rubyforge.org/blockenspiel'
83
83
  s_.rubyforge_project = 'virtuoso'
84
84
  s_.required_ruby_version = '>= 1.8.6'
85
- s_.files = FileList['ext/**/*.{c,rb,java}', 'lib/**/*.{rb,jar}', 'tests/**/*.rb', '*.rdoc', 'Rakefile'].to_a
85
+ s_.files = ::FileList['ext/**/*.{c,rb,java}', 'lib/**/*.{rb,jar}', 'tests/**/*.rb', '*.rdoc', 'Rakefile'].to_a
86
86
  s_.extra_rdoc_files = extra_rdoc_files_
87
87
  s_.has_rdoc = true
88
88
  s_.test_files = FileList['tests/tc_*.rb']
89
- if RUBY_PLATFORM =~ /java/
89
+ if ::RUBY_PLATFORM =~ /java/
90
90
  s_.platform = 'java'
91
91
  s_.files += ['lib/blockenspiel_unmixer.jar']
92
92
  else
93
- s_.platform = Gem::Platform::RUBY
93
+ s_.platform = ::Gem::Platform::RUBY
94
94
  s_.extensions = ['ext/blockenspiel/extconf.rb']
95
95
  end
96
96
  end
97
97
  task :package => [:compile]
98
- Rake::GemPackageTask.new(gemspec_) do |task_|
98
+ ::Rake::GemPackageTask.new(gemspec_) do |task_|
99
99
  task_.need_zip = false
100
- task_.need_tar = RUBY_PLATFORM !~ /java/
100
+ task_.need_tar = ::RUBY_PLATFORM !~ /java/
101
101
  end
102
102
 
103
103
 
104
104
  # General build task
105
- task :compile => RUBY_PLATFORM =~ /java/ ? [:compile_java] : [:compile_c]
105
+ task :compile => ::RUBY_PLATFORM =~ /java/ ? [:compile_java] : [:compile_c]
106
106
 
107
107
 
108
108
  # Build tasks for MRI
@@ -112,13 +112,13 @@ desc 'Builds the extension'
112
112
  task :compile_c => ["lib/blockenspiel/unmixer.#{dlext_}"]
113
113
 
114
114
  file 'ext/blockenspiel/Makefile' => ['ext/blockenspiel/extconf.rb'] do
115
- Dir.chdir('ext/blockenspiel') do
115
+ ::Dir.chdir('ext/blockenspiel') do
116
116
  ruby 'extconf.rb'
117
117
  end
118
118
  end
119
119
 
120
120
  file "ext/blockenspiel/unmixer.#{dlext_}" => ['ext/blockenspiel/Makefile', 'ext/blockenspiel/unmixer.c'] do
121
- Dir.chdir('ext/blockenspiel') do
121
+ ::Dir.chdir('ext/blockenspiel') do
122
122
  sh 'make'
123
123
  end
124
124
  end
@@ -131,7 +131,7 @@ end
131
131
  # Build tasks for JRuby
132
132
  desc "Compiles the JRuby extension"
133
133
  task :compile_java do
134
- Dir.chdir('ext/blockenspiel') do
134
+ ::Dir.chdir('ext/blockenspiel') do
135
135
  sh 'javac -source 1.5 -target 1.5 -classpath $JRUBY_HOME/lib/jruby.jar BlockenspielUnmixerService.java'
136
136
  sh 'jar cf blockenspiel_unmixer.jar BlockenspielUnmixerService.class'
137
137
  cp 'blockenspiel_unmixer.jar', '../../lib/blockenspiel_unmixer.jar'
@@ -141,53 +141,69 @@ end
141
141
 
142
142
  # Publish RDocs
143
143
  desc 'Publishes RDocs to RubyForge'
144
- task :publish_rdoc => [:rerdoc] do
145
- config_ = YAML.load(File.read(File.expand_path("~/.rubyforge/user-config.yml")))
144
+ task :publish_rdoc_to_rubyforge => [:rerdoc] do
145
+ config_ = ::YAML.load(::File.read(::File.expand_path("~/.rubyforge/user-config.yml")))
146
146
  username_ = config_['username']
147
147
  sh "rsync -av --delete doc/ #{username_}@rubyforge.org:/var/www/gforge-projects/virtuoso/blockenspiel"
148
148
  end
149
149
 
150
150
 
151
151
  # Publish gem
152
- task :publish_gem do |t_|
153
- v_ = ENV["VERSION"]
152
+ task :release_gem_to_rubyforge do |t_|
153
+ v_ = ::ENV["VERSION"]
154
154
  abort "Must supply VERSION=x.y.z" unless v_
155
- if v_ != Blockenspiel::VERSION_STRING
156
- abort "Versions don't match: #{v_} vs #{Blockenspiel::VERSION_STRING}"
155
+ if v_ != ::Blockenspiel::VERSION_STRING
156
+ abort "Versions don't match: #{v_} vs #{::Blockenspiel::VERSION_STRING}"
157
157
  end
158
158
  mri_pkg_ = "pkg/blockenspiel-#{v_}.gem"
159
159
  jruby_pkg_ = "pkg/blockenspiel-#{v_}-java.gem"
160
160
  tgz_pkg_ = "pkg/blockenspiel-#{v_}.tgz"
161
- if !File.file?(mri_pkg_) || !File.readable?(mri_pkg_)
161
+ if !::File.file?(mri_pkg_) || !::File.readable?(mri_pkg_)
162
162
  abort "You haven't built #{mri_pkg_} yet. Try rake package"
163
163
  end
164
- if !File.file?(jruby_pkg_) || !File.readable?(jruby_pkg_)
164
+ if !::File.file?(jruby_pkg_) || !::File.readable?(jruby_pkg_)
165
165
  abort "You haven't built #{jruby_pkg_} yet. Try jrake package"
166
166
  end
167
- if !File.file?(tgz_pkg_) || !File.readable?(tgz_pkg_)
167
+ if !::File.file?(tgz_pkg_) || !::File.readable?(tgz_pkg_)
168
168
  abort "You haven't built #{tgz_pkg_} yet. Try rake package"
169
169
  end
170
- release_notes_ = File.read("README.rdoc").split(/^(==.*)/)[2].strip
171
- release_changes_ = File.read("History.rdoc").split(/^(===.*)/)[1..2].join.strip
170
+ release_notes_ = ::File.read("README.rdoc").split(/^(==.*)/)[2].strip
171
+ release_changes_ = ::File.read("History.rdoc").split(/^(===.*)/)[1..2].join.strip
172
172
 
173
173
  require 'rubyforge'
174
- rf_ = RubyForge.new.configure
174
+ rf_ = ::RubyForge.new.configure
175
175
  puts "Logging in to RubyForge"
176
176
  rf_.login
177
177
  config_ = rf_.userconfig
178
178
  config_["release_notes"] = release_notes_
179
179
  config_["release_changes"] = release_changes_
180
180
  config_["preformatted"] = true
181
- puts "Releasing blockenspiel #{v_}"
181
+ puts "Releasing blockenspiel #{v_} to RubyForge"
182
182
  rf_.add_release('virtuoso', 'blockenspiel', v_, mri_pkg_, jruby_pkg_, tgz_pkg_)
183
183
  end
184
184
 
185
185
 
186
+ # Publish gem
187
+ task :release_gem_to_gemcutter => [:package] do |t_|
188
+ v_ = ::ENV["VERSION"]
189
+ abort "Must supply VERSION=x.y.z" unless v_
190
+ if v_ != ::Blockenspiel::VERSION_STRING
191
+ abort "Versions don't match: #{v_} vs #{::Blockenspiel::VERSION_STRING}"
192
+ end
193
+ puts "Releasing blockenspiel #{v_} to GemCutter"
194
+ `cd pkg && gem push blockenspiel-#{v_}.gem`
195
+ end
196
+
197
+
198
+ # Publish everything
199
+ task :release => [:release_gem_to_gemcutter, :release_gem_to_rubyforge, :publish_rdoc_to_rubyforge]
200
+
201
+
186
202
  # Custom task that takes the implementing dsl blocks paper
187
203
  # and converts it from RDoc format to Markdown
188
204
  task :idslb_markdown do
189
- File.open('ImplementingDSLblocks.txt') do |read_|
190
- File.open('idslb_markdown.txt', 'w') do |write_|
205
+ ::File.open('ImplementingDSLblocks.txt') do |read_|
206
+ ::File.open('idslb_markdown.txt', 'w') do |write_|
191
207
  linenum_ = 0
192
208
  read_.each do |line_|
193
209
  linenum_ += 1
data/lib/blockenspiel.rb CHANGED
@@ -34,7 +34,7 @@
34
34
  ;
35
35
 
36
36
 
37
- if RUBY_PLATFORM =~ /java/
37
+ if ::RUBY_PLATFORM =~ /java/
38
38
  require "blockenspiel_unmixer"
39
39
  else
40
40
  require "#{File.dirname(__FILE__)}/blockenspiel/unmixer"
@@ -47,7 +47,7 @@ module Blockenspiel
47
47
 
48
48
  # Base exception for all exceptions raised by Blockenspiel
49
49
 
50
- class BlockenspielError < RuntimeError
50
+ class BlockenspielError < ::RuntimeError
51
51
  end
52
52
 
53
53
 
@@ -55,14 +55,14 @@ module Blockenspiel
55
55
  # <tt>:mixin</tt> parameterless behavior with a target that does not have
56
56
  # the DSL module included. It is an error made by the DSL implementor.
57
57
 
58
- class DSLMissingError < BlockenspielError
58
+ class DSLMissingError < ::Blockenspiel::BlockenspielError
59
59
  end
60
60
 
61
61
 
62
62
  # This exception is raised when the block provided does not take the
63
63
  # expected number of parameters. It is an error made by the caller.
64
64
 
65
- class BlockParameterError < BlockenspielError
65
+ class BlockParameterError < ::Blockenspiel::BlockenspielError
66
66
  end
67
67
 
68
68
 
@@ -90,7 +90,7 @@ module Blockenspiel
90
90
  unless klass_.instance_variable_defined?(:@_blockenspiel_module)
91
91
  _setup_class(klass_)
92
92
  def klass_.inherited(subklass_)
93
- Blockenspiel::DSLSetupMethods._setup_class(subklass_)
93
+ ::Blockenspiel::DSLSetupMethods._setup_class(subklass_)
94
94
  super
95
95
  end
96
96
  end
@@ -105,7 +105,7 @@ module Blockenspiel
105
105
  def self._setup_class(klass_) # :nodoc:
106
106
  superclass_ = klass_.superclass
107
107
  superclass_ = nil unless superclass_.respond_to?(:_get_blockenspiel_module)
108
- mod_ = Module.new
108
+ mod_ = ::Module.new
109
109
  if superclass_
110
110
  mod_.module_eval do
111
111
  include superclass_._get_blockenspiel_module
@@ -113,7 +113,7 @@ module Blockenspiel
113
113
  end
114
114
  klass_.instance_variable_set(:@_blockenspiel_superclass, superclass_)
115
115
  klass_.instance_variable_set(:@_blockenspiel_module, mod_)
116
- klass_.instance_variable_set(:@_blockenspiel_methods, Hash.new)
116
+ klass_.instance_variable_set(:@_blockenspiel_methods, ::Hash.new)
117
117
  klass_.instance_variable_set(:@_blockenspiel_active, nil)
118
118
  end
119
119
 
@@ -177,8 +177,8 @@ module Blockenspiel
177
177
  unless @_blockenspiel_module.public_method_defined?(name_)
178
178
  @_blockenspiel_module.module_eval("
179
179
  def #{name_}(*params_, &block_)
180
- val_ = Blockenspiel._target_dispatch(self, :#{name_}, params_, block_)
181
- val_ == Blockenspiel::TARGET_MISMATCH ? super(*params_, &block_) : val_
180
+ val_ = ::Blockenspiel._target_dispatch(self, :#{name_}, params_, block_)
181
+ val_ == ::Blockenspiel::TARGET_MISMATCH ? super(*params_, &block_) : val_
182
182
  end
183
183
  ")
184
184
  end
@@ -218,7 +218,7 @@ module Blockenspiel
218
218
  elsif names_ == [false]
219
219
  @_blockenspiel_active = false
220
220
  else
221
- if names_.last.kind_of?(Hash)
221
+ if names_.last.kind_of?(::Hash)
222
222
  names_.pop.each do |name_, delegate_|
223
223
  dsl_method(name_, delegate_)
224
224
  end
@@ -245,7 +245,7 @@ module Blockenspiel
245
245
  module DSL
246
246
 
247
247
  def self.included(klass_) # :nodoc:
248
- klass_.extend(Blockenspiel::DSLSetupMethods)
248
+ klass_.extend(::Blockenspiel::DSLSetupMethods)
249
249
  end
250
250
 
251
251
  end
@@ -264,7 +264,7 @@ module Blockenspiel
264
264
 
265
265
  class Base
266
266
 
267
- include Blockenspiel::DSL
267
+ include ::Blockenspiel::DSL
268
268
 
269
269
  end
270
270
 
@@ -277,7 +277,7 @@ module Blockenspiel
277
277
  class ProxyDelegator # :nodoc:
278
278
 
279
279
  def method_missing(symbol_, *params_, &block_)
280
- Blockenspiel._proxy_dispatch(self, symbol_, params_, block_)
280
+ ::Blockenspiel._proxy_dispatch(self, symbol_, params_, block_)
281
281
  end
282
282
 
283
283
  end
@@ -291,7 +291,7 @@ module Blockenspiel
291
291
 
292
292
  class Builder
293
293
 
294
- include Blockenspiel::DSL
294
+ include ::Blockenspiel::DSL
295
295
 
296
296
 
297
297
  # This is a base class for dynamically constructed targets.
@@ -299,13 +299,13 @@ module Blockenspiel
299
299
 
300
300
  class Target # :nodoc:
301
301
 
302
- include Blockenspiel::DSL
302
+ include ::Blockenspiel::DSL
303
303
 
304
304
 
305
305
  # Add a method specification to the subclass.
306
306
 
307
307
  def self._add_methodinfo(name_, block_, yields_)
308
- (@_blockenspiel_methodinfo ||= Hash.new)[name_] = [block_, yields_]
308
+ (@_blockenspiel_methodinfo ||= ::Hash.new)[name_] = [block_, yields_]
309
309
  module_eval("
310
310
  def #{name_}(*params_, &block_)
311
311
  self.class._invoke_methodinfo(:#{name_}, params_, block_)
@@ -333,7 +333,7 @@ module Blockenspiel
333
333
  # Sets up the dynamic target class.
334
334
 
335
335
  def initialize # :nodoc:
336
- @target_class = Class.new(Blockenspiel::Builder::Target)
336
+ @target_class = ::Class.new(::Blockenspiel::Builder::Target)
337
337
  @target_class.dsl_methods(false)
338
338
  end
339
339
 
@@ -402,13 +402,13 @@ module Blockenspiel
402
402
 
403
403
 
404
404
  # :stopdoc:
405
- TARGET_MISMATCH = Object.new
405
+ TARGET_MISMATCH = ::Object.new
406
406
  # :startdoc:
407
407
 
408
- @_target_stacks = Hash.new
409
- @_mixin_counts = Hash.new
410
- @_proxy_delegators = Hash.new
411
- @_mutex = Mutex.new
408
+ @_target_stacks = ::Hash.new
409
+ @_mixin_counts = ::Hash.new
410
+ @_proxy_delegators = ::Hash.new
411
+ @_mutex = ::Mutex.new
412
412
 
413
413
 
414
414
  # === Invoke a given block.
@@ -471,7 +471,7 @@ module Blockenspiel
471
471
  # add_method(:set_foo) do |value|
472
472
  # my_foo = value
473
473
  # end
474
- # add_method(:set_things_from_block, :receive_block => true) do |value,blk|
474
+ # add_method(:set_things_from_block, :block => :last) do |value,blk|
475
475
  # my_foo = value
476
476
  # my_bar = blk.call
477
477
  # end
@@ -513,7 +513,7 @@ module Blockenspiel
513
513
  def self.invoke(block_, target_=nil, opts_={}, &builder_block_)
514
514
 
515
515
  unless block_
516
- raise ArgumentError, "Block expected"
516
+ raise ::ArgumentError, "Block expected"
517
517
  end
518
518
  parameter_ = opts_[:parameter]
519
519
  parameterless_ = opts_[:parameterless]
@@ -521,7 +521,7 @@ module Blockenspiel
521
521
  # Handle no-target behavior
522
522
  if parameter_ == false && parameterless_ == false
523
523
  if block_.arity != 0 && block_.arity != -1
524
- raise Blockenspiel::BlockParameterError, "Block should not take parameters"
524
+ raise ::Blockenspiel::BlockParameterError, "Block should not take parameters"
525
525
  end
526
526
  return block_.call
527
527
  end
@@ -529,7 +529,7 @@ module Blockenspiel
529
529
  # Perform dynamic target generation if requested
530
530
  if builder_block_
531
531
  opts_ = target_ || opts_
532
- builder_ = Blockenspiel::Builder.new
532
+ builder_ = ::Blockenspiel::Builder.new
533
533
  invoke(builder_block_, builder_)
534
534
  target_ = builder_._create_target
535
535
  end
@@ -537,14 +537,14 @@ module Blockenspiel
537
537
  # Handle parametered block case
538
538
  if parameter_ != false && block_.arity == 1 || parameterless_ == false
539
539
  if block_.arity != 1
540
- raise Blockenspiel::BlockParameterError, "Block should take exactly one parameter"
540
+ raise ::Blockenspiel::BlockParameterError, "Block should take exactly one parameter"
541
541
  end
542
542
  return block_.call(target_)
543
543
  end
544
544
 
545
545
  # Check arity for parameterless case
546
546
  if block_.arity != 0 && block_.arity != -1
547
- raise Blockenspiel::BlockParameterError, "Block should not take parameters"
547
+ raise ::Blockenspiel::BlockParameterError, "Block should not take parameters"
548
548
  end
549
549
 
550
550
  # Handle instance-eval behavior
@@ -555,22 +555,22 @@ module Blockenspiel
555
555
  # Get the module of dsl methods
556
556
  mod_ = target_.class._get_blockenspiel_module rescue nil
557
557
  unless mod_
558
- raise Blockenspiel::DSLMissingError
558
+ raise ::Blockenspiel::DSLMissingError
559
559
  end
560
560
 
561
561
  # Get the block's calling context object
562
- object_ = Kernel.eval('self', block_.binding)
562
+ object_ = ::Kernel.eval('self', block_.binding)
563
563
 
564
564
  # Handle proxy behavior
565
565
  if parameterless_ == :proxy
566
566
 
567
567
  # Create proxy object
568
- proxy_ = Blockenspiel::ProxyDelegator.new
568
+ proxy_ = ::Blockenspiel::ProxyDelegator.new
569
569
  proxy_.extend(mod_)
570
570
 
571
571
  # Store the target and proxy object so dispatchers can get them
572
572
  proxy_delegator_key_ = proxy_.object_id
573
- target_stack_key_ = [Thread.current.object_id, proxy_.object_id]
573
+ target_stack_key_ = [::Thread.current.object_id, proxy_.object_id]
574
574
  @_proxy_delegators[proxy_delegator_key_] = object_
575
575
  @_target_stacks[target_stack_key_] = [target_]
576
576
 
@@ -593,11 +593,11 @@ module Blockenspiel
593
593
 
594
594
  # Create hash keys
595
595
  mixin_count_key_ = [object_.object_id, mod_.object_id]
596
- target_stack_key_ = [Thread.current.object_id, object_.object_id]
596
+ target_stack_key_ = [::Thread.current.object_id, object_.object_id]
597
597
 
598
598
  # Store the target for inheriting.
599
599
  # We maintain a target call stack per thread.
600
- target_stack_ = @_target_stacks[target_stack_key_] ||= Array.new
600
+ target_stack_ = @_target_stacks[target_stack_key_] ||= ::Array.new
601
601
  target_stack_.push(target_)
602
602
 
603
603
  # Mix this module into the object, if required.
@@ -629,7 +629,7 @@ module Blockenspiel
629
629
  count_ = @_mixin_counts[mixin_count_key_]
630
630
  if count_ == 1
631
631
  @_mixin_counts.delete(mixin_count_key_)
632
- Blockenspiel::Unmixer.unmix(object_, mod_)
632
+ ::Blockenspiel::Unmixer.unmix(object_, mod_)
633
633
  else
634
634
  @_mixin_counts[mixin_count_key_] = count_ - 1
635
635
  end
@@ -646,8 +646,8 @@ module Blockenspiel
646
646
  # If we can't find an appropriate method to call, return the special value TARGET_MISMATCH.
647
647
 
648
648
  def self._target_dispatch(object_, name_, params_, block_) # :nodoc:
649
- target_stack_ = @_target_stacks[[Thread.current.object_id, object_.object_id]]
650
- return Blockenspiel::TARGET_MISMATCH unless target_stack_
649
+ target_stack_ = @_target_stacks[[::Thread.current.object_id, object_.object_id]]
650
+ return ::Blockenspiel::TARGET_MISMATCH unless target_stack_
651
651
  target_stack_.reverse_each do |target_|
652
652
  target_class_ = target_.class
653
653
  delegate_ = target_class_._get_blockenspiel_delegate(name_)
@@ -655,7 +655,7 @@ module Blockenspiel
655
655
  return target_.send(delegate_, *params_, &block_)
656
656
  end
657
657
  end
658
- return Blockenspiel::TARGET_MISMATCH
658
+ return ::Blockenspiel::TARGET_MISMATCH
659
659
  end
660
660
 
661
661
 
@@ -36,7 +36,7 @@
36
36
 
37
37
  module Blockenspiel
38
38
 
39
- # Current gem version
40
- VERSION_STRING = '0.2.1'.freeze
39
+ # Current gem version, as a frozen string.
40
+ VERSION_STRING = '0.2.2'.freeze
41
41
 
42
42
  end
Binary file
data/tests/tc_basic.rb CHANGED
@@ -37,19 +37,19 @@
37
37
 
38
38
 
39
39
  require 'test/unit'
40
- require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
40
+ require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/blockenspiel.rb")
41
41
 
42
42
 
43
43
  module Blockenspiel
44
44
  module Tests # :nodoc:
45
45
 
46
- class TestBasic < Test::Unit::TestCase # :nodoc:
46
+ class TestBasic < ::Test::Unit::TestCase # :nodoc:
47
47
 
48
48
 
49
- class SimpleTarget < Blockenspiel::Base
49
+ class SimpleTarget < ::Blockenspiel::Base
50
50
 
51
51
  def initialize
52
- @hash = Hash.new
52
+ @hash = ::Hash.new
53
53
  end
54
54
 
55
55
  def set_value(key_, value_)
@@ -81,7 +81,7 @@ module Blockenspiel
81
81
  assert(!self.respond_to?(:set_value_by_block))
82
82
  end
83
83
  target_ = SimpleTarget.new
84
- Blockenspiel.invoke(block_, target_)
84
+ ::Blockenspiel.invoke(block_, target_)
85
85
  assert_equal(1, target_.get_value(:a))
86
86
  assert_equal(2, target_.get_value(:b))
87
87
  end
@@ -99,7 +99,7 @@ module Blockenspiel
99
99
  set_value_by_block(:b){ 2 }
100
100
  end
101
101
  target_ = SimpleTarget.new
102
- Blockenspiel.invoke(block_, target_)
102
+ ::Blockenspiel.invoke(block_, target_)
103
103
  assert(!self.respond_to?(:set_value))
104
104
  assert(!self.respond_to?(:set_value_by_block))
105
105
  assert_equal(1, target_.get_value(:a))
@@ -117,8 +117,8 @@ module Blockenspiel
117
117
  set_value(:a, 1)
118
118
  set_value_by_block(:b){ 2 }
119
119
  end
120
- hash_ = Hash.new
121
- Blockenspiel.invoke(block_) do
120
+ hash_ = ::Hash.new
121
+ ::Blockenspiel.invoke(block_) do
122
122
  add_method(:set_value) do |key_, value_|
123
123
  hash_[key_] = value_
124
124
  end
@@ -37,16 +37,16 @@
37
37
 
38
38
 
39
39
  require 'test/unit'
40
- require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
40
+ require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/blockenspiel.rb")
41
41
 
42
42
 
43
43
  module Blockenspiel
44
44
  module Tests # :nodoc:
45
45
 
46
- class TextBehaviors < Test::Unit::TestCase # :nodoc:
46
+ class TextBehaviors < ::Test::Unit::TestCase # :nodoc:
47
47
 
48
48
 
49
- class Target1 < Blockenspiel::Base
49
+ class Target1 < ::Blockenspiel::Base
50
50
 
51
51
  dsl_methods false
52
52
 
@@ -86,19 +86,19 @@ module Blockenspiel
86
86
  # * Asserts that the caller's helper methods are not available.
87
87
 
88
88
  def test_instance_eval_behavior
89
- hash_ = Hash.new
89
+ hash_ = ::Hash.new
90
90
  context_self_ = self
91
91
  @my_instance_variable_test = :hello
92
92
  block_ = proc do
93
93
  set_value1('a', 1)
94
94
  set_value2('b'){ 2 }
95
95
  set_value3('c', 3)
96
- context_self_.assert_raise(NoMethodError){ set_value3_dslversion('d', 4) }
97
- context_self_.assert_raise(NoMethodError){ helper_method() }
96
+ context_self_.assert_raise(::NoMethodError){ set_value3_dslversion('d', 4) }
97
+ context_self_.assert_raise(::NoMethodError){ helper_method() }
98
98
  context_self_.assert(!instance_variable_defined?(:@my_instance_variable_test))
99
- context_self_.assert_instance_of(Blockenspiel::Tests::TextBehaviors::Target1, self)
99
+ context_self_.assert_instance_of(::Blockenspiel::Tests::TextBehaviors::Target1, self)
100
100
  end
101
- Blockenspiel.invoke(block_, Target1.new(hash_), :parameterless => :instance)
101
+ ::Blockenspiel.invoke(block_, Target1.new(hash_), :parameterless => :instance)
102
102
  assert_equal(1, hash_['a1'])
103
103
  assert_equal(2, hash_['b2'])
104
104
  assert_equal(3, hash_['c3'])
@@ -113,20 +113,20 @@ module Blockenspiel
113
113
  # * Asserts that the caller's helper methods *are* available.
114
114
 
115
115
  def test_proxy_behavior
116
- hash_ = Hash.new
116
+ hash_ = ::Hash.new
117
117
  context_self_ = self
118
118
  @my_instance_variable_test = :hello
119
119
  block_ = proc do
120
120
  set_value1('a', 1)
121
121
  set_value2('b'){ 2 }
122
122
  set_value3_dslversion('c', 3)
123
- context_self_.assert_raise(NoMethodError){ set_value3('d', 4) }
123
+ context_self_.assert_raise(::NoMethodError){ set_value3('d', 4) }
124
124
  context_self_.assert(helper_method())
125
125
  context_self_.assert(!instance_variable_defined?(:@my_instance_variable_test))
126
- context_self_.assert(!self.kind_of?(Blockenspiel::Tests::TextBehaviors::Target1))
126
+ context_self_.assert(!self.kind_of?(::Blockenspiel::Tests::TextBehaviors::Target1))
127
127
  context_self_.assert_not_equal(context_self_, self)
128
128
  end
129
- Blockenspiel.invoke(block_, Target1.new(hash_), :parameterless => :proxy)
129
+ ::Blockenspiel.invoke(block_, Target1.new(hash_), :parameterless => :proxy)
130
130
  assert_equal(1, hash_['a1'])
131
131
  assert_equal(2, hash_['b2'])
132
132
  assert_equal(3, hash_['c3'])
@@ -139,7 +139,7 @@ module Blockenspiel
139
139
  # * Asserts that sending a one-parameter block still works.
140
140
 
141
141
  def test_disable_parameterless
142
- hash_ = Hash.new
142
+ hash_ = ::Hash.new
143
143
  block1_ = proc do ||
144
144
  set_value1('a', 1)
145
145
  end
@@ -149,12 +149,12 @@ module Blockenspiel
149
149
  block3_ = proc do
150
150
  set_value1('c', 3)
151
151
  end
152
- assert_raise(Blockenspiel::BlockParameterError) do
153
- Blockenspiel.invoke(block1_, Target1.new(hash_), :parameterless => false)
152
+ assert_raise(::Blockenspiel::BlockParameterError) do
153
+ ::Blockenspiel.invoke(block1_, Target1.new(hash_), :parameterless => false)
154
154
  end
155
- Blockenspiel.invoke(block2_, Target1.new(hash_), :parameterless => false)
156
- assert_raise(Blockenspiel::BlockParameterError) do
157
- Blockenspiel.invoke(block3_, Target1.new(hash_), :parameterless => false)
155
+ ::Blockenspiel.invoke(block2_, Target1.new(hash_), :parameterless => false)
156
+ assert_raise(::Blockenspiel::BlockParameterError) do
157
+ ::Blockenspiel.invoke(block3_, Target1.new(hash_), :parameterless => false)
158
158
  end
159
159
  assert_equal(2, hash_['b1'])
160
160
  end
@@ -166,7 +166,7 @@ module Blockenspiel
166
166
  # * Asserts that sending a no-parameter block still works.
167
167
 
168
168
  def test_disable_parametered
169
- hash_ = Hash.new
169
+ hash_ = ::Hash.new
170
170
  block1_ = proc do ||
171
171
  set_value1('a', 1)
172
172
  end
@@ -176,11 +176,11 @@ module Blockenspiel
176
176
  block3_ = proc do
177
177
  set_value1('c', 3)
178
178
  end
179
- Blockenspiel.invoke(block1_, Target1.new(hash_), :parameter => false)
180
- assert_raise(Blockenspiel::BlockParameterError) do
181
- Blockenspiel.invoke(block2_, Target1.new(hash_), :parameter => false)
179
+ ::Blockenspiel.invoke(block1_, Target1.new(hash_), :parameter => false)
180
+ assert_raise(::Blockenspiel::BlockParameterError) do
181
+ ::Blockenspiel.invoke(block2_, Target1.new(hash_), :parameter => false)
182
182
  end
183
- Blockenspiel.invoke(block3_, Target1.new(hash_), :parameter => false)
183
+ ::Blockenspiel.invoke(block3_, Target1.new(hash_), :parameter => false)
184
184
  assert_equal(1, hash_['a1'])
185
185
  assert_equal(3, hash_['c1'])
186
186
  end
@@ -37,16 +37,16 @@
37
37
 
38
38
 
39
39
  require 'test/unit'
40
- require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
40
+ require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/blockenspiel.rb")
41
41
 
42
42
 
43
43
  module Blockenspiel
44
44
  module Tests # :nodoc:
45
45
 
46
- class TestDSLMethods < Test::Unit::TestCase # :nodoc:
46
+ class TestDSLMethods < ::Test::Unit::TestCase # :nodoc:
47
47
 
48
48
 
49
- class Target1 < Blockenspiel::Base
49
+ class Target1 < ::Blockenspiel::Base
50
50
 
51
51
  def initialize(hash_)
52
52
  @hash = hash_
@@ -67,7 +67,7 @@ module Blockenspiel
67
67
  end
68
68
 
69
69
 
70
- class Target2 < Blockenspiel::Base
70
+ class Target2 < ::Blockenspiel::Base
71
71
 
72
72
  def initialize(hash_)
73
73
  @hash = hash_
@@ -92,7 +92,7 @@ module Blockenspiel
92
92
  end
93
93
 
94
94
 
95
- class Target3 < Blockenspiel::Base
95
+ class Target3 < ::Blockenspiel::Base
96
96
 
97
97
  def initialize(hash_)
98
98
  @hash = hash_
@@ -114,7 +114,7 @@ module Blockenspiel
114
114
  end
115
115
 
116
116
 
117
- class Target4 < Blockenspiel::Base
117
+ class Target4 < ::Blockenspiel::Base
118
118
 
119
119
  def initialize(hash_)
120
120
  @hash = hash_
@@ -134,7 +134,7 @@ module Blockenspiel
134
134
  end
135
135
 
136
136
 
137
- class Target5a < Blockenspiel::Base
137
+ class Target5a < ::Blockenspiel::Base
138
138
 
139
139
  def initialize(hash_)
140
140
  @hash = hash_
@@ -176,7 +176,7 @@ module Blockenspiel
176
176
  end
177
177
 
178
178
 
179
- class Target6 < Blockenspiel::Base
179
+ class Target6 < ::Blockenspiel::Base
180
180
 
181
181
  def initialize(hash_)
182
182
  @hash = hash_
@@ -202,13 +202,13 @@ module Blockenspiel
202
202
  # * Asserts the right dsl methods are added for the default setting.
203
203
 
204
204
  def test_default_setting
205
- hash_ = Hash.new
205
+ hash_ = ::Hash.new
206
206
  block_ = proc do
207
207
  set_value1('a', 1)
208
208
  set_value2('b'){ 2 }
209
- assert_raise(NoMethodError){ _set_value3('c', 3) }
209
+ assert_raise(::NoMethodError){ _set_value3('c', 3) }
210
210
  end
211
- Blockenspiel.invoke(block_, Target1.new(hash_))
211
+ ::Blockenspiel.invoke(block_, Target1.new(hash_))
212
212
  assert_equal(1, hash_['a1'])
213
213
  assert_equal(2, hash_['b2'])
214
214
  assert_nil(hash_['c3'])
@@ -222,13 +222,13 @@ module Blockenspiel
222
222
  # * Asserts that underscore methods are added in dsl_methods true mode.
223
223
 
224
224
  def test_onoff_switching
225
- hash_ = Hash.new
225
+ hash_ = ::Hash.new
226
226
  block_ = proc do
227
- assert_raise(NoMethodError){ _set_value1('a', 1) }
227
+ assert_raise(::NoMethodError){ _set_value1('a', 1) }
228
228
  set_value2('b'){ 2 }
229
229
  _set_value3('c', 3)
230
230
  end
231
- Blockenspiel.invoke(block_, Target2.new(hash_))
231
+ ::Blockenspiel.invoke(block_, Target2.new(hash_))
232
232
  assert_nil(hash_['a1'])
233
233
  assert_equal(2, hash_['b2'])
234
234
  assert_equal(3, hash_['c3'])
@@ -241,14 +241,14 @@ module Blockenspiel
241
241
  # * Asserts that adding an explicit dsl method with a different name works.
242
242
 
243
243
  def test_explicit_add
244
- hash_ = Hash.new
244
+ hash_ = ::Hash.new
245
245
  block_ = proc do
246
246
  set_value1('a', 1)
247
- assert_raise(NoMethodError){ set_value2('b'){ 2 } }
247
+ assert_raise(::NoMethodError){ set_value2('b'){ 2 } }
248
248
  renamed_set_value2('c'){ 3 }
249
249
  another_set_value2('d'){ 4 }
250
250
  end
251
- Blockenspiel.invoke(block_, Target3.new(hash_))
251
+ ::Blockenspiel.invoke(block_, Target3.new(hash_))
252
252
  assert_equal(1, hash_['a1'])
253
253
  assert_nil(hash_['b2'])
254
254
  assert_equal(3, hash_['c2'])
@@ -262,13 +262,13 @@ module Blockenspiel
262
262
  # * Asserts that re-adding a removed method with a different name works.
263
263
 
264
264
  def test_explicit_removing
265
- hash_ = Hash.new
265
+ hash_ = ::Hash.new
266
266
  block_ = proc do
267
- assert_raise(NoMethodError){ set_value1('a', 1) }
268
- assert_raise(NoMethodError){ set_value2('b'){ 2 } }
267
+ assert_raise(::NoMethodError){ set_value1('a', 1) }
268
+ assert_raise(::NoMethodError){ set_value2('b'){ 2 } }
269
269
  renamed_set_value2('c'){ 3 }
270
270
  end
271
- Blockenspiel.invoke(block_, Target4.new(hash_))
271
+ ::Blockenspiel.invoke(block_, Target4.new(hash_))
272
272
  assert_nil(hash_['a1'])
273
273
  assert_nil(hash_['b2'])
274
274
  assert_equal(3, hash_['c2'])
@@ -281,16 +281,16 @@ module Blockenspiel
281
281
  # * Asserts that method overriding is done correctly.
282
282
 
283
283
  def test_subclassing
284
- hash_ = Hash.new
284
+ hash_ = ::Hash.new
285
285
  block_ = proc do
286
286
  set_value1('a', 1)
287
287
  set_value2('b'){ 2 }
288
- assert_raise(NoMethodError){ set_value3('c', 3) }
289
- assert_raise(NoMethodError){ set_value4('d', 4) }
288
+ assert_raise(::NoMethodError){ set_value3('c', 3) }
289
+ assert_raise(::NoMethodError){ set_value4('d', 4) }
290
290
  renamed_set_value4('e', 5)
291
291
  set_value5('f', 6)
292
292
  end
293
- Blockenspiel.invoke(block_, Target5b.new(hash_))
293
+ ::Blockenspiel.invoke(block_, Target5b.new(hash_))
294
294
  assert_equal(1, hash_['a1sub'])
295
295
  assert_equal(2, hash_['b2'])
296
296
  assert_nil(hash_['c3'])
@@ -306,13 +306,13 @@ module Blockenspiel
306
306
  # * Asserts that combined array and hash parameters works.
307
307
 
308
308
  def test_multiple_dsl_methods
309
- hash_ = Hash.new
309
+ hash_ = ::Hash.new
310
310
  block_ = proc do
311
311
  set_value1('a', 1)
312
312
  renamed_set_value2('b'){ 2 }
313
- assert_raise(NoMethodError){ set_value2('c', 3) }
313
+ assert_raise(::NoMethodError){ set_value2('c', 3) }
314
314
  end
315
- Blockenspiel.invoke(block_, Target6.new(hash_))
315
+ ::Blockenspiel.invoke(block_, Target6.new(hash_))
316
316
  assert_equal(1, hash_['a1'])
317
317
  assert_equal(2, hash_['b2'])
318
318
  end
data/tests/tc_dynamic.rb CHANGED
@@ -37,13 +37,13 @@
37
37
 
38
38
 
39
39
  require 'test/unit'
40
- require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
40
+ require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/blockenspiel.rb")
41
41
 
42
42
 
43
43
  module Blockenspiel
44
44
  module Tests # :nodoc:
45
45
 
46
- class TestDynamic < Test::Unit::TestCase # :nodoc:
46
+ class TestDynamic < ::Test::Unit::TestCase # :nodoc:
47
47
 
48
48
 
49
49
  # Test the simple case.
@@ -54,8 +54,8 @@ module Blockenspiel
54
54
  block_ = proc do
55
55
  set_value(:a, 1)
56
56
  end
57
- hash_ = Hash.new
58
- Blockenspiel.invoke(block_) do
57
+ hash_ = ::Hash.new
58
+ ::Blockenspiel.invoke(block_) do
59
59
  add_method(:set_value) do |key_, value_|
60
60
  hash_[key_] = value_
61
61
  end
@@ -70,7 +70,7 @@ module Blockenspiel
70
70
  # * Asserts that the method appears in its original name in a parametered block.
71
71
 
72
72
  def test_renaming
73
- hash_ = Hash.new
73
+ hash_ = ::Hash.new
74
74
  dsl_definition_ = proc do
75
75
  add_method(:set_value, :dsl_method => :renamed_set_value) do |key_, value_|
76
76
  hash_[key_] = value_
@@ -78,14 +78,14 @@ module Blockenspiel
78
78
  end
79
79
  block1_ = proc do
80
80
  renamed_set_value(:a, 1)
81
- assert_raise(NoMethodError){ set_value(:b, 2) }
81
+ assert_raise(::NoMethodError){ set_value(:b, 2) }
82
82
  end
83
- Blockenspiel.invoke(block1_, &dsl_definition_)
83
+ ::Blockenspiel.invoke(block1_, &dsl_definition_)
84
84
  block2_ = proc do |dsl_|
85
85
  dsl_.set_value(:c, 3)
86
- assert_raise(NoMethodError){ renamed_set_value(:d, 4) }
86
+ assert_raise(::NoMethodError){ renamed_set_value(:d, 4) }
87
87
  end
88
- Blockenspiel.invoke(block2_, &dsl_definition_)
88
+ ::Blockenspiel.invoke(block2_, &dsl_definition_)
89
89
  assert_equal(1, hash_[:a])
90
90
  assert_nil(hash_[:b])
91
91
  assert_equal(3, hash_[:c])
@@ -100,7 +100,7 @@ module Blockenspiel
100
100
  # * Asserts that a block passed "last" works.
101
101
 
102
102
  def test_blocks_first_and_last
103
- hash_ = Hash.new
103
+ hash_ = ::Hash.new
104
104
  dsl_definition_ = proc do
105
105
  add_method(:set_value1, :block => :first) do |bl_, key_|
106
106
  hash_[key_] = bl_.call
@@ -117,7 +117,7 @@ module Blockenspiel
117
117
  set_value2(:b){ 2 }
118
118
  set_value2(:c){ 3 }
119
119
  end
120
- Blockenspiel.invoke(block_, &dsl_definition_)
120
+ ::Blockenspiel.invoke(block_, &dsl_definition_)
121
121
  assert_equal(1, hash_[:a])
122
122
  assert_equal(2, hash_[:b])
123
123
  assert_equal(3, hash_[:c])
@@ -129,7 +129,7 @@ module Blockenspiel
129
129
  # * Asserts that if a block isn't given, it is set to nil.
130
130
 
131
131
  def test_blocks_nil
132
- hash_ = Hash.new
132
+ hash_ = ::Hash.new
133
133
  dsl_definition_ = proc do
134
134
  add_method(:set_value1, :block => :first) do |bl_, key_|
135
135
  assert_nil(bl_)
@@ -142,7 +142,7 @@ module Blockenspiel
142
142
  set_value1(:a)
143
143
  set_value2(:b)
144
144
  end
145
- Blockenspiel.invoke(block_, &dsl_definition_)
145
+ ::Blockenspiel.invoke(block_, &dsl_definition_)
146
146
  assert_nil(hash_[:a])
147
147
  assert_nil(hash_[:b])
148
148
  end
@@ -155,7 +155,7 @@ module Blockenspiel
155
155
  # * Asserts that a block passed "last" works.
156
156
 
157
157
  def test_blocks_legacy
158
- hash_ = Hash.new
158
+ hash_ = ::Hash.new
159
159
  dsl_definition_ = proc do
160
160
  add_method(:set_value, :receive_block => true) do |key_, bl_|
161
161
  hash_[key_] = bl_.call
@@ -164,7 +164,7 @@ module Blockenspiel
164
164
  block_ = proc do
165
165
  set_value(:a){ 1 }
166
166
  end
167
- Blockenspiel.invoke(block_, &dsl_definition_)
167
+ ::Blockenspiel.invoke(block_, &dsl_definition_)
168
168
  assert_equal(1, hash_[:a])
169
169
  end
170
170
 
data/tests/tc_mixins.rb CHANGED
@@ -38,16 +38,16 @@
38
38
 
39
39
 
40
40
  require 'test/unit'
41
- require File.expand_path("#{File.dirname(__FILE__)}/../lib/blockenspiel.rb")
41
+ require ::File.expand_path("#{::File.dirname(__FILE__)}/../lib/blockenspiel.rb")
42
42
 
43
43
 
44
44
  module Blockenspiel
45
45
  module Tests # :nodoc:
46
46
 
47
- class TestMixins < Test::Unit::TestCase # :nodoc:
47
+ class TestMixins < ::Test::Unit::TestCase # :nodoc:
48
48
 
49
49
 
50
- class Target1 < Blockenspiel::Base
50
+ class Target1 < ::Blockenspiel::Base
51
51
 
52
52
  def initialize(hash_)
53
53
  @hash = hash_
@@ -64,12 +64,12 @@ module Blockenspiel
64
64
  end
65
65
 
66
66
 
67
- class Target2 < Blockenspiel::Base
67
+ class Target2 < ::Blockenspiel::Base
68
68
 
69
69
  dsl_methods false
70
70
 
71
71
  def initialize(hash_=nil)
72
- @hash = hash_ || Hash.new
72
+ @hash = hash_ || ::Hash.new
73
73
  end
74
74
 
75
75
  def set_value(key_, value_)
@@ -92,7 +92,7 @@ module Blockenspiel
92
92
  # * Asserts that self doesn't change, and instance variables are preserved.
93
93
 
94
94
  def test_basic_mixin
95
- hash_ = Hash.new
95
+ hash_ = ::Hash.new
96
96
  saved_object_id_ = self.object_id
97
97
  @my_instance_variable_test = :hello
98
98
  assert(!self.respond_to?(:set_value))
@@ -103,7 +103,7 @@ module Blockenspiel
103
103
  assert_equal(:hello, @my_instance_variable_test)
104
104
  assert_equal(saved_object_id_, self.object_id)
105
105
  end
106
- Blockenspiel.invoke(block_, Target1.new(hash_))
106
+ ::Blockenspiel.invoke(block_, Target1.new(hash_))
107
107
  assert(!self.respond_to?(:set_value))
108
108
  assert(!self.respond_to?(:set_value2))
109
109
  assert_equal(1, hash_['a1'])
@@ -117,7 +117,7 @@ module Blockenspiel
117
117
  # * Asserts that the methods properly delegate to the target object.
118
118
 
119
119
  def test_mixin_with_renaming
120
- hash_ = Hash.new
120
+ hash_ = ::Hash.new
121
121
  assert(!self.respond_to?(:set_value))
122
122
  assert(!self.respond_to?(:set_value2))
123
123
  assert(!self.respond_to?(:set_value2_inmixin))
@@ -126,7 +126,7 @@ module Blockenspiel
126
126
  set_value2_inmixin('b'){ 2 }
127
127
  assert(!self.respond_to?(:set_value2))
128
128
  end
129
- Blockenspiel.invoke(block_, Target2.new(hash_))
129
+ ::Blockenspiel.invoke(block_, Target2.new(hash_))
130
130
  assert(!self.respond_to?(:set_value))
131
131
  assert(!self.respond_to?(:set_value2))
132
132
  assert(!self.respond_to?(:set_value2_inmixin))
@@ -142,15 +142,15 @@ module Blockenspiel
142
142
  # multiple mixins add the same method name
143
143
 
144
144
  def test_nested_different
145
- hash_ = Hash.new
145
+ hash_ = ::Hash.new
146
146
  assert(!self.respond_to?(:set_value))
147
147
  assert(!self.respond_to?(:set_value2))
148
148
  assert(!self.respond_to?(:set_value2_inmixin))
149
- Blockenspiel.invoke(proc do
149
+ ::Blockenspiel.invoke(proc do
150
150
  set_value('a', 1)
151
151
  set_value2('b'){ 2 }
152
152
  assert(!self.respond_to?(:set_value2_inmixin))
153
- Blockenspiel.invoke(proc do
153
+ ::Blockenspiel.invoke(proc do
154
154
  set_value('c', 1)
155
155
  set_value2_inmixin('d'){ 2 }
156
156
  end, Target2.new(hash_))
@@ -175,14 +175,14 @@ module Blockenspiel
175
175
  # * Asserts that the methods are added and removed at the right time.
176
176
 
177
177
  def test_nested_same
178
- hash_ = Hash.new
178
+ hash_ = ::Hash.new
179
179
  assert(!self.respond_to?(:set_value))
180
180
  assert(!self.respond_to?(:set_value2))
181
181
  assert(!self.respond_to?(:set_value2_inmixin))
182
- Blockenspiel.invoke(proc do
182
+ ::Blockenspiel.invoke(proc do
183
183
  set_value('a', 1)
184
184
  set_value2_inmixin('b'){ 2 }
185
- Blockenspiel.invoke(proc do
185
+ ::Blockenspiel.invoke(proc do
186
186
  set_value('c', 1)
187
187
  set_value2_inmixin('d'){ 2 }
188
188
  assert(!self.respond_to?(:set_value2))
@@ -207,7 +207,7 @@ module Blockenspiel
207
207
  # * Asserts that the mixin is removed only after the second thread is done.
208
208
 
209
209
  def test_threads_same_mixin
210
- hash_ = Hash.new
210
+ hash_ = ::Hash.new
211
211
  block1_ = proc do
212
212
  set_value('a', 1)
213
213
  sleep(0.5)
@@ -219,11 +219,11 @@ module Blockenspiel
219
219
  set_value2('d'){ 4 }
220
220
  end
221
221
  target_ = Target1.new(hash_)
222
- thread1_ = Thread.new do
223
- Blockenspiel.invoke(block1_, target_)
222
+ thread1_ = ::Thread.new do
223
+ ::Blockenspiel.invoke(block1_, target_)
224
224
  end
225
- thread2_ = Thread.new do
226
- Blockenspiel.invoke(block2_, target_)
225
+ thread2_ = ::Thread.new do
226
+ ::Blockenspiel.invoke(block2_, target_)
227
227
  end
228
228
  thread1_.join
229
229
  thread2_.join
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: blockenspiel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Azuma
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-04-16 00:00:00 -07:00
12
+ date: 2009-10-28 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
 
@@ -64,7 +64,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
64
64
  requirements: []
65
65
 
66
66
  rubyforge_project: virtuoso
67
- rubygems_version: 1.3.2
67
+ rubygems_version: 1.3.5
68
68
  signing_key:
69
69
  specification_version: 3
70
70
  summary: Blockenspiel is a helper library designed to make it easy to implement DSL blocks.