Err the Blog Atom Feed Icon
Err the Blog
Rubyisms and Railities
  • “Sugary Adapters”
    – Chris on February 16, 2008

    It has two comments.
    Advertisement

    Very recently, Simon Harris had an idea: nil? for Ambition. Tasty sugar.

    Let’s figure out what it takes to make

    User.select { |x| x.nil? }
    

    behave just like

    User.select { |x| x == nil }
    

    in Ambition.

    Short and Sweet

    Simon’s approach was to modify Ambition directly to add support for nil?. While this is for sure ambitious, nil? is just another method. Not special. The adapter should decide what to do with it.

    Easy. Here’s what we added to the ActiveRecord adapter’s Select translator:

    def nil?(column)
      left = "#{owner.table_name}.#{quote_column_name column}" 
      negated? ? not_equal(left, nil) : self.==(left, nil)
    end
    

    See it in action on lines 84 to 87.

    The tests, of course, can be found in types_test.

    Chaining Stuffs

    So, how does this work?

    Every adapter’s Select translator has a special chained_call method. Ambition invokes chained_call and passes it an array of symbols when a chained.method.call is executed on itself.

    In this case, the chain is m.name.nil?. Ambition knows that m is itself and ignores it, passing [ :name, :nil? ] to chained_call.

    The ActiveRecord adapter’s chained_call method takes the passed array and, if it can find the second element, sends it the first element.

    Basically:

    # methods = [ :name, :nil? ]
    if respond_to? methods[1]
      send(methods[1], methods.first)
    end
    

    Which translates to:

    self.nil? :name
    

    Cool. Adapters don’t need to set themselves up this way, but it works for ActiveRecord.

    Notice: the ActiveRecord adapter doesn’t support anything more than chains two methods deep. It calls the second element and passes the first, ignoring the rest. Almost discouraging, but chin up – this is ActiveRecord specific. Ambition itself supports chains of arbitrary length, and your adapter can, too.

    So array.include?, right?

    The thing is, chained_call is only invoked when a chained method call is executed on an object Ambition owns.

    User.select { |x| x.nil? }
    

    In the above, Ambition owns the x. It’s self as far as the translator is concerned.

    User.select { |x| [1,2,3].include? x.id }
    

    Ambition does not own the array, only the x.id. So what happens?

    Well, it’s the same as [1,2,3] == x.id to Ambition. The dude really doesn’t care. Any time there is something like left op right, Ambition calls op(left, right) on your translator.

    Here’s an idea of the call:

    include?([1,2,3], x.id)
    

    Luckily x.id is translated for you prior to this. The call really looks more like:

    include?([1,2,3], 'users.id')
    

    The include? definition, then, on ActiveRecord’s translator is very straightforward:

    def include?(left, right)
      left = left.map { |element| sanitize element }.join(', ')
      "#{right} IN (#{left})" 
    end
    

    Beautiful.

    Join the Fun

    While the Err twitter is great for general stuff, you should really hop on the Ambition mailing list if you want in on this action. Or just watch the project on GitHub.

    Til next time.

  • The Comedy of Errors
    Every why hath a wherefore.
    • 71. Adapting Ambitiously
      Published January of 2008. Twenty-five comments.
    • 70. Feeds for Free
      Published January of 2008. Nineteen comments.
    • 69. The jSkinny on jQuery
      Published January of 2008. Thirty-three comments.
    • 68. Paginatin' Christmas
      Published December of 2007. Twenty-five comments.
    • 67. Evil Twin Plugin
      Published November of 2007. Seventeen comments.
    • 66. View Testing 2.0
      Published September of 2007. Thirty-seven comments.
    • 65. Automatically
      Published September of 2007. Thirty-four comments.
    • 64. Even More Ambitious
      Published September of 2007. Seventeen comments.
    • 63. Full of Ambition
      Published August of 2007. Sixty-one comments.
    • 62. So, You Want Your Own Counter, Huh?
      Published August of 2007. Thirteen comments.
    • 61. Fixin' Fixtures
      Published July of 2007. Twenty-nine comments.
    • 60. Sake Bomb!
      Published June of 2007. Fifty-seven comments.
    • 59. Cappin' that Stat
      Published June of 2007. Fifteen comments.
    • 58. Jottin' to the Fullest
      Published June of 2007. Twelve comments.
    • 57. Kickin Ass w/ Cache-Fu
      Published May of 2007. Fifteen comments.
    • 56. I'm Paginating Again
      Published May of 2007. One hundred and thirty-five comments.
    • 55. Ya Talkin' Gibberish
      Published May of 2007. Forty-one comments.
    • 54. Be Dee Dee and Me
      Published May of 2007. Thirteen comments.
    • 53. Microformathingies
      Published April of 2007. Four comments.
    • 52. Nginx Config Like Whoa
      Published April of 2007. Twenty-one comments.
    • 51. Sexy Migrations
      Published March of 2007. Thirty-seven comments.
    • 50. Vendor Everything
      Published March of 2007. Twenty-six comments.
    • 49. A Zoned Defense
      Published March of 2007. Eleven comments.
    • 48. alias_method_bling
      Published February of 2007. Ten comments.
    • 47. I Will Paginate
      Published February of 2007. Eighty-nine comments.
    • 46. RSSin' Your SVN
      Published January of 2007. Sixteen comments.
    • 45. Allow Me to Inject
      Published January of 2007. Ten comments.
    • 44. Select a Reject
      Published January of 2007. Eight comments.
    • 43. Captchator on Rails
      Published January of 2007. Sixteen comments.
    • 42. Rails Rubyisms Advent
      Published January of 2007. Twenty-seven comments.
    • 41. Real Console Helpers
      Published January of 2007. Five comments.
    • 40. Extend for Profit
      Published January of 2007. Sixteen comments.
    • 39. with_scope with scope
      Published January of 2007. Eighteen comments.
    • 38. SOAP in my Mocha!
      Published January of 2007. Seven comments.
    • 37. Pennin' a DSL
      Published January of 2007. Two comments.
    • 36. Rakie Pankie
      Published January of 2007. Six comments.
    • 35. Me and uFormats
      Published January of 2007. Twenty-one comments.
    • 34. A Ruby Rainbow
      Published January of 2007. Fourteen comments.
    • 33. My Rails Toolbox
      Published January of 2007. Forty-three comments.
    • 32. Cheat Again!
      Published January of 2007. Sixteen comments.
    • 31. Rake Around the Rosie
      Published January of 2007. Eight comments.
    • 30. OpenStruct IRL
      Published January of 2007. Five comments.
    • 29. Undefined what?!
      Published January of 2007. Five comments.
    • 28. Strut Your Structs
      Published January of 2007. Ten comments.
    • 27. Quickly: returning
      Published January of 2007. Fourteen comments.
    • 26. Content for Whom?
      Published January of 2007. Twelve comments.
    • 25. Memcaching Rails
      Published January of 2007. Eleven comments.
    • 24. irb Mix Tape
      Published January of 2007. Nineteen comments.
    • 23. submit_to_popup
      Published January of 2007. Nine comments.
    • 22. Sessions N Such
      Published January of 2007. Twenty-seven comments.
    • 21. Cheat!
      Published January of 2007. Thirty-six comments.
    • 20. Back Double At Ya
      Published January of 2007. Nine comments.
    • 19. Streaming Capistrano
      Published January of 2007. Three comments.
    • 18. Accessor Missing
      Published January of 2007. Four comments.
    • 17. Camping with Dr Nic
      Published January of 2007. Zero comments.
    • 16. Friday Hash Fun
      Published January of 2007. Three comments.
    • 15. has_many :as
      Published January of 2007. One comment.
    • 14. Composite Migrations
      Published January of 2007. Fifteen comments.
    • 13. Colored Tests
      Published January of 2007. Eleven comments.
    • 12. acts_as_textiled
      Published January of 2007. Thirty-five comments.
    • 11. Block to Partial
      Published January of 2007. Eight comments.
    • 10. case when else end
      Published January of 2007. Zero comments.
    • 09. Drop to IRB
      Published January of 2007. One comment.
    • 08. DRY Your Controllers
      Published January of 2007. Seven comments.
    • 07. ActiveRecord Variance
      Published January of 2007. Eight comments.
    • 06. Parse XML with Hpricot
      Published January of 2007. Three comments.
    • 05. Simpler irb
      Published January of 2007. Two comments.
    • 04. Auto-Patch Rails
      Published January of 2007. One comment.
    • 03. Organize Your Models
      Published January of 2007. Ten comments.
    • 02. rake remigrate
      Published January of 2007. Ten comments.
    • 01. Actions Are Methods
      Published January of 2007. Three comments.

Projects

  • Cheat! Sheets
  • Subtlety: RSSin' Your SVN
  • cache_fu
  • acts_as_textiled
  • mofo [microformat parsing]
  • require 'errtheblog'

Information

  • Dynamite! — The Err Free Weblog
  • Err Free: Ruby Development & Consulting
  • Err on GitHub
  • Err on Twitter
  • Report Err Plugin Bugs (Lighthouse Tracker)
  • Contact
This is Err, the weblog of PJ Hyett and Chris Wanstrath.
All original content copyright ©2006-2008 the aforementioned.