Monday, May 3, 2010

Dynamic finder with #doesNotUnderstand, #perform and Regex

This is the sequel to SandstoneDb, simple ActiveRecord style persistence screencast.

I show how to:
  • override Object#doesNotUnderstand in your class to answer to unknown messages
  • use regular expressions to extract substrings
  • use #perform: and #perform:with: to send a message dynamically
  • develop new code in the debugger without stopping current call.

To learn about Regex in Pharo, read the (draft) chapter for Pharo By Example 2.

Download screencast (800x600): .mpeg 23.1 MB, .mov 37.2 MB

Here's the final code of Person#doesNotUnderstand:
doesNotUnderstand: aMessage
  "aMessage arguments  #('Laurent' 10)"
  "aMessage selector #findAllByName:Age:"
  | selRegex findSelector searchSelectors searchedValues |
  selRegex := 'find(All|First)By(\w+\:)+' asRegex.
  (selRegex search: aMessage selector)
      ifFalse: [^ super doesNotUnderstand: aMessage].
  findSelector := ((selRegex subexpression: 2) = 'All') 
                                       ifTrue: [#findAll:] 
                                       ifFalse: [#find:].
  searchSelectors := (selRegex subexpressions: 3) collect: 
                        aSymbol asLowercase allButLast asSymbol].
  (self allSelectors includesAllOf: searchSelectors) 
                 ifFalse: [^ super doesNotUnderstand: aMessage].
  searchedValues := aMessage arguments.
  ^ self 
    perform: findSelector 
    with: [:aPerson| |values| 
           values := searchSelectors collect: 
                       aPerson perform: aSelector].
           searchedValues = values].

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.