27 October 2013

Needed to update OpenSSL Certificates as part of Ruby 2.0.0 install

[for some reason], when RVM installs Ruby 2.0.0 (MRI), it fails on dated certificates.  There's a simple fix, thanks to Michal Papis (currently from Engine Yard) for the fix and Daniel Kehoe (from the RailsApps Project) for pushing for a solution.

john@Slick:cliffschat [517]$ rvm install 2.0.0
Searching for binary rubies, this might take some time.
Checking requirements for osx.
Updating certificates in '/opt/local/etc/openssl/cert.pem'.
john password required for '/usr/bin/env PATH=/opt/local/bin:/Users/john/.rvm/gems/ruby-1.9.3-p448@chatter/bin:/Users/john/.rvm/gems/ruby-1.9.3-p448@global/bin:/Users/john/.rvm/rubies/ruby-1.9.3-p448/bin:/Users/john/.rvm/bin:/opt/local/sbin:/usr/local/heroku/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr/X11/bin:/Users/john/development/tools/apache-maven-3.0.4/bin:/Users/john/development/tools/sonar-runner-2.0/bin:/sbin:/usr/sbin:/usr/local/sbin mv -f /var/folders/by/fy0sbzy52xx8c23sgrd5n6t80000gn/T//tmp.zqrm6ETIUqreSbsocw /opt/local/etc/openssl/cert.pem': 

Not sure why, but RVM appears to be updating my OpenSSL certificate...

An explanation from Daniel Kehoe:

What is Happening

When creating a new Rails application, the Ruby language interpreter uses OpenSSL to connect to https://rubygems.org/. The Gemfile installed by the rails new command specifies https://rubygems.org/ as the source for gems and requires an SSL connection.
In the case of a new application generated from an application template hosted on GitHub, the Ruby language interpreter uses OpenSSL to connect to GitHub. GitHub requires all connections to be made using SSL.
The error message indicates the connection failed because OpenSSL was unable to verify the server certificate.
If you are seeing an error when you create a new Rails application, it is likely that you need to update OpenSSL certificate files on your computer. Users of older versions of Mac OS X and Ubuntu operating systems are likely to see these errors.
Check RubyGems issues on GitHub and look for recent updates to the issue SSL_connect failure when running ‘rails new’. You may find more information on Stack Overflow, especially this discussion: Bundle install fails with SSL certificate verification error. And please read thecomments below.




john@Slick:cliffschat [522]$ rvm osx-ssl-certs status all
Certificates for /System/Library/OpenSSL/cert.pem: Old.
Certificates for /opt/local/etc/openssl/cert.pem: Old.

john@Slick:cliffschat [523]$ rvm osx-ssl-certs update all
Updating certificates for /System/Library/OpenSSL/cert.pem: Updating certificates in '/System/Library/OpenSSL/cert.pem'.
Updated.
Updating certificates for /opt/local/etc/openssl/cert.pem: Updating certificates in '/opt/local/etc/openssl/cert.pem'.
Updated.

john@Slick:cliffschat [528]$ rvm install 2.0.0
Searching for binary rubies, this might take some time.
Found remote file https://rvm.io/binaries/osx/10.7/x86_64/ruby-2.0.0-p247.tar.bz2
Checking requirements for osx.
Certificates in '/opt/local/etc/openssl/cert.pem' already are up to date.
Requirements installation successful.
ruby-2.0.0-p247 - #configure
ruby-2.0.0-p247 - #download
#######################################################################   99.7%
ruby-2.0.0-p247 - #validate archive
ruby-2.0.0-p247 - #extract
ruby-2.0.0-p247 - #validate binary
ruby-2.0.0-p247 - #setup
Saving wrappers to '/Users/john/.rvm/wrappers/ruby-2.0.0-p247'........
ruby-2.0.0-p247 - #importing default gemsets, this may take time..........................

john@Slick:cliffschat [532]$ rvm --default use 2.0.0
Using /Users/john/.rvm/gems/ruby-2.0.0-p247

john@Slick:cliffschat [533]$ ruby -v
ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.5.0]

Voila!

25 October 2013

Great Article: class_eval and define_method, @tenderlove'd

Heard that Ruby is slow?  Heard that metaprogramming is slower?  They can be and it's up to you, developer, to make informed choices.

Aaron Patterson (@tenderlove) switched over the attribute class feature of ActiveSupport to use define_method rather than class_eval [git commit].  In it, he cites that doing so would "drop memory consumption and (increase) startup speed..."

This is of particular noteworthiness because, actually, this particular feature started out life using define_method.  And then circa 2009, Yehuda Katz specifically rewrote the code to use the class_eval style, noting that the class_eval was much easier to comprehend (agreed).  When someone says, "Yehuda Katz", think, "smart and prolific" [github].  So, reverting this work was no small move.

