Module: Changes::ClassMethods
- Includes:
- Gather::ClassMethods
- Defined in:
- lib/changes.rb
Instance Method Summary collapse
-
#blankslate! ⇒ Object
Remove all but the absolutely essential methods from this class.
- #dynamic! ⇒ Object
- #dynamic? ⇒ Boolean
-
#dynamic_properties(*syms) ⇒ Object
Allow accessors to be added dynamically, the default.
- #module_name(symbol) ⇒ Object
-
#operation(name, &body) ⇒ Object
define a method ‘name’ (which can be symbol or a string) which takes args and a block calls gather and then executes the block.
-
#property(*symbols) ⇒ Object
For each property in symbols, add methods: instance.property as reader instance.property( value ) as writer instance.property = value as writer instance.before_property {|old,new| … } instance.after_property {|old,new| … } instance.on_property {|old,new| … } instance.property_changed? instance.undo_property!.
- #static! ⇒ Object
-
#static_properties(*syms) ⇒ Object
Do not allow accessors to be added dynamically.
Methods included from Gather::ClassMethods
Instance Method Details
#blankslate! ⇒ Object
Remove all but the absolutely essential methods from this class. Useful if you want a dynamic property list, but can have some surprising side effects, obviously.
129 130 131 132 133 134 135 |
# File 'lib/changes.rb', line 129 def blankslate! # remove unused methods that might clash with user accessors keep_methods = %w( __send__ __id__ self send class inspect instance_eval instance_variables ) instance_methods.each do |method| undef_method( method ) unless keep_methods.include?( method ) end end |
#dynamic! ⇒ Object
268 |
# File 'lib/changes.rb', line 268 def dynamic!; @dynamic = true; end |
#dynamic? ⇒ Boolean
271 272 273 274 275 276 |
# File 'lib/changes.rb', line 271 def dynamic? # don't optimise this to @dynamic ||= true, because it will reset # an @dynamic of false to true @dynamic = false if @dynamic.nil? @dynamic end |
#dynamic_properties(*syms) ⇒ Object
Allow accessors to be added dynamically, the default.
263 264 265 266 |
# File 'lib/changes.rb', line 263 def dynamic_properties( *syms ) @dynamic = true property( *syms ) end |
#module_name(symbol) ⇒ Object
137 138 139 |
# File 'lib/changes.rb', line 137 def module_name( symbol ) "#{symbol.to_s.capitalize}Property" end |
#operation(name, &body) ⇒ Object
define a method ‘name’ (which can be symbol or a string) which takes args and a block calls gather and then executes the block. Any changes made from args and block are rolled back name! will not roll back values
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 |
# File 'lib/changes.rb', line 288 def operation( name, &body ) # save the block to be executed later class_eval "@@#{name.to_s}_operation_block = body" # define the new method called name class_eval <<-EOF, __FILE__, __LINE__.to_i + 1 def #{name.to_s}( args = {}, &block ) preserve do gather( args, &block ) instance_eval( &@@#{name.to_s}_operation_block ) end end EOF # define new method called name! class_eval <<-EOF, __FILE__, __LINE__.to_i + 1 def #{name.to_s}!( args = {}, &block ) gather( args, &block ) instance_eval( &@@#{name.to_s}_operation_block ) end EOF end |
#property(*symbols) ⇒ Object
For each property in symbols, add methods:
instance.property as reader
instance.property( value ) as writer
instance.property = value as writer
instance.before_property {|old,new| ... }
instance.after_property {|old,new| ... }
instance.on_property {|old,new| ... }
instance.property_changed?
instance.undo_property!
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 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 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/changes.rb', line 150 def property( *symbols ) @stripper ||= /^([^\= ]+)\s*\=?\s*$/ symbols.each do |sym| property = @stripper.match( sym.to_s )[1] # TODO false here until I figure out how to remove properties unless false && const_defined?( module_name( property ).to_sym ) own_properties << property.to_sym line, st = __LINE__, <<-EOF module #{module_name( property )} public def #{property}(*val) if val.empty? @#{property} else unwrapped_value = val.size == 1 ? val[0] : val self.#{property} = unwrapped_value end end def on_#{property}( &block ) @on_#{property}_block = block end def after_#{property}( &block ) @after_#{property}_block = block end def before_#{property}( &block ) @before_#{property}_block = block end def #{property}=(*new_value) unwrapped_value = new_value.size == 1 ? new_value[0] : new_value return if unwrapped_value == @#{property} @before_#{property}_block.call_if( @#{property}, unwrapped_value ) changes[:#{property}] ||= Change.new changes[:#{property}].old << @#{property} changes[:#{property}].new = unwrapped_value @#{property} = unwrapped_value @after_#{property}_block.call_if( changes[:#{property}].old, unwrapped_value ) @on_#{property}_block.call_if( changes[:#{property}].old, unwrapped_value ) on_change( :#{property}, changes[:#{property}].old, unwrapped_value ) end def #{property}_changed? changes.has_key?(:#{property}) && !changes[:#{property}].old.empty? end # Undo the last change and return the undone value. # return nil if there were no changes to undo def undo_#{property}! undo( :#{property} ) end def reset_#{property}! changes[x] = Change.new end private def direct_#{property}=( value ) @#{property} = value end end # module EOF class_eval st, __FILE__, line + 1 end # always include the module, for re-definitions class_eval "include #{property.capitalize}Property" end end |
#static! ⇒ Object
269 |
# File 'lib/changes.rb', line 269 def static!; @dynamic = false; end |
#static_properties(*syms) ⇒ Object
Do not allow accessors to be added dynamically. In other words, a subclass like this
class IndexCollector
static_properties :row, :column
end
will fail if used like this
collector = IndexCollector.new( :row => 4, :column => 6 ) do
other 'oops'
end
because :other isn’t added by static_properties.
257 258 259 260 |
# File 'lib/changes.rb', line 257 def static_properties( *syms ) @dynamic = false property( *syms ) end |