Ben Matasar

Mon, 14 Aug 2006

ParseTree and rails console

Lately I have been thinking about IDEs and developer tools in general. I have been using Eclipse with Java and Squeak Smalltalk mostly, trying to understand why those tools are so good. One of the things that separates Eclipse and the refactoring browser from what other languages have is that they keep the parsed tree of the program in memory. With that in mind, here's what I think is an interesting irb exchange with a simple, one model rails app.

   >> pt = ParseTree.new
=> #<ParseTree:0x24236f4 @include_newlines=false>
>> pt.parse_tree Conversation
=> [[:class, :Conversation, :"ActiveRecord::Base"]]
>> conv = Conversation.find 1
=> #<Conversation:0x2767748 @attributes={"name"=>"Hello, world", "id"=>"1", "description"=>nil}>
>> pt.parse_tree Conversation
=> [[:class, :Conversation, :"ActiveRecord::Base"]]
>> conv.name
=> "Hello, world"
>> pt.parse_tree Conversation
=> [[:class, :Conversation, :"ActiveRecord::Base", [:defn, :description, [:scope, [:block, [:args], [:if, [:call, [:ivar, :@attributes], :has_key?, [:array, [:str, "description"]]], nil, [:fcall, :raise, [:array, [:const, :NoMethodError], [:str, "missing attribute: description"], [:vcall, :caller]]]], [:call, [:ivar, :@attributes], :[], [:array, [:str, "description"]]]]]], [:defn, :description?, [:scope, [:block, [:args], [:fcall, :query_attribute, [:array, [:str, "description"]]]]]], [:defn, :id?, [:scope, [:block, [:args], [:fcall, :query_attribute, [:array, [:str, "id"]]]]]], [:defn, :name, [:scope, [:block, [:args], [:if, [:call, [:ivar, :@attributes], :has_key?, [:array, [:str, "name"]]], nil, [:fcall, :raise, [:array, [:const, :NoMethodError], [:str, "missing attribute: name"], [:vcall, :caller]]]], [:call, [:ivar, :@attributes], :[], [:array, [:str, "name"]]]]]], [:defn, :name?, [:scope, [:block, [:args], [:fcall, :query_attribute, [:array, [:str, "name"]]]]]]]]

I learned two things from this:

  1. Rails lazily build the methods in ActiveRecord::Base.
  2. ParseTree has no problem with metaprogramming code.

Both of these things are what I guessed. If I wanted to build some tools for rails or ruby in general, I would have to work around metaprogramming. Here's another fun bit:

 >> objects = []
=> []
>> ObjectSpace.each_object{|obj| objects.push obj}
=> 76851
>> models = objects.select{|obj| obj.class == Class && obj.superclass == ActiveRecord::Base}
=> [CGI::Session::ActiveRecordStore::Session]
>> Conversation
=> Conversation
>> objects = []
=> []
>> ObjectSpace.each_object{|obj| objects.push obj}
=> 78580
>> models = objects.select{|obj| obj.class == Class && obj.superclass == ActiveRecord::Base}
=> [CGI::Session::ActiveRecordStore::Session, Conversation]

tech | link | 2006/Aug | comments (0)


Ben Matasar ben@matasar.org