Unfortunately, Mr. Patterson didn't leave a crumb as to what led him to the performance difference conclusion.  So, I did a little digging.  Turns out, this is something that Aaron learned around March of this year (i.e. 2013).  And this is the main thing I want to direct your attention to: tenderlove's treatment of the topic:
http://tenderlovemaking.com/2013/03/03/dynamic_method_definitions.html
In it, Aaron carefully walks through, step by step, how to compare and detect the causes of the performance differences.  Along the way, I was introduced to a number of very helpful tools:

In his examination, Aaron is not satisfied with the performance of method definition, but digs into the performance of the dynamically generated methods, themselves (who might have thunk they'd be that different?).  Lots to learn from this:
  1. some mechanics of performance tuning in Ruby.
  2. how to write a high-signal blog post.  (great code-to-prose ratio, did I mention that?)
  3. ways to contribute to Open Source in addition to cutting code: help others level up.
Thank you, @tenderlove!


My teeny tiny OSS contribution?  I commented on Aaron's github commit with a link to his own blog post. :)

23 October 2013

Test-Driven Metaprogramming, by Example

If you've been following along in my blog, you'll know that the study group I attend is currently working our way through the Rebuilding Rails book, together.  In chapter 7, we tackle the meaty subject of ActiveRecord.  This one area where the metaprogramming facilities of Ruby really shine.

I wanted to tackle this work using Test-Driven Development.  There were some interesting challenges when it came to some required metaprogramming.  I learned a lot through the process.

The Story So Far...

Guided along by Noah's narrative, we have developed a core class called SQLiteModel — an ActiveRecord pattern implementation.  Application programmers would subclass for their concrete models and use the base functionality to find, create, update, and delete.  Each instance of this class corresponds directly to a row in the database.

Trimmed down (and mostly folded), here's the outline of the class, so far:

class SQLiteModel
  def self.connect(path_to_db)
    @db = SQLite3::Database.new path_to_db
    @dialect = SQLiteDialect.new table, schema
  end
  def self.table...
  def self.schema...
  def self.create(values)...
  def self.find_by_id(id)...
  def self.count...
  def [](attribute)...
  def []=(attribute, new_value)...
# def save
#   update_sql = @dialect.sql_for_update @values
#   @db.execute update_sql
# end
end
Listing 1 — sqlite_model.rb @ 3ae4ce6e7c.  Just as I tried to implement an instance method that wanted to access a metaclass variable.

As you can see, we can connect to a database, determine the name of the table that backs this specific SQLiteModel type, obtain schema information, insert new records, find records by id, find out how records there are and get/set values of individual rows.

(The experienced observer will note that @db and @dialect are not instance variables (i.e. variables specific to each instance of SQLiteModel).  You can tell because they are declared within a singleton method.  Therefore they are class variables.)

Things were going great!  However, when it came time to provide individual instances of SQLiteModel (i.e. objects that represent individual rows in the underlying table) with the ability to save changes, we hit a wall...

Accessing Singleton Class Instance Variables in Direct Instance Methods

# def save
#   update_sql = @dialect.sql_for_update @values
#   @db.execute update_sql
# end
Listing 2 — In sqlite_model.rb, the save() method.  This implementation won't work because @dialect and @db are instance variables on SQLiteModel's singleton class, not variables on individual instances. 

The problem here is that I want to access two variables defined at the class level: "@dialect" and "@db".

"A wall?!" my pair might say, "but all you have to do is provide an attribute reader on the singleton class and then call that reader."

"huh?," I would exclaim with a puzzled look on my face.  To which my partner would turn to the editor and write this:

class SQLiteModel
  def self.connect(path_to_db)
    @db = SQLite3::Database.new path_to_db
    @dialect = SQLiteDialect.new table, schema
  end
  
  def self.dialect
    @dialect
  end
  
  def self.db
    @db
  end

  ...
  
  def save
    update_sql = self.class.dialect.sql_for_update @values
    self.class.db.execute update_sql
  end
end
Listing 3 — In sqlite_model.rb, a straight-forward way for instances to access class singleton variables.

"ooooohhh!" I'd say, slapping my forehead.  But then we'd sit there and stair at those last two executable lines, trying not to think about how the "self.class." phrase would liter the codebase.  On the one-hand, rather literal ("my class' dialect attribute") but also perhaps a bit verbose (especially when repeated everywhere?).

The Essential Challenge

In effect we have discovered a new1 desired feature from the language.  Namely, in the same way that we can declare instance attributes (via attr_reader, attr_writer, or attr_accessor) that we would like to be able to declare a class attributes that is inherited by subclasses and accessible by instances.  Ruby is so pliable, we can actually add this feature to the language (and the Rails core team do so.  Here's a description of the feature: http://guides.rubyonrails.org/active_support_core_extensions.html#class-attributes )

So as to give credit where it's due, I had no idea of how that would be implemented.  Had I not had a working example in Rails (namely, https://github.com/rails/rails/blob/3-2-stable/activesupport/lib/active_support/core_ext/class/attribute.rb), at this point, I'd would have some spike work to do, personally.  But I'm lazy and so I read their code. :)

The Code

What follows is a test-driven approach to implementing class_attribute.  I originally did this in the following series of commits: https://github.com/jtigger/ruby-on-rulers/compare/3ae4ce6e7cc770dcf30fd645e340e81d560f28fc...7297d58f0a8d1a90a51d09653f654a47349110d7

Step 1: Setup and Teardown

In the first step, I had to discover how to clean-up class definitions so that the results of the unit tests were independent of each other.  Lee Jarvis posted a helpful technique to do this on Stackoverflow.  Here's how we do it in our unit tests...

class ClassExtTest < Test::Unit::TestCase
  def setup
    TestClasses.module_eval "class Foo; end"
    @foo = TestClasses::Foo.new
  end
  
  def teardown
    TestClasses.send(:remove_const, "Bar")
    TestClasses.send(:remove_const, "Foo")
  end
...
end
Listing 4 — A class definition can be "deleted" by calling remove_const on the containing module.

Step 2: Add Attribute Reader

And the next natural step is to begin using the class macro.  We create a private namespace (we'll call it TestClasses).

module TestClasses
end

class ClassExtTest < Test::Unit::TestCase
  ...  
  def test_class_attribute__creates_variable_reader_on_base_class
    TestClasses::Foo.class_eval "class_attribute :ree"
    assert_nil TestClasses::Foo.ree
  end
  ...
end
Listing 5 — the first test case.

which sets us up with the simplest thing that could possibly work:

class Class
  def class_attribute(attr)
    define_singleton_method(attr) { nil }
  end
end
Listing 6 — Monkey patching Class.  At first, we're just getting the attribute reader on the class.

We run it and the tests pass.  So far, so good. (git commit of steps 1 & 2)

Step 3: Verify the Class Attribute is Inherited 


class ClassExtTest < Test::Unit::TestCase
  def setup
    TestClasses.module_eval "class Foo; end"
    @foo = TestClasses::Foo.new
    TestClasses.module_eval "class Bar < Foo; end"
    @bar = TestClasses::Bar.new
  end
  ...
  def test_class_attribute__creates_variable_reader_on_subclass
    TestClasses::Foo.class_eval "class_attribute :ree"
    assert_nil TestClasses::Bar.ree
  end
  ...
end
Listing 7 — the second test case.

This one comes for free since public and protected methods defined on base classes are inherited by their subclasses.


Step 4: Add Attribute Writer

Building on what we've constructed thus far, we can both drive the ability to assign values to the class attribute and verify that it works for subclasses.

class ClassExtTest < Test::Unit::TestCase
  ...
  def test_class_attribute__GIVEN_subclass_has_no_value_defined_THEN_assignments_to_variable_applies_to_both_base_class_and_subclass
    TestClasses::Foo.class_eval "class_attribute :ree"
  
    TestClasses::Foo.ree = 42
  
    assert_equal 42, TestClasses::Foo.ree, "assignment failed for the base class"
    assert_equal 42, TestClasses::Bar.ree, "assignment worked for the base class, but not the subclass"
  end
  ...
end
Listing 8 — the third test case

However, as I got started down the road of implementing the assignment, I realized that I wanted to have the ability to remove methods (regardless of visibility):

class Class
  def class_attribute(attr)
    define_singleton_method(attr) { nil }
    
    # the writer simply redefines the reader
    define_singleton_method("#{attr}=") do |new_value|
      singleton_class.class_eval do
        # TODO: if "attr" is already defined, remove it...
        define_method(attr) { new_value }
      end
    end
  end
end
Listing 9 — I want to remove any existing definition of the writer method before redefining it.

Detour: Cleanly Removing Existing Methods

Out of the box, Ruby's Module class has a "undef_method", but if you call it for a method that does not exist, it raises an exception.  So, we'd like to check first that the method, in fact, exists; and if so, remove it.  But Module::method_defined?() only matches on public and protected methods, so to be thorough, we'd want to also call Module::private_method_defined?().  Not only is this getting a little complicated, but this is very likely something we'll be doing again and again.

So, I detoured: commented out the test in Listing 8, and set out to test-drive a method that would do just this...

class ModuleExtTest < Test::Unit::TestCase
  def setup
    TestClasses.module_eval "class Foo; end"
    @foo = TestClasses::Foo.new
  end
  
  def teardown
    @foo = nil
    TestClasses.send(:remove_const, "Foo")
  end
  
  def test_GIVEN_a_method_is_defined_on_a_module_THEN_remove_possible_method_undefines_it
    TestClasses::Foo.class_eval do
      public; def public_bar; nil; end
      protected; def protected_bar; nil; end
      private; def _private_bar; nil; end
    end
    
    assert TestClasses::Foo.method_defined?(:public_bar)
    assert TestClasses::Foo.method_defined?(:protected_bar)
    assert TestClasses::Foo.private_method_defined?(:_private_bar)
    
    TestClasses::Foo.class_eval do
      remove_possible_method :public_bar
      remove_possible_method :protected_bar
      remove_possible_method :_private_bar
    end
    
    assert !TestClasses::Foo.method_defined?(:public_bar), "expected method 'public_bar' to be removed, but it's still there."
    assert !TestClasses::Foo.method_defined?(:protected_bar), "expected method 'protected_bar' to be removed, but it's still there."
    assert !TestClasses::Foo.private_method_defined?(:_private_bar), "expected method '_private_bar' to be removed, but it's still there."
  end
  
  def test_GIVEN_a_method_is_NOT_defined_on_a_module_THEN_remove_possible_method_quietly_ignores
    TestClasses::Foo.class_eval do
      def ree
      end
    end
    foo = TestClasses::Foo.new
    assert !foo.respond_to?(:bar)
    
    TestClasses::Foo.class_eval do
      remove_possible_method :bar
    end
    
    assert !foo.respond_to?(:bar), "expected method 'bar' to be removed, but it's still there."
  end
end
Listing 10 — Specification of the "remove_possible_method" method.

Which, over the two iterations (we define and drive to one test at a time), yielded this monkey patch on Module:

class Module
  def remove_possible_method(name)
    if method_defined?(name) || private_method_defined?(name)
      undef_method(name)
    end
  end
end
Listing 11 — Adding remove_possible_method to Module.

With that new capability under our belts, we can now satisfy our attribute writer test (detour is captured in this commit: https://github.com/jtigger/ruby-on-rulers/commit/e3d24887128de2f1568011ce136e907807c44e9d):

class Class
  def class_attribute(attr)
    # define the reader
    define_singleton_method(attr) { nil }
    
    # the writer simply redefines the reader
    define_singleton_method("#{attr}=") do |new_value|
      
      singleton_class.class_eval do
        remove_possible_method(attr)
        define_method(attr) { new_value }
      end
    end
  end
end
Listing 12 — the first useful implementation of class_attribute.

Step 5: Ensure Writer Affects the Target Class Only

With all my current tests passing green, now is a good time to make sure we cover other highly important cases.  The most obvious one being to ensure that subclasses can override the value set in their super classes:

class ClassExtTest < Test::Unit::TestCase
  ...
  def test_class_attribute__GIVEN_subclass_HAS_a_value_defined_THEN_assignments_to_variable_applies_to_only_subclass
    TestClasses::Foo.class_eval "class_attribute :ree"
    
    TestClasses::Foo.ree = 42
    TestClasses::Bar.ree = 157
    
    assert_equal 42, TestClasses::Foo.ree, "assignment failed for the base class"
    assert_equal 157, TestClasses::Bar.ree, "assignment worked for the base class, but not the subclass"
  end
  ...
end
Listing 13 — An important use-case: assigning a value to the class attribute in the subclass.

As it turns out, this is how the implementation works, but it's lovely to make this fact plain and verifiable in a test.

Meanwhile... Back at the Ranch

And now we have just added a new feature to Ruby: the ability to define an attribute on a class that is inherited by subclasses and visible to direct instances.  Returning back to our original goal, now we can simply declare "db" and "schema" as class attributes...

class SQLiteModel
  class_attribute :db
  class_attribute :dialect
  
  def self.connect(path_to_db)
    self.db = SQLite3::Database.new path_to_db
    self.dialect = SQLiteDialect.new table, schema
  end
  ...
  def save
    update_sql = dialect.sql_for_update @values
    db.execute update_sql
  end
  ...
end
Listing 14 — SQLiteModel @ dcd61e9b8a5.  Class attributes simplify the syntax in this simplest case.  Not illustrated are the capabilities of subclasses to set their own value for these attributes.

And the syntax for using them is simplified.  That alone is almost reason to invest in this feature.  But there's more.  Even with the minimal implementation we did, here, subclasses of SQLiteModel can simply set their own value, overriding that for themselves.  This means Models default to sharing a DB connection, but can have different DB connections, if desired; same is true for dialect.

The story isn't over...

This is the starting point, not the conclusion.  In fact, there are a number of cases that we'll likely want to cover:
  • what about singleton classes?  does this code work properly if the class being decorated is one of those?
  • what about direct instances?  would it be useful for individual instances to also override the value for themselves (while allowing all the rest of the instances to continue to use the class-level value)?
  • since this is close to core language modification, perhaps we should be providing a means of determining if an instance has such an attribute (known as instance predicate methods).

Cheers!




1 Actually, this is a feature that Rails implements called "class_attribute".  This implementation has been all but lifted from their code (link at the bottom of the article.

20 October 2013

A Sliver of Ruby #4: The Ruby Language Specification — Objects and Classes

Having a rigorous language for describing the features of Ruby can be incredibly helpful, especially when reasoning metaprogramming code.

Such a rigorous definition exists and is defined in the Ruby Language Specification (published by the Japanese Information-technology Promotion Agency [IPA] in August, 2010).

At the core of the language are two fundamental concepts: objects and classes.

Here is a summary of their characteristics, capabilities and relationships:
  • everything in Ruby is an object (almost)1, even primitives and classes are objects.
  • objects have instance variables which hold that objects state (these bindings are always private).
  • there is a special kind of object known as a class.
    • classes (as an object) can have instance variables.
    • classes (and only classes) can also have constants.
    • classes (and only classes) can also have class variables.
    • classes (and only classes) also have methods which determine their behavior.
    • a class has one direct superclass.
  • classes have an associated collection of objects called direct instances.
    • direct instances have instance variables (but no other kind of variable binding)
    • direct instances obtain their behavior from their class; methods are never bound to them directly.
  • a class' instance variable is that class' own private state; whereas a class' class variables are state shared among the family of objects of that class (i.e. all subclasses and their direct instances).
  • there is a special kind of class known as a singleton class.
    • a singleton class is itself an object.
    • a singleton class is always associated with some other object.
      • the way this works is that the singleton class is inserted in between the object and its class.  E.g. if foo is a direct instance of Foo, then when an a singleton class is associated with foo, foo becomes a direct instance of that singleton class and that singleton class is a subclass of Foo.
    • In this association, then, the singleton class gets first crack at providing the behavior for that object.
      • this is how direct instances appear to have methods defined on them; that behavior is provided by the singleton class.
      • this is also how classes appear to have "class level methods"; these are merely methods defined on the singleton class for the given class.  In fact, this case is so common, that when a class is created, it comes complete with a singleton class, already.



1 — operators, blocks, and methods are not objects; although the last two can be wrapped in objects  (see also: http://stackoverflow.com/a/416154

06 October 2013

Moving a ClearCase Remote Client View

The ClearCase Remote Client Eclipse plugin does not include a feature to move a view (CC's term for a local working copy or checkout).  Thankfully, relocating a view is not difficult.

I ran into this problem, yesterday.  I joined a CC "project" which effectively means that I create two new streams and a view on each.  I'm on a windows machine for this work and I wanted to put my views close to the root of the drive.  I updated the path of my development stream, but forgot to do the same of my integration stream.

I had:

c:\clearcase\userj_proj1-v1
c:\Documents and Settings\userj\workspace\userj-proj1-v1_int

So I wanted to move that second view so that it becomes a sibling of the first.

Moving a ClearCase View

Turns out, it's two simple steps:

  1. Exit out of Eclipse/CCRC
  2. move the subtree to the new location in the file system,
  3. edit the .ccase_wvreg file (found in your user home directory) and update the path location.
  4. Restart Eclipse/CCRC.
In my case, .ccase_wvreg is located at c:\Documents and Settings\userj. It's merely a list of paths.

Reference

04 October 2013

Adventures In Native Extensions

It seemed like an innocent enough thing to do: install a gem.  But woe to the developer who assumes simplicity in a minefield of complexity!

I've reached Chapter 7 in "Rebuilding Rails" and it's been a fabulous ride, so far!  If you're an advanced beginning or competent Rails developer, going through Noah's guide is a wonderful way to deepen your understanding of what's really going on.

Anywho...

Attempt #1: gem install ... easy peazy! ... right?!

There I was, getting ready to start cutting code against the sqlite3 gem.  The next step was simply installing the gem.  Easy enough...

I simply added the gem to my project's gemspec:

<project-home>/rulers.gemspec:
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'rulers/version'

Gem::Specification.new do |spec|
  spec.name          = "rulers"
  spec.version       = Rulers::VERSION
  spec.authors       = ["John S. Ryan"]

...

  spec.add_runtime_dependency "sqlite3"
end

and ran bundle install...

john@Slick:ruby-on-rulers (master) [1345]$ bundle install
Fetching gem metadata from https://rubygems.org/..........
Fetching gem metadata from https://rubygems.org/..
Resolving dependencies...
Using rake (10.1.0) 
Using bundler (1.3.5) 
Using erubis (2.7.0) 
Using multi_json (1.8.0) 
Using rack (1.5.2) 
Using rack-test (0.6.2) 
Using require_all (1.3.1) 
Installing sqlite3 (1.3.8) 
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

        /Users/john/.rvm/rubies/ruby-1.9.2-p290/bin/ruby extconf.rb 
checking for sqlite3.h... *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
  .
  .
  .
/Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:368:in `try_do': The complier failed to generate an executable file. (RuntimeError)
You have to install development tools first.
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:452:in `try_cpp'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:853:in `block in find_header'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:693:in `block in checking_for'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:280:in `block (2 levels) in postpone'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:254:in `open'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:280:in `block in postpone'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:254:in `open'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:276:in `postpone'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:692:in `checking_for'
  from /Users/john/.rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/mkmf.rb:852:in `find_header'
  from extconf.rb:34:in `<main>'


Gem files will remain installed in /Users/john/.rvm/gems/ruby-1.9.2-p290@rulers/gems/sqlite3-1.3.8 for inspection.
Results logged to /Users/john/.rvm/gems/ruby-1.9.2-p290@rulers/gems/sqlite3-1.3.8/ext/sqlite3/gem_make.out

An error occurred while installing sqlite3 (1.3.8), and Bundler cannot continue.
Make sure that `gem install sqlite3 -v '1.3.8'` succeeds before bundling.


Native Extensions

If you're new to the Ruby environment, you might not yet be familiar with the fact that Ruby has native extensions.  Native extensions are pieces of code (written in C and compiled to shared libraries) that either need to run much faster than Ruby can be interpreted or needs access to OS resources not available directly through the Ruby VM.

For more details, find this gentle yet informative treatment here: http://patshaughnessy.net/2011/10/31/dont-be-terrified-of-building-native-extensions

What Happened?

Back to the output of our first attempt.  When encountering this output for the first time, it can be rather hard to read.  But I've highlighted some important elements for ya...

Three key clues:

  1. there's an additional log file that might have the next level of details: mkmf.log
  2. it's the extconf.rb script that failed (which, if you read that link in the previous section, you'd know that it's responsible for generating the Makefile) which means that some system dependency wasn't satisfied (e.g. a missing C header file or a build tool).
  3. the causing symptom is "...install development tools first."  (and "development tools" on Mac OS X, that's the Xcode command-line tools).

First, was somehow finding that mkmf.log.  I searched from the root of the RVM ruby I'm using:

$ find /Users/john/.rvm/rubies/ruby-1.9.2-p290 -name mkmf.log

At first glance, I didn't see anything that jumped out at me as a problem.

Xcode / extconf.rb Out of Sync

But then I googled it and stumbled into what  Dave Isaacs reported that in some versions of Xcode, the gcc compiler had a new prefix: llvm-gcc-4.2... and that the Ruby extensions configurator (extconf.rb) is using the old name gcc-4.2:  http://stackoverflow.com/a/10458609/1190801 (who rightfully credited Michael Cohen: http://frozencanuck.wordpress.com/tag/extconf-rb/ ).

I added the symlink which resolved that problem...

$ sudo ln -s /usr/bin/{llvm-,}gcc-4.2

Sidebar: that's a fun little bit of globbing.  it expands into:

$ sudo ln -s /usr/bin/llbm-gcc-4.2 gcc-4.2

Cool, eh?  :)


Attempt #2: Missing Libraries

With the symlink in place, I tried again...

john@Slick:ruby-on-rulers (master) [1360]$ bundle install
Fetching gem metadata from https://rubygems.org/..........
Fetching gem metadata from https://rubygems.org/..
Resolving dependencies...
Using rake (10.1.0) 
Using bundler (1.3.5) 
Using erubis (2.7.0) 
Using multi_json (1.8.0) 
Using rack (1.5.2) 
Using rack-test (0.6.2) 
Using require_all (1.3.1) 
Installing sqlite3 (1.3.8) 
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.

        /Users/john/.rvm/rubies/ruby-1.9.2-p290/bin/ruby extconf.rb 
checking for sqlite3.h... yes
checking for sqlite3_libversion_number() in -lsqlite3... yes
checking for rb_proc_arity()... yes
checking for sqlite3_initialize()... yes
checking for sqlite3_backup_init()... yes
checking for sqlite3_column_database_name()... no
checking for sqlite3_enable_load_extension()... no
checking for sqlite3_load_extension()... no
checking for sqlite3_open_v2()... yes
checking for sqlite3_prepare_v2()... yes
checking for sqlite3_int64 in sqlite3.h... yes
checking for sqlite3_uint64 in sqlite3.h... yes
creating Makefile

make
/usr/bin/gcc-4.2 -I. -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/x86_64-darwin10.8.0 -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/ruby/backward -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1 -I. -DHAVE_RB_PROC_ARITY -DHAVE_SQLITE3_INITIALIZE -DHAVE_SQLITE3_BACKUP_INIT -DHAVE_SQLITE3_OPEN_V2 -DHAVE_SQLITE3_PREPARE_V2 -DHAVE_TYPE_SQLITE3_INT64 -DHAVE_TYPE_SQLITE3_UINT64 -I/Users/john/.rvm/usr/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long  -fno-common -pipe  -o backup.o -c backup.c
/usr/bin/gcc-4.2 -I. -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/x86_64-darwin10.8.0 -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/ruby/backward -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1 -I. -DHAVE_RB_PROC_ARITY -DHAVE_SQLITE3_INITIALIZE -DHAVE_SQLITE3_BACKUP_INIT -DHAVE_SQLITE3_OPEN_V2 -DHAVE_SQLITE3_PREPARE_V2 -DHAVE_TYPE_SQLITE3_INT64 -DHAVE_TYPE_SQLITE3_UINT64 -I/Users/john/.rvm/usr/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long  -fno-common -pipe  -o database.o -c database.c
/usr/bin/gcc-4.2 -I. -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/x86_64-darwin10.8.0 -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/ruby/backward -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1 -I. -DHAVE_RB_PROC_ARITY -DHAVE_SQLITE3_INITIALIZE -DHAVE_SQLITE3_BACKUP_INIT -DHAVE_SQLITE3_OPEN_V2 -DHAVE_SQLITE3_PREPARE_V2 -DHAVE_TYPE_SQLITE3_INT64 -DHAVE_TYPE_SQLITE3_UINT64 -I/Users/john/.rvm/usr/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long  -fno-common -pipe  -o exception.o -c exception.c
/usr/bin/gcc-4.2 -I. -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/x86_64-darwin10.8.0 -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/ruby/backward -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1 -I. -DHAVE_RB_PROC_ARITY -DHAVE_SQLITE3_INITIALIZE -DHAVE_SQLITE3_BACKUP_INIT -DHAVE_SQLITE3_OPEN_V2 -DHAVE_SQLITE3_PREPARE_V2 -DHAVE_TYPE_SQLITE3_INT64 -DHAVE_TYPE_SQLITE3_UINT64 -I/Users/john/.rvm/usr/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long  -fno-common -pipe  -o sqlite3.o -c sqlite3.c
/usr/bin/gcc-4.2 -I. -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/x86_64-darwin10.8.0 -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1/ruby/backward -I/Users/john/.rvm/rubies/ruby-1.9.2-p290/include/ruby-1.9.1 -I. -DHAVE_RB_PROC_ARITY -DHAVE_SQLITE3_INITIALIZE -DHAVE_SQLITE3_BACKUP_INIT -DHAVE_SQLITE3_OPEN_V2 -DHAVE_SQLITE3_PREPARE_V2 -DHAVE_TYPE_SQLITE3_INT64 -DHAVE_TYPE_SQLITE3_UINT64 -I/Users/john/.rvm/usr/include -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE   -fno-common -O3 -ggdb -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long  -fno-common -pipe  -o statement.o -c statement.c
/usr/bin/gcc-4.2 -dynamic -bundle -o sqlite3_native.bundle backup.o database.o exception.o sqlite3.o statement.o -L. -L/Users/john/.rvm/rubies/ruby-1.9.2-p290/lib -L/Users/john/.rvm/usr/lib -L. -L/usr/local/lib -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -Wl,-flat_namespace  -lruby.1.9.1 -lsqlite3  -lpthread -ldl -lobjc 


make install
make: /opt/local/bin/gmkdir: No such file or directory
make: [/Users/john/.rvm/gems/ruby-1.9.2-p290@rulers/gems/sqlite3-1.3.8/lib/sqlite3/sqlite3_native.bundle] Error 1 (ignored)
/opt/local/bin/ginstall -c -m 0755 sqlite3_native.bundle /Users/john/.rvm/gems/ruby-1.9.2-p290@rulers/gems/sqlite3-1.3.8/lib/sqlite3
make: /opt/local/bin/ginstall: No such file or directory
make: *** [/Users/john/.rvm/gems/ruby-1.9.2-p290@rulers/gems/sqlite3-1.3.8/lib/sqlite3/sqlite3_native.bundle] Error 1

Gem files will remain installed in /Users/john/.rvm/gems/ruby-1.9.2-p290@rulers/gems/sqlite3-1.3.8 for inspection.
Results logged to /Users/john/.rvm/gems/ruby-1.9.2-p290@rulers/gems/sqlite3-1.3.8/ext/sqlite3/gem_make.out

An error occurred while installing sqlite3 (1.3.8), and Bundler cannot continue.
Make sure that `gem install sqlite3 -v '1.3.8'` succeeds before bundling.


Notice that extconf.rb succeeded, this time (green section).  And that the compilation even succeeded (cyan section).

Things started going wrong during the install step.  Specifically, two command-line tools are missing: /opt/local/bin/gmkdir and /opt/local/bin/ginstall.  I checked and sure enough, those files didn't exist on my machine.  What are they?  Where would I get them?

More Googling...

Installing coreutils

...I learned that gmkdir and ginstall are part of a package called coreutils.  Which turns out to be a pretty fundamental package that includes a whole bunch of GNU style tools for BSD-based Unix systems (and Darwin is a BSD variant).

http://thoughtsthatleakedout.blogspot.com/2011/10/problem-with-gmkdir-when-updating-gems.html

... and I took a wild guessed that this was the same package on MacPorts...

https://lists.macosforge.org/pipermail/macports-users/2010-September/022031.html

So, I installed coreutils...

john@Slick:.rvm [507]$ sudo port install coreutils
Password:
--->  Computing dependencies for gettext
--->  Fetching archive for gettext
--->  Attempting to fetch gettext-0.18.3.1_1.darwin_11.x86_64.tbz2 from http://packages.macports.org/gettext
--->  Attempting to fetch gettext-0.18.3.1_1.darwin_11.x86_64.tbz2.rmd160 from http://packages.macports.org/gettext
--->  Installing gettext @0.18.3.1_1
--->  Cleaning gettext
--->  Computing dependencies for gettext
--->  Deactivating gettext @0.18.3.1_0
--->  Cleaning gettext
--->  Activating gettext @0.18.3.1_1
--->  Cleaning gettext
--->  Fetching archive for gmp
--->  Attempting to fetch gmp-5.1.2_0.darwin_11.x86_64.tbz2 from http://packages.macports.org/gmp
--->  Attempting to fetch gmp-5.1.2_0.darwin_11.x86_64.tbz2.rmd160 from http://packages.macports.org/gmp
--->  Installing gmp @5.1.2_0
--->  Cleaning gmp
--->  Deactivating gmp @5.0.5_0
--->  Cleaning gmp
--->  Activating gmp @5.1.2_0
--->  Cleaning gmp
--->  Computing dependencies for coreutils
--->  Fetching archive for coreutils
--->  Attempting to fetch coreutils-8.21_0.darwin_11.x86_64.tbz2 from http://packages.macports.org/coreutils
--->  Attempting to fetch coreutils-8.21_0.darwin_11.x86_64.tbz2.rmd160 from http://packages.macports.org/coreutils
--->  Installing coreutils @8.21_0
--->  Activating coreutils @8.21_0

The tools provided by GNU coreutils are prefixed with the character 'g' by default to distinguish them from the BSD commands.
For example, cp becomes gcp and ls becomes gls.

If you want to use the GNU tools by default, add this directory to the front of your PATH environment variable:
    /opt/local/libexec/gnubin/

--->  Cleaning coreutils
--->  Updating database of binaries: 100.0%
--->  Scanning binaries for linking errors: 100.0%
--->  No broken files found.
john@Slick:.rvm [508]$ which ginstall
/opt/local/bin/ginstall


Cool, thankfully that step worked.  Now, to try again...

Attempt #3: Success!!!

With the symlink to gcc in place and the missing GNU tools installed, gave it one more go...


john@Slick:ruby-on-rulers (master) [1362]$ bundle install
Fetching gem metadata from https://rubygems.org/..........
Fetching gem metadata from https://rubygems.org/..
Resolving dependencies...
Using rake (10.1.0) 
Using bundler (1.3.5) 
Using erubis (2.7.0) 
Using multi_json (1.8.0) 
Using rack (1.5.2) 
Using rack-test (0.6.2) 
Using require_all (1.3.1) 
Installing sqlite3 (1.3.8) 
Using rulers (0.7.0) from source at . 
Your bundle is complete!
Use `bundle show [gemname]` to see where a bundled gem is installed.

Hurray!!!

Retrospective

Here's a few things I learned about troubleshooting in this process:

  • gather all your forensics (i.e. read through all of the logging output you can get your hands on);
  • learn the process at hand (knowing what extconf.rb was doing was hugely helpful);
  • where you're given the gift of full command lines that were executed and failed, go run those manually to see if you get more information/context;
  • If at first you don't find it, google, google again.


02 October 2013

A Sliver of Ruby #3: Nesting Scopes and Constant Name Resolution

I was plodding my way along The Path To Enlightenment, this morning (ruby koans), and I was rather stumped on the following:

class Animal
  LEGS = 4
  def legs_in_animal
    LEGS
  end
end

class MyAnimals
  LEGS = 2

  class Bird < Animal
    def legs_in_bird
      LEGS
    end
  end
end

class MyAnimals::Oyster < Animal
  def legs_in_oyster
    LEGS
  end
end

def test_who_wins_with_both_nested_and_inherited_constants
  assert_equal 2, MyAnimals::Bird.new.legs_in_bird
end

def test_who_wins_with_explicit_scoping_on_class_definition
  assert_equal 4, MyAnimals::Oyster.new.legs_in_oyster
end

Notice that in the first test, the lexical scope wins, but in the second test, the inheritance hierarchy wins...and I was baffled as to why...

Turns out that, constant names are resolved in the following order (according to zetetic):
  1. the enclosing scope
  2. the outer scope (if any)
  3. included modules
  4. the superclass
  5. the class Object
  6. the class Kernel
And also referenced this complete example:


The bottom-line answer to my question is: the syntax used to declare Oyster (i.e. using the qualified name as opposed to re-opening MyAnimals and nesting Oyster within) specifically means that it does not participate in the lexical scope of MyAnimals, it's merely sharing namespace.  There's no outer scope for Oyster and therefore the name resolution makes it all the way down to the 4th source.

It's the difference between this:

class MyAnimals::Oyster < Animal
  def legs_in_oyster
    LEGS
  end
end

and this:

class MyAnimals
  class Oyster < Animal
    def legs_in_oyster
      LEGS
    end
  end
end