qualitysmith_extensions 0.0.20 → 0.0.24

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,7 +5,10 @@
5
5
  # Submit to Facets?:: Yes!
6
6
  # Developer notes::
7
7
  # * Is it thread-safe?? Probably not, as it stands...
8
- # But the whole thing that prompted me to create a guard method in the first place was to try to avoid a deadlock that was caused by recursively calling a method with a synchronize in it. So I'm not even sure if it's possible to make it thread-safe?
8
+ # But the whole thing that prompted me to create a guard method in the first place was to try to avoid a deadlock that was
9
+ # caused by recursively calling a method with a synchronize in it (in other words, someone else's attempt at thread-safety
10
+ # resulted in me getting into a deadlock, which is why I wrote this method to begin with). So I'm not even sure if it's
11
+ # possible to make it thread-safe?
9
12
  #++
10
13
 
11
14
  require 'rubygems'
@@ -16,23 +19,78 @@ require 'qualitysmith_extensions/symbol/match'
16
19
 
17
20
 
18
21
  class Module
19
- def guard_method(method_name, guard_variable)
22
+ # A guard method (by this definition anyway) is a method that sets a flag, executes a block, and then returns the flag to its
23
+ # previous value. It ensures that the flag is set during the execution of the block.
24
+ #
25
+ # In the simplest case, you'd use it like this:
26
+ # class A
27
+ # guard_method :disable_stupid_stuff!, :@stupid_stuff_disabled
28
+ # end
29
+ # a = A.new
30
+ # a.disable_stupid_stuff! do # Causes @stupid_stuff_disabled to be set to true
31
+ # # Section of code during which you don't want any stupid stuff to happen
32
+ # end # Causes @stupid_stuff_disabled to be set back to false
33
+ # # Okay, a, you can resume doing stupid stuff again...
34
+ #
35
+ # If you also want a guard method that *disables* the flag rather than *enabling* it, simply pass in the desired name of this
36
+ # "unguard" method as the value of the +unguard_method_name+ argument.
37
+ # class A
38
+ # guard_method :guard_the_fruit!, :@guarding_the_fruit, :stop_guarding_the_fruit!
39
+ # end
40
+ #
41
+ # Examples of unguard methods:
42
+ # mguard_method :color_on!, :@@color_enabled, :color_off!
43
+ # mguard_method :without_benchmarking, :@@benchmarking_disabled, :with_benchmarking
44
+ #
45
+ # These calls can be nested however you wish:
46
+ # a.guard_the_fruit! do
47
+ # a.stop_guarding_the_fruit! do
48
+ # assert_equal false, a.guarding_the_fruit?
49
+ # end
50
+ # assert_equal true, a.guarding_the_fruit?
51
+ # end
52
+ #
53
+ # You can also use the guard methods as normal flag setter/clearer methods by simply not passing a block to it. Hence
54
+ # a.guard_the_fruit!
55
+ # will simply set @guarding_the_fruit to true, and
56
+ # a.stop_guarding_the_fruit!
57
+ # will set @guarding_the_fruit to false.
58
+ #
59
+ def guard_method(guard_method_name, guard_variable, unguard_method_name = nil)
20
60
  raise ArgumentError.new("Expected an instance variable name but got #{guard_variable}") if guard_variable !~ /^@([\w_]+)$/
21
61
  guard_variable.to_s =~ /^@([\w_]+)$/ # Why didn't the regexp above set $1 ??
22
62
  class_eval do
23
63
  attr_tester $1.to_sym
24
64
  end
25
65
  module_eval <<-End, __FILE__, __LINE__+1
26
- def #{method_name}(&block)
66
+ def #{guard_method_name}(new_value = nil, &block)
27
67
  old_guard_state, #{guard_variable} = #{guard_variable}, true
28
- returning = yield
29
- #{guard_variable} = old_guard_state
30
- returning
68
+ if block_given?
69
+ returning = yield
70
+ #{guard_variable} = old_guard_state
71
+ returning
72
+ end
73
+ end
74
+ End
75
+ module_eval <<-End, __FILE__, __LINE__+1 unless unguard_method_name.nil?
76
+ def #{unguard_method_name}(new_value = nil, &block)
77
+ old_guard_state, #{guard_variable} = #{guard_variable}, false
78
+ if block_given?
79
+ returning = yield
80
+ #{guard_variable} = old_guard_state
81
+ returning
82
+ end
31
83
  end
