<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>Hayai Raspberry</title>
	<atom:link href="http://asqyzeron.wordpress.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://asqyzeron.wordpress.com</link>
	<description>Hacking cool stuff</description>
	<lastBuildDate>Thu, 18 Jan 2007 19:44:13 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.com/</generator>
<cloud domain='asqyzeron.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://s2.wp.com/i/buttonw-com.png</url>
		<title>Hayai Raspberry</title>
		<link>http://asqyzeron.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://asqyzeron.wordpress.com/osd.xml" title="Hayai Raspberry" />
	<atom:link rel='hub' href='http://asqyzeron.wordpress.com/?pushpress=hub'/>
		<item>
		<title>How to have friends</title>
		<link>http://asqyzeron.wordpress.com/2007/01/17/how-to-have-friends/</link>
		<comments>http://asqyzeron.wordpress.com/2007/01/17/how-to-have-friends/#comments</comments>
		<pubDate>Wed, 17 Jan 2007 22:35:57 +0000</pubDate>
		<dc:creator>asqyzeron</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://asqyzeron.wordpress.com/2007/01/17/how-to-have-friends/</guid>
		<description><![CDATA[First of all, welcome to all the lonely people who arrived on this page falsely brought here by this deceiving title. The reason behind it is that I wondered how to make a Ruby equivalent to C++&#8217;s friend methods. What we have to do is to catch any attempt to call a private or protected [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=asqyzeron.wordpress.com&amp;blog=679580&amp;post=9&amp;subd=asqyzeron&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>First of all, welcome to all the lonely people who arrived on this page falsely brought here by this deceiving title.<br />
The reason behind  it is that I wondered how to make a Ruby equivalent to C++&#8217;s friend methods.</p>
<p>What we have to do is to catch any attempt to call a private or protected method, check that the caller is authorized to do so and then call it on his behalf.</p>
<h3>Detecting a missed call</h3>
<p>Ruby provides a method called <code>missing_method</code>. Overloading this method lets us catch (among other things) any attempt at calling a private method.</p>
<p>We have to make sure that this is indeed a call to a private method. We do so (even if this is certainly not the most efficient way) by checking that the method name passed as an argument is present in the private methods list returned by <code>private_methods</code>.</p>
<pre>	<strong>def</strong> <span style="color:#000080;">method_missing</span> mthid
 		<span style="color:#000080;">puts</span> <span style="color:#dd0000;">"method_missing : "</span> <span style="color:#ff00ff;">+</span> mthid<span style="color:#4000a7;">.id2name
</span>  	<span style="color:#808080;"><em>	# Check that mthid is actually a private method</em></span>
 		<strong>if</strong> private_methods<span style="color:#4000a7;">.include?</span> mthid<span style="color:#4000a7;">.id2name</span>
 		<span style="color:#808080;"><em>	# Perform other checks...</em></span>
 		<strong>end</strong>
 	<strong>end</strong></pre>
<h3>Telling your friends from your foes</h3>
<p align="justify">Checking that a private method exists is not enough, as you don&#8217;t want uninvited methods to be able to call private methods of your object. You make sure this doesn&#8217;t happen by keeping a list of who is allowed to call your private methods.<br />
The problem is, how do you ensure that it doesn&#8217;t get compromised? Ruby&#8217;s strength lies in the fact that nothing is really fixed. Would this be the end of a beautiful story?</p>
<p>Of course not. First, because one can <strong>freeze</strong> objects, that is protect them from further alteration. Which is very useful if we want to maintain an access list, write a few methods to access it and make sure that no one will be able to add new methods so as to bypass security checks.</p>
<p>Once an access list exists, we have to make sure that any method that calls the private methods is actually whom it pretends it is. This is a touchy point, as we will see in the following part.</p>
<h3>Finding who is the caller</h3>
<p>At the moment, Ruby doesn&#8217;t provide a very nice methods to do this. There is a method named <code>caller</code> that returns a bunch of strings. Parsing them is quite tedious, and sometimes the relevant information is not available at all. An improved version of this method is one of the much anticipated features of the next versions of Ruby. Meanwhile, we have to do this in ourselves. And that involves delving into the code of the Ruby interpreter.<br />
When evaluating code, Ruby uses a structure to remember where it comes from, and where it is going. This structure is called a <a href="http://www.ruby-doc.org/doxygen/1.8.4/env_8h-source.html">FRAME</a> and keeps track of information like what is the current file, the current line, and many other relevant things. The thing we are interested in, however, is that it also mentions the class and the method that were referred to. These frames are stored as a linked list, the head of which is stored in the global variable <code>ruby_frame</code>.<br />
Analyzing that linked list should hence provide us with all the information we need to identify who has been calling the program. This is done by the C function below:</p>
<pre><span style="color:#008000;">#include "ruby.h"</span>
<span style="color:#008000;">#include "env.h"</span>
<span style="color:#008000;">#include "node.h"</span>
<span style="color:#800000;">
static</span> VALUE getbt(VALUE self)
{
  <strong>struct</strong> FRAME *frame	= ruby_frame;
  VALUE	ary		= rb_ary_new();
  VALUE	temp;

 	<strong>for</strong> (; frame; frame=frame-&gt;prev) {
 		temp = rb_ary_new();
 		rb_ary_push(temp, frame-&gt;last_class);
 		<strong>if</strong> (frame-&gt;last_func)
 			rb_ary_push(temp, ID2SYM(frame-&gt;last_func));
 		rb_ary_push(ary, temp);
 	}
  	<strong>return</strong> ary;
 }

 <span style="color:#800000;">void</span> Init_sunwind()
 {
 	rb_define_method(rb_cObject, <span style="color:#dd0000;">"backtrace"</span>, getbt, <span style="color:#0000ff;">0</span>);
 }</pre>
<p align="justify">Follow <a href="http://gballet.free.fr/sunwind.html">this link</a> if it isn&#8217;t displayed properly.</p>
<p align="justify">Note that, unfortunately, things are not as easy as this. Someone could still trick our program into believing that access should bre granted when it should not. Inserting a fake entry in the linked list should do the trick. However, it is not as easy as writing ruby code, as a hacker would have to install a C library and call it. Also, increasing the complexity of our linked-list parsing function by checking other elements could help us deter a few attacks. This is left as an open question for future articles.</p>
<p align="justify">Compile the program as a Ruby library, and let&#8217;s move on to the next step : the actual Ruby code.</p>
<h3>The final code</h3>
<p align="justify">The program is made up of several classes : The first one, <code>BuddyController</code>, maintains the list of friend methods for each class in a hash table. The second one, <code>Test</code>, has a secret method <code>sekret_method</code> that is private. It declares two methods, one is the method_missing method we have talked about at the beginning of this post. The second one is a class method that is used to declare friends. The last class, <code>TestBuddy</code>, defines a single method that is declared as a friend of <code>Test</code>.</p>
<p align="justify">Note that, in order to keep things simple, there is no real access control to <code>BuddyController</code>. Anyone can register the method he wishes. A real world implementation would obviously proceed by calling <code>backtrace</code> instead of trusting the caller.</p>
<pre><span style="color:#000080;">require</span> <span style="color:#dd0000;">"sunwind"
</span>
<span style="color:#808080;"><em># Declaration</em></span>
<strong>class</strong> <span style="color:#800000;">TestBuddy</span>
<strong>end</strong>

<strong>class</strong> <span style="color:#800000;">Test</span>
<strong>end</strong>

<span style="color:#808080;"><em># This class maintains a list of friend methods</em></span>
<strong>class</strong> <span style="color:#800000;">BuddyController</span>
<span style="color:#808080;"><em>	# The list</em></span>
	<span style="color:#008000;">@@friend_list</span> <span style="color:#ff00ff;">=</span> <span style="color:#800000;">Hash</span><span style="color:#4000a7;">.new</span>
 <span style="color:#808080;"><em>	# Forbids instantiation</em></span>
	<span style="color:#0000ff;"><strong>private_class_method</strong></span> <span style="color:#d40000;">:new</span>

<span style="color:#808080;"><em>	# Add a methdod's signature to the list of friends</em></span>
	<strong>def</strong> <span style="color:#800000;">BuddyController</span><span style="color:#4000a7;">.add</span> klass, str
	<span style="color:#808080;"><em>	# Add it to the list</em></span>
		<strong>if</strong> <span style="color:#008000;">@@friend_list</span><span style="color:#ff00ff;">[</span>klass<span style="color:#ff00ff;">]</span><span style="color:#4000a7;">.nil?</span>
			<span style="color:#008000;">@@friend_list</span><span style="color:#ff00ff;">[</span>klass<span style="color:#ff00ff;">]</span> <span style="color:#ff00ff;">=</span> <span style="color:#ff00ff;">[</span>str<span style="color:#ff00ff;">]</span>
<strong>		else</strong>
			<span style="color:#008000;">@@friend_list</span><span style="color:#ff00ff;">[</span>klass<span style="color:#ff00ff;">]</span> <span style="color:#ff00ff;">+=</span> str
		<strong>end</strong>
	<strong>end</strong>

<span style="color:#808080;"><em>	# Check wether or not a method is a friend</em></span>
	<strong>def</strong> <span style="color:#800000;">BuddyController</span><span style="color:#4000a7;">.match</span> klass, str
		<strong>if</strong> (!<span style="color:#008000;">@@friend_list</span><span style="color:#ff00ff;">[</span>klass<span style="color:#ff00ff;">]</span><span style="color:#4000a7;">.nil?</span>) <span style="color:#ff00ff;">&amp;&amp;</span> (<span style="color:#008000;">@@friend_list</span><span style="color:#ff00ff;">[</span>klass<span style="color:#ff00ff;">]</span><span style="color:#4000a7;">.include?</span> str)
			<span style="color:#0000ff;">true</span>
<strong>		else</strong>
			<span style="color:#0000ff;">false</span>
		<strong>end</strong>
	<strong>end</strong>

	<strong>def</strong> <span style="color:#800000;">BuddyController</span><span style="color:#4000a7;">.dump</span>
		<span style="color:#008000;">@@friend_list</span><span style="color:#4000a7;">.each</span> <span style="color:#ff00ff;">{</span> <span style="color:#ff00ff;">|</span>k,v<span style="color:#ff00ff;">|</span>
			<span style="color:#000080;">puts</span> k<span style="color:#4000a7;">.to_s</span> <span style="color:#ff00ff;">+</span> <span style="color:#dd0000;">"="</span> <span style="color:#ff00ff;">+</span> v<span style="color:#4000a7;">.to_s</span>
		<span style="color:#ff00ff;">}</span>
	<strong>end</strong>
<strong>end</strong>

<span style="color:#808080;"><em># Freeze BuddyController to prevent any alteration</em></span>
<span style="color:#800000;">BuddyController</span><span style="color:#4000a7;">.freeze</span>

<span style="color:#808080;"><em># Alter class object so that every object can access the friend class method.</em></span>
<strong>class</strong> <span style="color:#800000;">Object</span>
<span style="color:#808080;"><em>	# The class method used to declare methods as friends.</em></span>
	<strong>def</strong> <span style="color:#800000;">Object</span><span style="color:#4000a7;">.friend</span> klass, sym
		<span style="color:#800000;">BuddyController</span><span style="color:#4000a7;">.add</span> <span style="color:#0000ff;">self</span>, klass<span style="color:#4000a7;">.to_s</span> <span style="color:#ff00ff;">+</span> <span style="color:#dd0000;">"#"</span> <span style="color:#ff00ff;">+</span> sym<span style="color:#4000a7;">.to_s</span>
	<strong>end</strong>
<strong>end</strong>

<span style="color:#808080;"><em># A class with a private method, declares friends.</em></span>
<strong>class</strong> <span style="color:#800000;">Test</span>
	<span style="color:#0000ff;"><strong>private</strong></span>

<span style="color:#808080;"><em>	# When a method cannot be loaded, check wether or not it is private</em></span>
	<strong>def</strong> <span style="color:#000080;">method_missing</span> mthid
		<span style="color:#000080;">puts</span> <span style="color:#dd0000;">"method_missing : "</span> <span style="color:#ff00ff;">+</span> mthid<span style="color:#4000a7;">.id2name</span>
 	<span style="color:#808080;"><em>	# Check that mthid is actually a private method</em></span>
		<strong>if</strong> private_methods<span style="color:#4000a7;">.include?</span> mthid<span style="color:#4000a7;">.id2name</span>
		<span style="color:#808080;"><em>	# Get the backtrace</em></span>
			bt 		<span style="color:#ff00ff;">=</span> backtrace
		<span style="color:#808080;"><em>	# after the target function, method_missing and backtrace</em></span>
		<span style="color:#808080;"><em>	# have been called.</em></span>
			klass, sym	<span style="color:#ff00ff;">=</span> bt<span style="color:#ff00ff;">[</span><span style="color:#0000ff;">2</span><span style="color:#ff00ff;">]</span>
			tempvalue	<span style="color:#ff00ff;">=</span> klass<span style="color:#4000a7;">.to_s</span> <span style="color:#ff00ff;">+</span> <span style="color:#dd0000;">"#"</span> <span style="color:#ff00ff;">+</span> sym<span style="color:#4000a7;">.to_s</span>

			<strong>if</strong> (<span style="color:#800000;">BuddyController</span><span style="color:#4000a7;">.match</span> <span style="color:#0000ff;">self</span><span style="color:#4000a7;">.class</span>, tempvalue)
			<span style="color:#808080;"><em>	# Call the method id
</em></span>				send(mthid)
<strong>			else</strong>
				<span style="color:#000080;">puts</span> <span style="color:#dd0000;">"Unauthorized access, or nonexistent method."</span>
			<strong>end</strong>
		<strong>end
</strong>	<strong>end

</strong>	<strong>def</strong> sekret_method
		<span style="color:#000080;">puts</span> <span style="color:#dd0000;">"Hello from the sekret method!"</span>
	<strong>end</strong>

<span style="color:#808080;"><em>	# Declare TestBuddy#do_test as a friend</em></span>
	friend <span style="color:#800000;">TestBuddy</span>, <span style="color:#d40000;">:do_test</span>
<strong>end</strong>

<span style="color:#808080;"><em># Freeze test so that no one can add its own method as a friend</em></span>
<span style="color:#800000;">Test</span><span style="color:#4000a7;">.freeze</span>

<span style="color:#808080;"><em># A class with a method that is friend to Test</em></span>
<strong>class</strong> <span style="color:#800000;">TestBuddy</span>
	<strong>def</strong> do_test
		temp <span style="color:#ff00ff;">=</span> <span style="color:#800000;">Test</span><span style="color:#4000a7;">.new</span>
		temp<span style="color:#4000a7;">.sekret_method</span>
	<strong>end</strong>
<strong>end</strong>

<span style="color:#808080;"><em># "Main" program</em></span>
tb <span style="color:#ff00ff;">=</span> <span style="color:#800000;">TestBuddy</span><span style="color:#4000a7;">.new</span>
tb<span style="color:#4000a7;">.do_test</span></pre>
<p>Follow <a href="http://gballet.free.fr/test.html">this link</a> if it is not displayed properly.</p>
<p>This program is far from being perfect, as nothing has been done to handle arguments. In fact, many things need to be improved. Backtraces aren&#8217;t used in BuddyControllet and declaring Object.friend is not the best choice. It&#8217;s a call for a version 2, isn&#8217;t it?</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/asqyzeron.wordpress.com/9/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/asqyzeron.wordpress.com/9/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/asqyzeron.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/asqyzeron.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/asqyzeron.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/asqyzeron.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/asqyzeron.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/asqyzeron.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/asqyzeron.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/asqyzeron.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/asqyzeron.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/asqyzeron.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/asqyzeron.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/asqyzeron.wordpress.com/9/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/asqyzeron.wordpress.com/9/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/asqyzeron.wordpress.com/9/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=asqyzeron.wordpress.com&amp;blog=679580&amp;post=9&amp;subd=asqyzeron&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://asqyzeron.wordpress.com/2007/01/17/how-to-have-friends/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/2ed627672a22f41f0f8b0a7bf9614563?s=96&#38;d=identicon" medium="image">
			<media:title type="html">Asq-Yzeron</media:title>
		</media:content>
	</item>
		<item>
		<title>RTracker is going public!</title>
		<link>http://asqyzeron.wordpress.com/2007/01/16/rtracker-going-public/</link>
		<comments>http://asqyzeron.wordpress.com/2007/01/16/rtracker-going-public/#comments</comments>
		<pubDate>Tue, 16 Jan 2007 13:33:19 +0000</pubDate>
		<dc:creator>asqyzeron</dc:creator>
				<category><![CDATA[RTracker]]></category>

		<guid isPermaLink="false">http://asqyzeron.wordpress.com/2007/01/16/rtracker-going-public/</guid>
		<description><![CDATA[Last week, I have opened a sourceforge account for RTracker. Although the code is still not production quality, I believe the project is ripe enough to welcome a bunch of other developpers. Pieces of code should be published little by little, as fast as I can &#8220;clean&#8221; them. Some demonstration videos are being uploaded on [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=asqyzeron.wordpress.com&amp;blog=679580&amp;post=6&amp;subd=asqyzeron&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p>Last week, I have opened a sourceforge account for <a href="http://rdtracker.sourceforge.net">RTracker</a>. Although the code is still not production quality, I believe the project is ripe enough to welcome a bunch of other developpers. Pieces of code should be published little by little, as fast as I can &#8220;clean&#8221; them.</p>
<p>Some demonstration videos are being uploaded on the website. They are not really beautiful, as a lot of work has to be done on the graphics design side, but they show what the software can do.</p>
<p>If you are interested in joining, please note that the project&#8217;s Unix name on <a href="http://www.sourceforge.net">sourceforge.net</a> is r<strong>d</strong>tracker, as rtracker was already taken by some other project.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/asqyzeron.wordpress.com/6/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/asqyzeron.wordpress.com/6/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/asqyzeron.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/asqyzeron.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/asqyzeron.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/asqyzeron.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/asqyzeron.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/asqyzeron.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/asqyzeron.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/asqyzeron.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/asqyzeron.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/asqyzeron.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/asqyzeron.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/asqyzeron.wordpress.com/6/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/asqyzeron.wordpress.com/6/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/asqyzeron.wordpress.com/6/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=asqyzeron.wordpress.com&amp;blog=679580&amp;post=6&amp;subd=asqyzeron&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://asqyzeron.wordpress.com/2007/01/16/rtracker-going-public/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/2ed627672a22f41f0f8b0a7bf9614563?s=96&#38;d=identicon" medium="image">
			<media:title type="html">Asq-Yzeron</media:title>
		</media:content>
	</item>
		<item>
		<title>Toying with the dynamic features of Ruby : Adding methods at run time</title>
		<link>http://asqyzeron.wordpress.com/2007/01/14/toying-with-the-dynamic-features-of-ruby-adding-methods-at-run-time/</link>
		<comments>http://asqyzeron.wordpress.com/2007/01/14/toying-with-the-dynamic-features-of-ruby-adding-methods-at-run-time/#comments</comments>
		<pubDate>Sun, 14 Jan 2007 12:06:51 +0000</pubDate>
		<dc:creator>asqyzeron</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://asqyzeron.wordpress.com/2007/01/14/toying-with-the-dynamic-features-of-ruby-adding-methods-at-run-time/</guid>
		<description><![CDATA[&#160; I feel the way to start this blog is to introduce a trick that is central to RTracker, namely the possibility given to the Ruby programer to add methods to its classes on the flight. Like almost everything else you can wish for, Ruby provides the user with a method that does just this [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=asqyzeron.wordpress.com&amp;blog=679580&amp;post=5&amp;subd=asqyzeron&amp;ref=&amp;feed=1" width="1" height="1" />]]></description>
			<content:encoded><![CDATA[<p class="entrybody">&nbsp;</p>
<p class="snap_preview">I feel the way to start this blog is to introduce a trick that is central to <a href="http://rdtracker.sourceforge.net/" target="_blank">RTracker</a>, namely the possibility given to the Ruby programer to add methods to its classes on the flight. Like almost everything else you can wish for, Ruby provides the user with a method that does just this : <a href="http://www.ruby-doc.org/core/classes/Module.html#M001707">Module#define_method</a>. There is, however, a problem : that method is private. Don&#8217;t worry, there is a hack to do this anyway:</p>
<blockquote><p><code><font color="#00aa11">self</font>.class.send(<font color="#ffa000">:define_method</font>, <font color="#ff0000">“method_name”</font>) { <em>method_code</em> }</code></p></blockquote>
<p>That is, one has to <a href="http://www.ruby-doc.org/core/classes/Object.html#M000292" target="_blank">send</a> a message calling <a href="http://www.ruby-doc.org/core/classes/Module.html#M001707">define_method</a> to the <strong>class</strong> of the current object. In order to illustrate this, let’s write a small profiler that shows the performances of a method call. Note that the purpose of this program is to demonstrate how Ruby works, as Ruby already provides a very interesting tool, the <a href="http://www.ruby-doc.org/stdlib/libdoc/benchmark/rdoc/index.html" target="_blank">benchmark</a>.</p>
<p>If one wants to measure the time taken by a method to run, the simplest thing to do is to use the method <a href="http://www.ruby-doc.org/core/classes/Time.html#M000207" target="_blank">Time#now</a>, which returns what time it is. By calling this method before and after executing the “profiled” method, one can infer how much time the method took.</p>
<p>The next step is to replace the method whose performances we want to measure by our own method, that captures the current time, run the actual method and then captures the time again in order to display the difference. Why replace it, instead of simply creating a new method? Simply because profiling is interesting when dealing with huge pieces of code, and that one cannot imagine replacing every occurence of a widely used method. The following code does that for us:</p>
<blockquote><p><code><strong>class</strong> Object<br />
<strong> </strong>  <strong>def</strong> Object.profile symbol<br />
rename_symbol = (”rprof_” + symbol.to_s).to_sym<br />
alias_method rename_symbol, symbol<br />
<font color="#000055"><em># Define the new method so as to add timing</em><br />
<em># code.</em></font><br />
<font color="#00aa11">self</font></code><code>.send(<font color="#ffa000">:define_method</font>, symbol.to_s) { |*args|<br />
start_time = Time.nowself.send(rename_symbol, *args)<br />
puts (Time.now - start_time).to_s + <font color="#ff0000">” have elapsed”</font><br />
}<br />
puts <font color="#ff0000">“The new method ”</font> + rename_symbol.to_s + <font color="#ff0000">” has been created for method ”</font> + symbol<br />
<strong>end</strong><br />
<strong>end</strong></code></p></blockquote>
<p>Then, in order to monitor a method, you can just use it like:</p>
<blockquote><p><code><strong>class</strong> Test<br />
<strong>  def</strong> hello<br />
puts “hello”<br />
<strong>end</strong><br />
profile <font color="#ffa000">:hello</font><br />
<strong>end</strong></code></p></blockquote>
<p>Calling hello on an instance of set gives you the timing for that call.</p>
<p>There is something I have implicitely assumed, and haven’t talked about: the fact that the method is a member of class <a href="http://www.ruby-doc.org/core/classes/Module.html" target="_blank">Module</a> and not of class <a href="http://www.ruby-doc.org/core/classes/Class.html">Class</a>. Yet, we managed to add a method to our class. This is due to the fact that the module Kernel is automatically included in class Object. We have therefore access to that method at class level.</p>
<p>Another problem is that we do not take into account the fact that the <a href="http://www.ruby-doc.org/core/classes/Time.html#M000207" target="_blank">Time#now</a> method itself takes some time. Of course, one can imagine writing something like:</p>
<blockquote><p><code>@@time_overhead = Time.now - Time.now</code></p></blockquote>
<p>and then turning the time calculation code into:</p>
<blockquote><p><code>puts (Time.now - start_time - @@time_overhead).to_s + <font color="#ff0000">" seconds have elapsed."</font></code></p></blockquote>
<p>But that is not really relevant as trying <code>Time.now - Time.now</code> several times in irb returns very different values. That is because of the fact that it is run on a multitasked operating system, and that it is not possible to ensure that there will always be the same amount of time between the two calls of Time#now. Which means that measures are relevant when their <em>order</em> is bigger than the order of the scheduler&#8217;s overhead. When the order is not so different, only the <em>average</em> over several values is relevant.</p>
<p>A fix to this problem could be to focus only on how much <em>user time</em> has elapsed. Which is beyond the scope of this post.</p>
<br /><img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/asqyzeron.wordpress.com/5/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/asqyzeron.wordpress.com/5/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/asqyzeron.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/asqyzeron.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/asqyzeron.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/asqyzeron.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gofacebook/asqyzeron.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/facebook/asqyzeron.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gotwitter/asqyzeron.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/twitter/asqyzeron.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/asqyzeron.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/asqyzeron.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/asqyzeron.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/asqyzeron.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/asqyzeron.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/asqyzeron.wordpress.com/5/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=asqyzeron.wordpress.com&amp;blog=679580&amp;post=5&amp;subd=asqyzeron&amp;ref=&amp;feed=1" width="1" height="1" />]]></content:encoded>
			<wfw:commentRss>http://asqyzeron.wordpress.com/2007/01/14/toying-with-the-dynamic-features-of-ruby-adding-methods-at-run-time/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/2ed627672a22f41f0f8b0a7bf9614563?s=96&#38;d=identicon" medium="image">
			<media:title type="html">Asq-Yzeron</media:title>
		</media:content>
	</item>
	</channel>
</rss>
