<?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/"
	>

<channel>
	<title>~clay &#187; ruby</title>
	<atom:link href="http://daemons.net/~clay/tag/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://daemons.net/~clay</link>
	<description>merely my musings</description>
	<lastBuildDate>Mon, 10 May 2010 17:48:58 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>The various flavors of Ruby class attributes</title>
		<link>http://daemons.net/~clay/2009/05/16/the-various-flavors-of-ruby-class-attributes/</link>
		<comments>http://daemons.net/~clay/2009/05/16/the-various-flavors-of-ruby-class-attributes/#comments</comments>
		<pubDate>Sun, 17 May 2009 04:57:38 +0000</pubDate>
		<dc:creator>clay</dc:creator>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Geek]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://daemons.net/~clay/?p=292</guid>
		<description><![CDATA[Here&#8217;s a curious thing about Ruby: it&#8217;s got three flavors of class attributes. You can adorn your classes with class variables, class instance variables, and class constants. Not knowing the differences between them, and thinking that one of them might be useful for a project I was working on, I set out to figure out [...]]]></description>
			<content:encoded><![CDATA[<p>Here&#8217;s a curious thing about Ruby: it&#8217;s got three flavors of class attributes. You can adorn your classes with class variables, class instance variables, and class constants. Not knowing the differences between them, and thinking that one of them might be useful for a project I was working on, I set out to figure out how they all worked, especially with respect to inheritance.</p>
<p>As a trivial example of the design scenario I was working with, consider the case of an object-oriented vegetable garden. Vegetables come in all shapes, sizes, and colors, but we might want to say that all vegetables should be green unless we&#8217;ve said otherwise. We might start modeling our vegetable garden with a <code>Vegetable</code> class, and we could set a <code>color</code> attribute on it with a default value of <code>"green"</code>. <code>Lettuce</code>, which happens to be green, could inherit that attribute from <code>Vegetable</code>. <code>Eggplant</code>, however, should redefine <code>color</code> to be <code>"purple"</code>. </p>
<p>While certainly a contrived and flawed example, it demonstrates the behavior I was looking for. Let&#8217;s see how Ruby&#8217;s various flavors of class attributes can help us solve this design problem &#8212; or not.</p>
<p>First up, class variables:</p>
<pre class="brush: ruby;">
class Vegetable
  @@color = 'green'
  def color
    @@color
  end
end

class Eggplant &lt; Vegetable
  @@color = 'purple'
end

Vegetable.new.color  # =&gt; &quot;purple&quot;
Eggplant.new.color   # =&gt; &quot;purple&quot;
</pre>
<p>I wasn&#8217;t expecting that! Apparently class variables are shared among subclasses, so you can&#8217;t redefine their value in subclasses without changing the value in the base class.</p>
<p>Next up, class instance variables:</p>
<pre class="brush: ruby;">
class Vegetable
  @color = 'green'
  class &lt;&lt; self
    attr_reader :color
  end
  def color
    self.class.color
  end
end

class Lettuce &lt; Vegetable
  # no need to set @color here, since lettuce is green ... right?
end

Vegetable.new.color  # =&gt; &quot;green&quot;
Lettuce.new.color    # =&gt; nil
</pre>
<p>No love here, either: class instance variables are not accessible from subclasses at all. Probably for the better, since the code needed to access class instance variables from instances is even uglier than that needed to access class variables from instances.</p>
<p>Class constants are right out:</p>
<pre class="brush: ruby;">
class Vegetable
  Color = 'green'
  def color
    Color
  end
end

class Eggplant &lt; Vegetable
  Color = 'purple'
end

Vegetable.new.color  # =&gt; &quot;green&quot;
Eggplant.new.color   # =&gt; &quot;green&quot;
</pre>
<p>Class constants are statically bound, so the polymorphic call to Vegetable#color from an Eggplant instance references the Color constant defined in Vegetable, not the one defined in Eggplant.</p>
<p>Giving up on the class attributes approach, I resorted to defining the attributes at the instance level. I considered explicitly setting a <code>@color</code> instance variable in the class <code>initialize</code> method, but then the attribute wouldn&#8217;t be constant. Instead, the simplest implementation that does what I want seems to be to use methods that return constant values:</p>
<pre class="brush: ruby;">
class Vegetable
  def color
    'green'
  end
end

class Lettuce &lt; Vegetable
end

class Eggplant &lt; Vegetable
  def color
    'purple'
  end
end

Vegetable.new.color  # =&gt; &quot;green&quot;
Lettuce.new.color    # =&gt; &quot;green&quot;
Eggplant.new.color   # =&gt; &quot;purple&quot;
</pre>
<p>So as it turns out, each of Ruby&#8217;s class attribute mechanisms behaves differently in subclasses. I&#8217;m sure class variables, class instance variables, and class constants have their utility, but they aren&#8217;t useful for defining constant attributes shared by all instances of a class, but which can be redefined in subclasses.</p>
]]></content:encoded>
			<wfw:commentRss>http://daemons.net/~clay/2009/05/16/the-various-flavors-of-ruby-class-attributes/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Ruby, why do you torment me?</title>
		<link>http://daemons.net/~clay/2009/05/03/ruby-why-do-you-torment-me/</link>
		<comments>http://daemons.net/~clay/2009/05/03/ruby-why-do-you-torment-me/#comments</comments>
		<pubDate>Sun, 03 May 2009 17:39:03 +0000</pubDate>
		<dc:creator>clay</dc:creator>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Geek]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://daemons.net/~clay/?p=91</guid>
		<description><![CDATA[I want to like Ruby, I really do. The language is expressive, powerful, and eminently readable. Moreover, it&#8217;s fun to write. But try as I might to be productive, I keep running into quirks and gotchas with Ruby libraries that make we wish I was using a language with a more mature standard library. Things [...]]]></description>
			<content:encoded><![CDATA[<p>I want to like Ruby, I really do. The language is expressive, powerful, and eminently readable. Moreover, it&#8217;s fun to write. But try as I might to be productive, I keep running into quirks and gotchas with Ruby libraries that make we wish I was using a language with a more mature standard library. Things that take five minutes in Perl or Python have taken me all day to get working in Ruby.</p>
<p>SOAP support, which ought to be fully baked in Ruby by now, is still somewhat painful to work with. In Perl, SOAP just works. When I wrote our release orchestration tool a year ago, it took way longer than it should have to get Ruby talking to the SOAP iControl interface on our BigIP load balancers. By contrast, it took all of five minutes to get the Perl sample working &#8212; and that includes time spent installing the <code>SOAP::Lite</code> CPAN module.</p>
<p>Using Rails for the first time in a recent project, I was immediately struck by how little work is required to get a web app off the ground. I almost felt guilty for writing so little code. But a lot of the clever Rails magic that&#8217;s supposed to make life easier, didn&#8217;t. While error messages like, &#8220;<a href="http://blog.teksol.info/2007/03/09/expected-x-to-define-y-error">Expected foo.rb to define Foo</a>&#8221; seem pretty straight-forward, they are maddening when foo.rb does indeed define Foo. For their next trick, the Rails developers ought to use their meta-programming fu to produce intelligible error messages! <img src='http://daemons.net/~clay/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>We recently ported a Rails app to JRuby, and straight away we ran into bugs. JRuby couldn&#8217;t call Java correctly, and it had a file descriptor leak in Net::SSH that caused the site crawler component of our application to go belly-up after a few hours. And we should have known better than to try talking to Oracle from JRuby on Rails. The <code>activerecord-jdbc-adapter</code> component had myriad issues &#8212; goofy things like <code>"uninitialized constant ActiveRecord::VERSION"</code>, improper column name quoting, and incorrect integer datatype coercions. Finally we gave up and ported the database to MySQL.</p>
<p>I understand that Ruby and its libraries are open-source efforts written mostly by unpaid enthusiasts, so I try not to get too upset when things don&#8217;t work correctly. I wish I had the time to jump in and submit patches to fix issues when I run into them.</p>
]]></content:encoded>
			<wfw:commentRss>http://daemons.net/~clay/2009/05/03/ruby-why-do-you-torment-me/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>setuid() ate my CSS</title>
		<link>http://daemons.net/~clay/2009/05/02/setuid-ate-my-css/</link>
		<comments>http://daemons.net/~clay/2009/05/02/setuid-ate-my-css/#comments</comments>
		<pubDate>Sat, 02 May 2009 10:15:35 +0000</pubDate>
		<dc:creator>clay</dc:creator>
				<category><![CDATA[Engineering]]></category>
		<category><![CDATA[Systems Management]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[setuid]]></category>

		<guid isPermaLink="false">http://daemons.net/~clay/?p=244</guid>
		<description><![CDATA[We ran into an interesting problem while testing a new version of our code deployment tool tonight. By all appearances, the tool was happily deploying code and launching our Java applications, but one of our QA engineers noticed missing CSS on some pages in our test environment. Could that possibly be related to the code deployment tool, which essentially just untars an archive and forks off a little ruby script to start the application?]]></description>
			<content:encoded><![CDATA[<p>We ran into an interesting problem while testing a new version of our code deployment tool tonight. By all appearances, the tool was happily deploying code and launching our Java applications, but one of our QA engineers noticed missing CSS on some pages in our test environment. Could that possibly be related to the code deployment tool, which essentially just untars an archive and forks off a little ruby script to start the application?</p>
<p>Tracing the application&#8217;s system calls with truss revealed that the process was getting EPERM errors while trying to read the CSS files, which live on NFS. One of our more clever engineers decided to start up the application manually, not via the code deployment tool, and found that the CSS loaded just fine when the Java process was invoked directly from the shell. He compared user and group ids, as reported by ps, of JVMs started by our tool and those started manually and found no differences. Hmm.</p>
<p>When looking at the processes&#8217; <code>/proc/&lt;pid&gt;/cred</code> files, however, some differences were apparent. The <code>cred</code> file contains binary data and is best viewed with <code>od</code>:</p>
<p><code><br />
$ od -X /proc/$$/cred<br />
0000000 00002716 00002716 00002716 0000000a<br />
0000020 0000000a 0000000a 00000002 0000000a<br />
0000040 0000000e<br />
0000044<br />
</code></p>
<p>The file consists of a sequence of 32-bit id values in the following order:</p>
<p>* uid<br />
* euid<br />
* suid<br />
* gid<br />
* egid<br />
* sgid<br />
* supplemental group ids &#8230;</p>
<p>You can see how that maps to decimal ids by comparing with <code>id</code> output:</p>
<p><code><br />
$ id -a<br />
uid=10006(clay) gid=10(staff) groups=10(staff),14(sysadmin)<br />
</code></p>
<p>[Solaris geek aside: remember when you wanted to be a member of the sysadmin group so you could run the handy-dandy admintool?]</p>
<p>So what we noticed was that while the manually started JVM and the JVM launched via our code deployment tool had identical uid/euid/sgid and gid/egid/sgid values, they had different supplemental group id lists. Notably, the JVM running under the code deployment tool still had a gid of 0 in its supplemental group list. Letting our Java application servers traipse around the filesystem with elevated privileges is perhaps not the best &#8220;feature&#8221; we&#8217;ve ever implemented.</p>
<p>Trust but verify might be a good foreign policy, but our NFS server wasn&#8217;t having any of it. It thoroughly distrusted the Java app servers claiming to have elevated privileges, and rewarded them with EPERMs for their trouble. Root squash is, after all, a pretty common NFS security measure.</p>
<p>As it turns out, I had implemented a new feature in the code deployment agent to make it switch user id on startup. Previously we handled the user switch by launching the tool under <code>su</code>, but that approach prevented the tool from writing its pid file to the root-owned /var/run directory. The solution, I thought, was just to call <code>setgid()</code> followed by <code>setuid()</code>. We tested that code by verifying the user and group ids with <code>ps</code>, and it seemed to work just great.</p>
<p>Quick: what&#8217;s wrong with this?</p>
<pre class="brush: ruby;">
    def HostUtils.switch_user user
      pwent = Etc::getpwnam(user)
      Process::GID::change_privilege(pwent.gid)
      Process::UID::change_privilege(pwent.uid)
    end
</pre>
<p>Maybe several things, but certainly one thing is that I&#8217;ve completely neglected supplemental group ids. I should have written:</p>
<pre class="brush: ruby;">
    def HostUtils.switch_user user
      pwent = Etc::getpwnam(user)
      Process::initgroups(user, pwent.gid)
      Process::GID::change_privilege(pwent.gid)
      Process::UID::change_privilege(pwent.uid)
    end
</pre>
<p>That call to <a href="http://www.ruby-doc.org/core/classes/Process.html#M003208">Process::initgroups</a> makes all the difference. After making the change, the apps could access NFS and our test site looked all pretty again. Good thing we caught it when we did!</p>
<p>Turns out this is a fairly <a href="http://www.ruby-forum.com/topic/110492">common problem</a>, and I feel especially dumb for overlooking something so obvious. Live and learn.</p>
]]></content:encoded>
			<wfw:commentRss>http://daemons.net/~clay/2009/05/02/setuid-ate-my-css/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