32
84
  End
33
85
  end
34
86
 
35
- def mguard_method(method_name, guard_variable)
87
+ # See the documentation for guard_method. mguard_method does the same thing, only it creates a _class_ (or _module_) method
88
+ # rather than an instance method and it uses a _class_ (or _module_) variable rather than an instance variable to store the
89
+ # guard state.
90
+ #
91
+ # Example:
92
+ # mguard_method :guard_the_fruit!, :@@guarding_the_fruit
93
+ def mguard_method(guard_method_name, guard_variable, unguard_method_name = nil)
36
94
  raise ArgumentError.new("Expected a class variable name but got #{guard_variable}") if guard_variable !~ /^@@[\w_]+$/
37
95
  guard_variable.to_s =~ /^@@([\w_]+)$/
38
96
  class_eval do
@@ -40,11 +98,25 @@ class Module
40
98
  end
41
99
  module_eval <<-End, __FILE__, __LINE__+1
42
100
  class << self
43
- def #{method_name}(&block)
101
+ def #{guard_method_name}(new_value = nil, &block)
44
102
  old_guard_state, #{guard_variable} = #{guard_variable}, true
45
- returning = yield
46
- #{guard_variable} = old_guard_state
47
- returning
103
+ if block_given?
104
+ returning = yield
105
+ #{guard_variable} = old_guard_state
106
+ returning
107
+ end
108
+ end
109
+ end
110
+ End
111
+ module_eval <<-End, __FILE__, __LINE__+1 unless unguard_method_name.nil?
112
+ class << self
113
+ def #{unguard_method_name}(new_value = nil, &block)
114
+ old_guard_state, #{guard_variable} = #{guard_variable}, false
115
+ if block_given?
116
+ returning = yield
117
+ #{guard_variable} = old_guard_state
118
+ returning
119
+ end
48
120
  end
49
121
  end
50
122
  End
@@ -61,7 +133,7 @@ end
61
133
  =begin test
62
134
  require 'test/unit'
63
135
 
64
- class GuardMethodTest < Test::Unit::TestCase
136
+ class GuardMethodTest_Simple < Test::Unit::TestCase
65
137
  class A
66
138
  guard_method :guard_the_fruit!, :@guarding_the_fruit
67
139
  end
@@ -89,7 +161,70 @@ class GuardMethodTest < Test::Unit::TestCase
89
161
  end
90
162
  end
91
163
 
92
- class MGuardMethodTest < Test::Unit::TestCase
164
+ class GuardMethodTest_WithUnguard < Test::Unit::TestCase
165
+ class A
166
+ guard_method :guard_the_fruit!, :@guarding_the_fruit, :stop_guarding_the_fruit!
167
+ end
168
+ def test_guard_method
169
+ a = A.new
170
+ assert_equal nil, a.guarding_the_fruit?
171
+ a.guard_the_fruit! do
172
+ a.guard_the_fruit! do
173
+ assert_equal true, a.guarding_the_fruit?
174
+
175
+ a.stop_guarding_the_fruit! do
176
+ assert_equal false, a.guarding_the_fruit?
177
+ a.guard_the_fruit! do
178
+ assert_equal true, a.guarding_the_fruit?
179
+ end
180
+ assert_equal false, a.guarding_the_fruit?
181
+ end
182
+
183
+ assert_equal true, a.guarding_the_fruit?
184
+ end
185
+ assert_equal true, a.guarding_the_fruit?
186
+ end
187
+ assert_equal nil, a.guarding_the_fruit?
188
+ end
189
+
190
+ def test_guard_method_with_simple_blockless_toggles
191
+ a = A.new
192
+ assert_equal nil, a.guarding_the_fruit?
193
+ a.guard_the_fruit!
194
+ assert_equal true, a.guarding_the_fruit?
195
+
196
+ a.stop_guarding_the_fruit! do
197
+ assert_equal false, a.guarding_the_fruit?
198
+ a.guard_the_fruit! do
199
+ assert_equal true, a.guarding_the_fruit?
200
+ a.stop_guarding_the_fruit!
201
+ assert_equal false, a.guarding_the_fruit?
202
+ a.guard_the_fruit!
203
+ assert_equal true, a.guarding_the_fruit?
204
+ end
205
+ assert_equal false, a.guarding_the_fruit?
206
+ end
207
+
208
+ assert_equal true, a.guarding_the_fruit?
209
+ end
210
+
211
+ def test_return_value
212
+ assert_equal nil, A.new.guard_the_fruit!
213
+ assert_equal nil, A.new.stop_guarding_the_fruit!
214
+ assert_equal 'special return value', A.new.guard_the_fruit! { 'special return value' }
215
+ assert_equal 'special return value', A.new.stop_guarding_the_fruit! { 'special return value' }
216
+ end
217
+ end
218
+
219
+ #---------------------------------------------------------------------------------------------------------------------------------
220
+ # Begin duplication
221
+ # The following TestCases are simply duplicates of the previous except that they test mguard_method rather than guard_method
222
+ # The main differenes/substitutions:
223
+ # * @@guarding_the_fruit, rather than @guarding_the_fruit
224
+ # * :'<,'>s/A.new/B/g
225
+ # * :'<,'>s/\<a\>/B/g
226
+
227
+ class MGuardMethodTest_Simple < Test::Unit::TestCase
93
228
  class B
