Module: Agio::Flags::ClassMethods
- Defined in:
- lib/agio/flags.rb
Overview
Meta-programming methods to help create flags and accessor and test methods for those flags.
Instance Method Summary collapse
-
#array_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with arrays.
-
#boolean_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with Boolean (
trueorfalse) values. -
#flag_builder(name, options = {}) ⇒ Object
Creates a flag.
-
#flag_inits ⇒ Object
An array of initializer method symbols created so that Flags#reset_flags can reset flags to their default values.
-
#flags ⇒ Object
The flags that have been defined.
-
#hash_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with hashes.
-
#integer_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with integer values.
-
#public_flag_inits ⇒ Object
An array of initializer method symbols created so that Flags#reset_flags does its work appropriately for public flags.
-
#string_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with strings.
Instance Method Details
#array_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with arrays.
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 |
# File 'lib/agio/flags.rb', line 256 def array_flag(name, = {}) = { :default => lambda { [] } }.merge() = .merge(:type => :array) flag_builder(name, ) do |type, meth, ivar| case type when :setter define_method(meth) do |value| value = [ value ] unless value.nil? or value.kind_of? Array instance_variable_set(ivar, value) end when :tester define_method(meth) do value = instance_variable_get(ivar) !(value.nil? or value.empty?) end end end end |
#boolean_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with Boolean (true or false) values.
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/agio/flags.rb', line 203 def boolean_flag(name, = {}) = { :default => false }.merge().merge(:type => :boolean) flag_builder(name, ) do |type, meth, ivar| case type when :setter define_method(meth) do |value| instance_variable_set(ivar, !!value) end when :tester define_method(meth) do !!instance_variable_get(ivar) end end end end |
#flag_builder(name, options = {}) ⇒ Object
Creates a flag. This method is the core method for building flags. Flags must have a name and may specify one of two options, :default or :public.
flag_builder returns a Hash describing the flag.
Options
- :default
-
The default value for the flag. If not specified, or not overridden by one of the type helper methods, the default will be
nil. If the default is not an immediate value, the default should be specified in a Proc, as is done for Array flags:lambda { [] }. - :public
-
If
true, indicates that the flag is internal and should not be exposed to the user. The default is that flags are private (e.g.,:public => false).
Methods Defined
Four methods are always defined by flag_builder or a type helper method. The type helper methods mentioned below may override the default behaviours described below.
- Init
-
“init_name”. This is always private, and should only be called through Flags#reset_flags. Sets the value of the flag to the default value. If the default value returns to #call, it will be called to provide the default value. Uses the flag’s Setter.
- Getter
-
“name”. Returns the value of the flag.
- Setter
-
“set_name” if private or “name=” if public. Sets the flag to the provided value.
- Tester
-
“name?” Returns
trueorfalsefor the value with double negation (e.g.,!!value).
When calling flag_builder from a helper method, you can provide a block that will allow the customization of the Setter or the Tester. The other methods cannot be overridden.
Type Helper Methods
There are five type helpers defined:
- string_flag
-
Creates a flag that works with String values. The default value is
nil, unless otherwise specified. If a non-nil value is provided, the default value will be wrapped in a Proc that will create a new String object for every reset. The Setter converts all values (exceptnil) to a String using #to_s. The Tester will returnfalseif the value isnilor the String is empty. - boolean_flag
-
Creates a flag that works with Boolean values (
trueorfalse). The default value for a boolean_flag isfalse, unless otherwise specified. The Setter converts all values totrueorfalsethrough double negation (e.g.,!!value). The Tester forces the instance variable totrueorfalsethrough double negation. - integer_flag
-
Creates a flag that works with integer values. The default value for an integer_flag is zero, unless otherwise specified. The Setter converts all values to integer with #to_i. The Tester returns
trueif the value is non-zero. Private integer flags also define two additional methods, incr_name and decr_name, that will increment or decrement the integer value by the value provided. - hash_flag
-
Creates a flag that works with Hash values. The default value is a lambda that creates an empty Hash. The Tester returns
falseif the value isnilor the Hash is empty. - array_flag
-
Creates a flag that works with Array values. The default value is a lambda that creates an empty Array. The Tester returns
falseif the value isnilor the Array is empty.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
# File 'lib/agio/flags.rb', line 105 def flag_builder(name, = {}) raise SyntaxError, "Flag #{name} already defined" if flags.has_key? name.to_sym default = [:default] type = [:type] is_public = [:public] flag = { :ivar => "@flag_#{name}", :init => "init_#{name}".to_sym, :getter => name.to_sym, :setter => (is_public ? "#{name}=" : "set_#{name}").to_sym, :tester => "#{name}?".to_sym, :public => is_public, :type => type, :default => default, } # Define the flag initializer define_method(flag[:init]) do value = if default.respond_to? :call default.call else default end __send__(flag[:setter], value) end private flag[:init] if is_public public_flag_inits << flag[:init] else flag_inits << flag[:init] end # Define the flag getter define_method(flag[:getter]) do instance_variable_get(flag[:ivar]) end private flag[:getter] unless is_public # Define the flag setter defined = yield :setter, flag[:setter], flag[:ivar] if block_given? unless defined define_method(flag[:setter]) do |value| instance_variable_set(flag[:ivar], value) end end private flag[:setter] unless is_public # Define the flag tester defined = yield :tester, flag[:tester], flag[:ivar] if block_given? unless defined define_method(flag[:tester]) do !!instance_variable_get(ivar) end end private flag[:tester] unless is_public flags[name.to_sym] = flag end |
#flag_inits ⇒ Object
An array of initializer method symbols created so that Flags#reset_flags can reset flags to their default values.
299 300 301 |
# File 'lib/agio/flags.rb', line 299 def flag_inits @flag_inits ||= [] end |
#flags ⇒ Object
The flags that have been defined.
312 313 314 |
# File 'lib/agio/flags.rb', line 312 def flags @flags ||= {} end |
#hash_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with hashes.
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
# File 'lib/agio/flags.rb', line 277 def hash_flag(name, = {}) = { :default => lambda { {} } }.merge() = .merge(:type => :hash) flag_builder(name, ) do |type, meth, ivar| case type when :setter define_method(meth) do |value| raise ArgumentError unless value.nil? or value.kind_of? Hash instance_variable_set(ivar, value) end when :tester define_method(meth) do value = instance_variable_get(ivar) !(value.nil? or value.empty?) end end end end |
#integer_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with integer values.
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 |
# File 'lib/agio/flags.rb', line 221 def integer_flag(name, = {}) = { :default => 0 }.merge().merge(:type => :integer) flag = flag_builder(name, ) do |type, meth, ivar| case type when :setter define_method(meth) do |value| instance_variable_set(ivar, value.to_i) end when :tester define_method(meth) do instance_variable_get(ivar).nonzero? end end end unless flag[:public] incr = "incr_#{name}".to_sym define_method(incr) do |value| value = instance_variable_get(flag[:ivar]) + value.to_i instance_variable_set(flag[:ivar], value) end private incr decr = "decr_#{name}".to_sym define_method(decr) do |value| value = instance_variable_get(flag[:ivar]) - value.to_i instance_variable_set(flag[:ivar], value) end private decr end end |
#public_flag_inits ⇒ Object
An array of initializer method symbols created so that Flags#reset_flags does its work appropriately for public flags.
306 307 308 |
# File 'lib/agio/flags.rb', line 306 def public_flag_inits @public_flag_inits ||= [] end |
#string_flag(name, options = {}) ⇒ Object
Defines a flag optimized for working with strings.
171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 |
# File 'lib/agio/flags.rb', line 171 def string_flag(name, = {}) = { :default => nil }.merge().merge(:type => :string) value = [:default] [:default] = case value when nil nil when String lambda { value.dup } else lambda { value.to_s } end flag_builder(name, ) do |type, meth, ivar| case type when :setter define_method(meth) do |value| value = value.to_s unless value.nil? instance_variable_set(ivar, value) end when :tester define_method(meth) do value = instance_variable_get(ivar) !(value.nil? or value.empty?) end end end end |