rconditions 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +117 -2
- data/lib/rconditions.rb +23 -128
- metadata +11 -5
data/README
CHANGED
@@ -1,5 +1,120 @@
|
|
1
1
|
= RConditions
|
2
2
|
|
3
|
-
RConditions generates a bang method (for example, <tt>Array#empty!</tt>)
|
3
|
+
RConditions generates a bang method (for example, <tt>Array#empty!</tt>)
|
4
|
+
for each predicate method (for example, <tt>Array#empty?</tt>). The bang
|
5
|
+
method will pass if the predicate method passes, otherwise it
|
6
|
+
will throw an exception. The exception will include auto-generated modules
|
7
|
+
that give information which predicate methods passed or failed in the bang
|
8
|
+
method's execution.
|
4
9
|
|
5
|
-
|
10
|
+
== A Simple Example
|
11
|
+
|
12
|
+
require "rconditions"
|
13
|
+
|
14
|
+
begin
|
15
|
+
[1,2].empty!
|
16
|
+
rescue Array::NotEmptyError => e
|
17
|
+
p e
|
18
|
+
end
|
19
|
+
|
20
|
+
# => #<Exception: Array::NotEmptyError>
|
21
|
+
|
22
|
+
The raised exception includes a module defined on the class where the method is defined. The module's name is derived from the predicate method's name.
|
23
|
+
|
24
|
+
== A More Complicated Example
|
25
|
+
|
26
|
+
require "rconditions"
|
27
|
+
|
28
|
+
class Posting
|
29
|
+
attr_writer :spam, :active
|
30
|
+
|
31
|
+
def spam?
|
32
|
+
@spam
|
33
|
+
end
|
34
|
+
|
35
|
+
def active?
|
36
|
+
@active
|
37
|
+
end
|
38
|
+
|
39
|
+
def visible?
|
40
|
+
!spam? && active?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
class User
|
45
|
+
attr_writer :admin
|
46
|
+
|
47
|
+
def admin?
|
48
|
+
@admin
|
49
|
+
end
|
50
|
+
|
51
|
+
def can_view_posting?(posting)
|
52
|
+
admin? || posting.visible?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
user = User.new
|
57
|
+
user.admin = false
|
58
|
+
|
59
|
+
posting = Posting.new
|
60
|
+
posting.active = false
|
61
|
+
posting.spam = true
|
62
|
+
|
63
|
+
begin
|
64
|
+
user.can_view_posting!(posting)
|
65
|
+
rescue Posting::SpamError => e
|
66
|
+
p e
|
67
|
+
rescue Posting::NotActiveError
|
68
|
+
puts "should not get here"
|
69
|
+
end
|
70
|
+
|
71
|
+
# => #<Exception: User::NotAdminError, Posting::SpamError,
|
72
|
+
# Posting::NotVisibleError, User::NotCanViewPostingError>
|
73
|
+
|
74
|
+
As you can see, the exception includes modules for each of the evaluated
|
75
|
+
predicate methods: <tt>User#can_view_posting!(posting)</tt> in the context
|
76
|
+
above called <tt>User#can_view_posting?(posting)</tt>, which called
|
77
|
+
<tt>User#admin?</tt> and <tt>Posting#can_view_posting?</tt>, which called
|
78
|
+
<tt>Posting#spam?</tt>.
|
79
|
+
|
80
|
+
The results were
|
81
|
+
|
82
|
+
* <tt>User#admin? # => false</tt>
|
83
|
+
* <tt>Posting#spam? # => true</tt>
|
84
|
+
* <tt>Posting#can_view_posting? # => false</tt>
|
85
|
+
* <tt>User#can_view_posting? # => false</tt>
|
86
|
+
|
87
|
+
so the included exception modules are
|
88
|
+
|
89
|
+
* <tt>User::NotAdminError</tt>
|
90
|
+
* <tt>Posting::SpamError</tt>
|
91
|
+
* <tt>Posting::NotCanViewPostingError</tt>
|
92
|
+
* <tt>User::NotCanViewPostingError</tt>
|
93
|
+
|
94
|
+
== Performance
|
95
|
+
|
96
|
+
As almost all predicate methods are extended by default, RConditions carries
|
97
|
+
a performance penalty which varies with the number of calls to predicate
|
98
|
+
methods. A simple test setup using mongrel/rails was slowed down by 10-20%
|
99
|
+
by adding <tt>require "rconditions"</tt> to the bottom of its
|
100
|
+
<tt>enviroment.rb</tt>.
|
101
|
+
|
102
|
+
The performance penalty can be avoided by applying RConditions only to new
|
103
|
+
methods, that is, methods defined after <tt>require "rconditions"</tt>. To
|
104
|
+
achieve this, set <tt>RCONDITIONS_ONLY_FOR_NEW_METHODS = true</tt> before
|
105
|
+
the require call. Our test setup had no measurable slowdown afterwards.
|
106
|
+
|
107
|
+
== Limitations
|
108
|
+
|
109
|
+
* RConditions currently only support predicate methods starting with a letter
|
110
|
+
and containing only word characters except the question mark at the end.
|
111
|
+
* RConditions does not support singleton methods. These includes all class
|
112
|
+
methods.
|
113
|
+
|
114
|
+
== License
|
115
|
+
|
116
|
+
RConditions is released under the MIT license.
|
117
|
+
|
118
|
+
== Authors
|
119
|
+
|
120
|
+
RConditions is written by Norman Timmler and Tammo Freese.
|
data/lib/rconditions.rb
CHANGED
@@ -1,122 +1,12 @@
|
|
1
|
-
#
|
2
|
-
#
|
3
|
-
# RConditions generates a bang method (for example, <tt>Array#empty!</tt>)
|
4
|
-
# for each predicate method (for example, <tt>Array#empty?</tt>). The bang
|
5
|
-
# method will return true if the predicate method returns true, otherwise it
|
6
|
-
# will throw an exception. The exception will include auto-generated modules
|
7
|
-
# that give information which predicate methods passed or failed in the bang
|
8
|
-
# method's execution.
|
9
|
-
#
|
10
|
-
# == Example
|
11
|
-
#
|
12
|
-
# Here is a simple example. The raised exception includes a module defined
|
13
|
-
# on the class where the method is defined:
|
14
|
-
#
|
15
|
-
# require "rconditions"
|
16
|
-
#
|
17
|
-
# begin
|
18
|
-
# [1,2].empty!
|
19
|
-
# rescue Array::NotEmptyError => e
|
20
|
-
# p e
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# # => #<Exception: Array::NotEmptyError>
|
24
|
-
#
|
25
|
-
# Here is a more complicated example:
|
26
|
-
#
|
27
|
-
# require "rconditions"
|
28
|
-
#
|
29
|
-
# class Posting
|
30
|
-
# attr_writer :spam, :active
|
31
|
-
#
|
32
|
-
# def spam?
|
33
|
-
# @spam
|
34
|
-
# end
|
35
|
-
#
|
36
|
-
# def active?
|
37
|
-
# @active
|
38
|
-
# end
|
39
|
-
#
|
40
|
-
# def visible?
|
41
|
-
# !spam? && active?
|
42
|
-
# end
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# class User
|
46
|
-
# attr_writer :admin
|
47
|
-
#
|
48
|
-
# def admin?
|
49
|
-
# @admin
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# def can_view_posting?(posting)
|
53
|
-
# admin? || posting.visible?
|
54
|
-
# end
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# user = User.new
|
58
|
-
# user.admin = false
|
59
|
-
#
|
60
|
-
# posting = Posting.new
|
61
|
-
# posting.active = false
|
62
|
-
# posting.spam = true
|
63
|
-
#
|
64
|
-
# begin
|
65
|
-
# user.can_view_posting!(posting)
|
66
|
-
# rescue Posting::SpamError => e
|
67
|
-
# p e
|
68
|
-
# rescue Posting::NotActiveError
|
69
|
-
# puts "should not get here"
|
70
|
-
# end
|
71
|
-
#
|
72
|
-
# # => #<Exception: User::NotAdminError, Posting::SpamError,
|
73
|
-
# # Posting::NotVisibleError, User::NotCanViewPostingError>
|
74
|
-
#
|
75
|
-
# As you can see, the exception includes modules for each of the evaluated
|
76
|
-
# predicate methods: <tt>User#can_view_posting!(posting)</tt> in the context
|
77
|
-
# above called <tt>User#can_view_posting?(posting)</tt>, which called
|
78
|
-
# <tt>User#admin?</tt> and <tt>Posting#can_view_posting?</tt>, which called
|
79
|
-
# <tt>Posting#spam?</tt>.
|
80
|
-
#
|
81
|
-
# The results were
|
82
|
-
#
|
83
|
-
# * <tt>User#admin? # => false</tt>
|
84
|
-
# * <tt>Posting#spam? # => true</tt>
|
85
|
-
# * <tt>Posting#can_view_posting? # => false</tt>
|
86
|
-
# * <tt>User#can_view_posting? # => false</tt>
|
87
|
-
#
|
88
|
-
# so the included exception modules are
|
89
|
-
#
|
90
|
-
# * <tt>User::NotAdminError</tt>
|
91
|
-
# * <tt>Posting::SpamError</tt>
|
92
|
-
# * <tt>Posting::NotCanViewPostingError</tt>
|
93
|
-
# * <tt>User::NotCanViewPostingError</tt>
|
94
|
-
#
|
95
|
-
# == Performance
|
96
|
-
#
|
97
|
-
# As almost all predicate methods are extended by default, RConditions carries
|
98
|
-
# a performance penalty which varies with the number of calls to predicate
|
99
|
-
# methods. A simple test setup using mongrel/rails was slowed down by 10-20%
|
100
|
-
# by adding <tt>require "rconditions"</tt> to the bottom of its
|
101
|
-
# <tt>enviroment.rb</tt>.
|
102
|
-
#
|
103
|
-
# The performance penalty can be avoided by applying RConditions only to new
|
104
|
-
# methods, that is, methods defined after <tt>require "rconditions"</tt>. To
|
105
|
-
# achieve this, set <tt>RCONDITIONS_ONLY_FOR_NEW_METHODS = true</tt> before
|
106
|
-
# the require call. Our test setup had no measurable slowdown afterwards.
|
107
|
-
#
|
108
|
-
# == Known Limitations
|
109
|
-
#
|
110
|
-
# * RConditions does only support predicate methods starting with a letter and
|
111
|
-
# containing only word characters except the question mark at the end.
|
112
|
-
# * RConditions does not support singleton methods. These includes all class
|
113
|
-
# methods.
|
1
|
+
# Holds RCondition's methods. You should never call these methods
|
2
|
+
# directly, as they are automatically called.
|
114
3
|
module RConditions
|
115
4
|
class << self
|
116
5
|
|
117
|
-
# Extends
|
118
|
-
# should never call this method
|
119
|
-
#
|
6
|
+
# Extends a given predicate method and defines a bang method for it. You
|
7
|
+
# should never call this method yourself, it is called either from
|
8
|
+
# RConditions#extend_predicate_methods_and_define_bang_methods, or from
|
9
|
+
# <tt>Module#method_added</tt> which is extended by RConditions.
|
120
10
|
# * <tt>mod</tt> -- the module on which the method is defined.
|
121
11
|
# * <tt>id</tt> -- the name of the method.
|
122
12
|
def extend_predicate_method_and_define_bang_method(mod, id)
|
@@ -132,6 +22,19 @@ module RConditions
|
|
132
22
|
end
|
133
23
|
end
|
134
24
|
|
25
|
+
# Extends almost all predicate methods and defines bang methods for them.
|
26
|
+
# You should never call this method yourself, it is called automatically
|
27
|
+
# when RConditions is required. To prevent it from being called, set
|
28
|
+
# <tt>RCONDITIONS_ONLY_FOR_NEW_METHODS</tt> to <tt>true</tt> before
|
29
|
+
# requiring RConditions.
|
30
|
+
def extend_predicate_methods_and_define_bang_methods
|
31
|
+
ObjectSpace.each_object(Module) do |mod|
|
32
|
+
mod.instance_methods(false).each do |id|
|
33
|
+
RConditions.extend_predicate_method_and_define_bang_method(mod, id)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
135
38
|
def exception_modules #:nodoc:
|
136
39
|
Thread.current[:rconditions_exception_modules]
|
137
40
|
end
|
@@ -212,22 +115,14 @@ unless defined? RCONDITIONS_ONLY_FOR_NEW_METHODS
|
|
212
115
|
end
|
213
116
|
|
214
117
|
unless RCONDITIONS_ONLY_FOR_NEW_METHODS
|
215
|
-
|
216
|
-
mod.instance_methods(false).each do |id|
|
217
|
-
RConditions.extend_predicate_method_and_define_bang_method(mod, id)
|
218
|
-
end
|
219
|
-
end
|
118
|
+
RConditions.extend_predicate_methods_and_define_bang_methods
|
220
119
|
end
|
221
|
-
|
222
|
-
class Module
|
120
|
+
|
121
|
+
class Module #:nodoc:
|
223
122
|
alias_method :method_added_without_rconditions, :method_added
|
224
123
|
private :method_added_without_rconditions
|
225
124
|
|
226
|
-
|
227
|
-
# RConditions hooks into <tt>method_added</tt>. An existing
|
228
|
-
# <tt>method_added</tt> implementation will not be replaced, but executed
|
229
|
-
# afterwards.
|
230
|
-
def method_added(id)
|
125
|
+
def method_added(id) #:nodoc:
|
231
126
|
RConditions.extend_predicate_method_and_define_bang_method(self, id)
|
232
127
|
method_added_without_rconditions(id)
|
233
128
|
end
|
metadata
CHANGED
@@ -3,7 +3,7 @@ rubygems_version: 0.9.2
|
|
3
3
|
specification_version: 1
|
4
4
|
name: rconditions
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.1.
|
6
|
+
version: 0.1.1
|
7
7
|
date: 2007-09-27 00:00:00 +02:00
|
8
8
|
summary: RConditions generates a bang method (for example, Array#empty!) for each predicate method (for example, Array#empty?). The bang method will return true if the predicate method returns true, otherwise it will throw an exception. The exception will include auto-generated modules that give information on predicate methods passed or failed in the bang method's execution.
|
9
9
|
require_paths:
|
@@ -36,10 +36,16 @@ files:
|
|
36
36
|
- MIT-LICENSE
|
37
37
|
test_files:
|
38
38
|
- test/rconditions_test.rb
|
39
|
-
rdoc_options:
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
rdoc_options:
|
40
|
+
- --title
|
41
|
+
- RConditions RDoc Documentation
|
42
|
+
- --main
|
43
|
+
- README
|
44
|
+
- --charset
|
45
|
+
- utf-8
|
46
|
+
extra_rdoc_files:
|
47
|
+
- README
|
48
|
+
- MIT-LICENSE
|
43
49
|
executables: []
|
44
50
|
|
45
51
|
extensions: []
|