94
229
  mguard_method :guard_the_fruit!, :@@guarding_the_fruit
95
230
  end
@@ -114,7 +249,61 @@ class MGuardMethodTest < Test::Unit::TestCase
114
249
  def test_return_value
115
250
  assert_equal 'special return value', B.guard_the_fruit! { 'special return value' }
116
251
  end
252
+ end
253
+
254
+ class MGuardMethodTest_WithUnguard < Test::Unit::TestCase
255
+ class B
256
+ mguard_method :guard_the_fruit!, :@@guarding_the_fruit, :stop_guarding_the_fruit!
257
+ end
258
+ def test_guard_method
259
+ assert_equal nil, B.guarding_the_fruit?
260
+ B.guard_the_fruit! do
261
+ B.guard_the_fruit! do
262
+ assert_equal true, B.guarding_the_fruit?
117
263
 
264
+ B.stop_guarding_the_fruit! do
265
+ assert_equal false, B.guarding_the_fruit?
266
+ B.guard_the_fruit! do
267
+ assert_equal true, B.guarding_the_fruit?
268
+ end
269
+ assert_equal false, B.guarding_the_fruit?
270
+ end
271
+
272
+ assert_equal true, B.guarding_the_fruit?
273
+ end
274
+ assert_equal true, B.guarding_the_fruit?
275
+ end
276
+ assert_equal nil, B.guarding_the_fruit?
277
+ end
278
+
279
+ def test_guard_method_with_simple_blockless_toggles
280
+ assert_equal nil, B.guarding_the_fruit?
281
+ B.guard_the_fruit!
282
+ assert_equal true, B.guarding_the_fruit?
283
+
284
+ B.stop_guarding_the_fruit! do
285
+ assert_equal false, B.guarding_the_fruit?
286
+ B.guard_the_fruit! do
287
+ assert_equal true, B.guarding_the_fruit?
288
+ B.stop_guarding_the_fruit!
289
+ assert_equal false, B.guarding_the_fruit?
290
+ B.guard_the_fruit!
291
+ assert_equal true, B.guarding_the_fruit?
292
+ end
293
+ assert_equal false, B.guarding_the_fruit?
294
+ end
295
+
296
+ assert_equal true, B.guarding_the_fruit?
297
+ end
298
+
299
+ def test_return_value
300
+ assert_equal nil, B.guard_the_fruit!
301
+ assert_equal nil, B.stop_guarding_the_fruit!
302
+ assert_equal 'special return value', B.guard_the_fruit! { 'special return value' }
303
+ assert_equal 'special return value', B.stop_guarding_the_fruit! { 'special return value' }
304
+ end
118
305
  end
306
+ # End duplication
307
+ #---------------------------------------------------------------------------------------------------------------------------------
119
308
  =end
120
309
 
@@ -0,0 +1,6 @@
1
+ # Idea:
2
+ # Allow using hashes:
3
+ # alias_method :code_review => :view_commits
4
+ # instead of
5
+ # alias_method :code_review, :view_commits
6
+ # because I always forget which argument becomes the argument for which
@@ -0,0 +1,46 @@
1
+ # Copied from ActiveSupport because I couldn't get the ones in Facets to work...
2
+
3
+ # Extends the module object with module and instance accessors for class attributes,
4
+ # just like the native attr* accessors for instance attributes.
5
+ class Module # :nodoc:
6
+ def mattr_reader(*syms)
7
+ syms.each do |sym|
8
+ class_eval(<<-EOS, __FILE__, __LINE__+1)
9
+ unless defined? @@#{sym}
10
+ @@#{sym} = nil
11
+ end
12
+
13
+ def self.#{sym}
14
+ @@#{sym}
15
+ end
16
+
17
+ def #{sym}
18
+ @@#{sym}
19
+ end
20
+ EOS
21
+ end
22
+ end
23
+
24
+ def mattr_writer(*syms)
25
+ syms.each do |sym|
26
+ class_eval(<<-EOS, __FILE__, __LINE__+1)
27
+ unless defined? @@#{sym}
28
+ @@#{sym} = nil
29
+ end
30
+
31
+ def self.#{sym}=(obj)
32
+ @@#{sym} = obj
33
+ end
34
+
35
+ def #{sym}=(obj)
36
+ @@#{sym} = obj
37
+ end
38
+ EOS
39
+ end
40
+ end
41
+
42
+ def mattr_accessor(*syms)
43
+ mattr_reader(*syms)
44
+ mattr_writer(*syms)
45
+ end
46
+ end
@@ -0,0 +1,334 @@
1
+ #--
2
+ # Author:: Thomas Sawyer, Tyler Rick
3
+ # Copyright:: Copyright (c) Thomas Sawyer, probably, since this is a derivative work
4
+ # License:: Ruby License
5
+ # Submit to Facets?:: Yes
6
+ # Developer notes::
7
+ # * Based on /usr/lib/ruby/gems/1.8/gems/facets-1.8.54/lib/facets/core/module/attr_tester.rb
8
+ # * Hey Thomas, don't you think Module#attr_tester should only create the read-only a? method and have another method that creates the writer (like there how we have attr_reader, _writer, and _accessor?) ? "tester" does not imply "setter" in my mind...
9
+ # * I'm going to rename this one to bool_attr_accessor, which calls both bool_attr_reader and bool_attr_writer
10
+ # * Then you also have the option to use bool_attr_reader and bool_attr_writer separately if you so desire.
11
+ # * Other changes made:
12
+ # * Changed it so that if you call a!(false) it would actually set @a to false rather than leaving it unchanged. (I assume that was a bug.)
13
+ #++
14
+
15
+
16
+ class Module
17
+
18
+ # This creates two methods for each given variable name. One is used to test
19
+ # the attribute and the other is used to set or toggle it.
20
+ #
21
+ # bool_attr_accessor :a
22
+ #
23
+ # is equivalent to
24
+ #
25
+ # def a?
26
+ # @a ? true : @a
27
+ # end
28
+ #
29
+ # def a!(switch=Exception)
30
+ # if switch == Exception
31
+ # @a = !@a
32
+ # else
33
+ # @a = switch ? true : false
34
+ # self
35
+ # end
36
+ # end
37
+ #
38
+ # Examples:
39
+ # x = Klass.new
40
+ # x.a! true # sets @a to true
41
+ # x.a! # toggles @a, so that it ends up being false
42
+ # x.a! # toggles @a, so that it ends up being true
43
+ # x.a! false # sets @a to false
44
+ #
45
+ def bool_attr_accessor(*args)
46
+
47
+ make = {}
48
+ args.each { |a|
49
+ make["#{a}?".to_sym] = %{
50
+ def #{a}?(true_value=true)
51
+ @#{a} ? true_value : @#{a}
52
+ end
53
+ }
54
+ make["#{a}!".to_sym] = %{
55
+ def #{a}!(switch=Exception)
56
+ if switch == Exception
57
+ @#{a} = !@#{a}
58
+ else
59
+ @#{a} = switch ? true : false
60
+ # used to be @#{a} instead of false in Facets version
61
+ self
62
+ end
63
+ end
64
+ }
65
+ }
66
+ module_eval make.values.join("\n"), __FILE__, __LINE__
67
+
68
+ make.keys
69
+ end
70
+
71
+ end
72
+
73
+ class Module
74
+ # This creates two methods for each given variable name. One is used to test
75
+ # the attribute and the other is used to set or toggle it.
76
+ #
77
+ # bool_attr_accessor :a
78
+ #
79
+ # is equivalent to
80
+ #
81
+ # def self.a?
82
+ # @@a ? true : @@a
83
+ # end
84
+ #
85
+ # def self.a!(switch=Exception)
86
+ # if switch == Exception
87
+ # @@a = !@@a
88
+ # else
89
+ # @@a = switch ? true : false
90
+ # self
91
+ # end
92
+ # end
93
+ #
94
+ # Works for both classes and modules.
95
+ #
96
+ def mbool_attr_accessor(*args)
97
+
98
+ make = {}
99
+ args.each { |a|
100
+ # Initialize it first so that we won't have any NameErrors.
101
+ module_eval %{ @@#{a} = nil if !defined?(@@#{a}) }, __FILE__, __LINE__
102
+
103
+ make["#{a}?".to_sym] = %{
104
+ def self.#{a}?(true_value=true)
105
+ @@#{a} ? true_value : @@#{a}
106
+ end
107
+ }
108
+ make["#{a}!".to_sym] = %{
109
+ def self.#{a}!(switch=Exception)
110
+ if switch == Exception
111
+ @@#{a} = !@@#{a}
112
+ else
113
+ @@#{a} = switch ? true : false
114
+ self
115
+ end
116
+ end
117
+ }
118
+ }
119
+ module_eval make.values.join("\n"), __FILE__, __LINE__
120
+
121
+ make.keys
122
+ end
123
+ end
124
+
125
+
126
+
127
+ # _____ _
128
+ # |_ _|__ ___| |_
129
+ # | |/ _ \/ __| __|
130
+ # | | __/\__ \ |_
131
+ # |_|\___||___/\__|
132
+ #
133
+ =begin test
134
+ require 'test/unit'
135
+ require 'rubygems'
136
+ require 'qualitysmith_extensions/object/ignore_access'
137
+ require 'set'
138
+
139
+ # Test that it works for *instances*
140
+ class TestBoolAttr < Test::Unit::TestCase
141
+ def setup
142
+ @x = C.new
143
+ end
144
+
145
+ class C
146
+ bool_attr_accessor :a
147
+ end
148
+
149
+ class C_for_default_is_nil
150
+ bool_attr_accessor :a
151
+ end
152
+
153
+ def test1_default_is_nil
154
+ assert_equal nil, C_for_default_is_nil.new.a?
155
+ end
156
+
157
+ def test2_toggle
158
+ assert_equal nil, @x.a?
159
+ @x.a!
160
+ assert_equal true, @x.a?
161
+ @x.a!
162
+ assert_equal false, @x.a?
163
+ end
164
+
165
+ def test3_setter
166
+ @x.a! true
167
+ @x.a! true
168
+ assert_equal true, @x.a?
169
+
170
+ @x.a! false
171
+ assert_equal false, @x.a?
172
+ end
173
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
174
+ @x.a! "whatever"
175
+ assert_equal true, @x.a? # Still returns a boolean even though we tried to set it to a string.
176
+
177
+ @x.a! nil
178
+ assert_equal false, @x.a? # Still returns a boolean even though we tried to set it to nil.
179
+ end
180
+ end
181
+
182
+ # Test that it works for *modules*
183
+ class TestForModules < Test::Unit::TestCase
184
+
185
+ class M_for_default_is_nil
186
+ mbool_attr_accessor :a
187
+ end
188
+ def test1_default_is_nil
189
+ assert_equal nil, M_for_default_is_nil.a?
190
+ end
191
+
192
+ module M
193
+ mbool_attr_accessor :a
194
+ end
195
+ def test2_toggle
196
+ assert_equal nil, M.a?
197
+ M.a!
198
+ assert_equal true, M.a?
199
+ M.a!
200
+ assert_equal false, M.a?
201
+ end
202
+ def test3_setter
203
+ M.a! true
204
+ M.a! true
205
+ assert_equal true, M.a?
206
+
207
+ M.a! false
208
+ assert_equal false, M.a?
209
+ end
210
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
211
+ M.a! "whatever"
212
+ assert_equal true, M.a? # Still returns a boolean even though we tried to set it to a string.
213
+
214
+ M.a! nil
215
+ assert_equal false, M.a? # Still returns a boolean even though we tried to set it to nil.
216
+ end
217
+ end
218
+
219
+ # Test that it also works for *classes*
220
+ class TestForClasses < Test::Unit::TestCase
221
+
222
+ class C_for_default_is_nil
223
+ mbool_attr_accessor :a
224
+ end
225
+ def test1_default_is_nil
226
+ assert_equal nil, C_for_default_is_nil.a?
227
+ end
228
+
229
+ class C
230
+ mbool_attr_accessor :a
231
+ end
232
+
233
+ def test2_toggle
234
+ C.access.class_variable_set :@@a, false
235
+ assert_equal false, C.a? # otherwise would have been nil
236
+ C.a!
237
+ assert_equal true, C.a?
238
+ C.a!
239
+ assert_equal false, C.a?
240
+
241
+ assert_equal ["@_ignore_access_functor"], C.instance_variables
242
+ assert_equal ["@@a"], C.class_variables
243
+ end
244
+
245
+ def test3_setter
246
+ C.a! true
247
+ C.a! true
248
+ assert_equal true, C.a?
249
+
250
+ C.a! false
251
+ assert_equal false, C.a?
252
+ end
253
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
254
+ C.a! "whatever"
255
+ assert_equal true, C.a? # Still returns a boolean even though we tried to set it to a string.
256
+
257
+ C.a! nil
258
+ assert_equal false, C.a? # Still returns a boolean even though we tried to set it to nil.
259
+ end
260
+ end
261
+
262
+
263
+ # Observation: You can also the normal bool_attr_accessor in conjunction with class << self.
264
+ # The methods generated seem to *behave* in the same way. Both techniques allow you to query the class, C.a?
265
+ # The only difference is in which *variables* are use to store the state:
266
+ # * class << self and the normal bool_attr_accessor:
267
+ # Stores the state in an instance variable for the *class*: @a
268
+ # * mbool_attr_accessor:
269
+ # Stores the state in a *class* variable: @@a
270
+ #
271
+ # Can someone explain to me the difference between class variables and instance variables of a class?
272
+ # It seems silly (confusing even!) to have both of them!
273
+ #
274
+ # My best explanation is that the fact that we can even *have* instance variables of a class does *not* mean it's a good idea
275
+ # to use them. It simply means that Matz made the language with as few arbitrary restrictions as possible. He made it
276
+ # technically *possible* to do a lot of things that it is probably not good practice to do... And one of those things is
277
+ # using instance variables of classes to store state information for that class.
278
+ #
279
+ # What do you think class variables are for? Exactly that! There's a *reason* we have both @a and @@a variables -- to
280
+ # *differentiate* between the two kinds of variables and keep programmers sane. So please don't blur the distinction and
281
+ # use the @a-type variable to do the job that @@a-type variables are for.
282
+ #
283
+ # Or am I missing something here?
284
+ #
285
+ class TestWith_class_self_and_plain_bool_attr_accessor < Test::Unit::TestCase
286
+
287
+ class C_for_default_is_nil
288
+ class << self
289
+ bool_attr_accessor :a
290
+ end
291
+ end
292
+ def test1_default_is_nil
293
+ assert_equal nil, C_for_default_is_nil.a?
294
+ end
295
+
296
+ class C
297
+ class << self
298
+ bool_attr_accessor :a
299
+ end
300
+ end
301
+ # This is where I spotted a class that uses this technique:
302
+ # * Test::Unit::Assertions::AssertionMessage
303
+
304
+ def test_2_toggle
305
+ assert_equal false, C.a? # Why isn't it nil like it is for the instance use case of bool_attr_accessor?
306
+ C.a!
307
+ assert_equal true, C.a?
308
+ C.a!
309
+ assert_equal false, C.a?
310
+
311
+ assert_equal ["@a"], C.instance_variables
312
+ assert_equal [], C.new.instance_variables # @a is an instance variable of the *class* *not* objects of the class -- weird!
313
+ assert_equal [], C.class_variables
314
+ end
315
+
316
+ def test3_setter
317
+ C.a! true
318
+ C.a! true
319
+ assert_equal true, C.a?
320
+
321
+ C.a! false
322
+ assert_equal false, C.a?
323
+ end
324
+ def test4_sets_to_boolean_even_if_try_to_set_to_other_type
325
+ C.a! "whatever"
326
+ assert_equal true, C.a? # Still returns a boolean even though we tried to set it to a string.
327
+
328
+ C.a! nil
329
+ assert_equal false, C.a? # Still returns a boolean even though we tried to set it to nil.
330
+ end
331
+
332
+ end
333
+ =end
334
+
@@ -0,0 +1,9 @@
1
+ #create_setter/constructor :_F, :filename
2
+ #create_setter/constructor :initialize, :filename do
3
+ # extra constructor stuff
4
+ #end
5
+ #
6
+ # def _F(filename)
7
+ # @filename = filename
8
+ # end
9
+ #