Showing posts with label Ruby. Show all posts
Showing posts with label Ruby. Show all posts
Saturday, November 28, 2009

Compiling Ruby 1.9 for Mac OSX 10.4

This article contains specifics for installing Ruby on PowerPC MacOSX 10.4. Newer Intel Macs with > 10.4 OS has more updated dependencies and probably do not require the instructions described here; you shouldn't need to compile from source in that case as well - there are one-click installers for binaries for Ruby 1.9 on the Internet, look for it.

On 10.4 PPC, the default version of Ruby is 1.8.2. This version is now old for some of the ruby plugins to be installed, specifically rubygems 1.3.5 in my case. I won't go into the reasons here on not going for older versions of rubygems (Read here if you are really interested why), but since an upgrade of Ruby is warranted, instead of upgrading to the latest 1.8.x series, it might be worthwhile to try out the new features from the 1.9.x series instead.

In order to recompile ruby, you'll need Xcode from Apple. That will install the SDK for developing on Apple's MacOS, but more importantly, it contains the gcc part of the GNU toolchain required for compilation.

However the GNU toolchain is incomplete at this stage; we'll require at the minimum GNU m4, autoconf and automake to complete the chain of dependencies Ruby needs.

Not Using Darwin Port/Fink

I'm going to compile these things from source directly without any package management system, and for a good reason; 3rd party MacOS package management systems are usually more trouble than it's worth, either having longer compilation time from spurious dependencies, compilation breakages due to improperly configured parameters or missing specific compiler flags that you'll end up having to fix by hand anyway.

That said, don't be put off by the exercise of compiling from scratch. It is not difficult, and you'll get to learn a thing or two about the internals of your OS.

Open up your terminal, and sudo into root:


Tigershark:~ vince$ sudo -i
Password:
Tigershark:~ root#


In order to separate your newly compiled stuffs from your existing binaries, I recommend you create a separate directory under the '/' directory so that they will be cleanly partitioned. I'm using the directory '/lfs' in my example here, as a tribute to the Linux from Scratch project, where I got my derivative knowledge from. Feel free to choose your own directory names though.


Tigershark:~ root# export LFS=/lfs
Tigershark:~ root# echo "export PATH=$LFS/bin:$PATH" >> /Users/YOURUSERNAME/.profile
Tigershark:~ root# export PATH=$LFS/bin:$PATH
Tigershark:~ root# mkdir -p $LFS/src
Tigershark:~ root# cd $LFS/src


The code above creates the /lfs directory, and the '/lfs/src' directory as well. It also sets up the PATH environment to firstly look in '/lfs/bin' before it searches all other paths. This is necessary so that you'll be using your new binaries instead of the old system binaries. The same change is added into your user's .profile file so that Terminal will know to look for the new binaries in the future when it starts up.

Installing m4


Tigershark:/ root# cd $LFS/src
Tigershark:/lfs/src root# curl http://ftp.gnu.org/gnu/m4/m4-1.4.9.tar.gz > m4-1.4.9.tar.gz
Tigershark:/lfs/src root# tar -zxvf m4-1.4.9.tar.gz
Tigershark:/lfs/src root# cd m4-1.4.9
Tigershark:/lfs/src/m4-1.4.9 root# ./configure --prefix=$LFS
Tigershark:/lfs/src/m4-1.4.9 root# make && make check


Make sure that the test results come up without any errors. When the test results are satisfied, install it.


Tigershark:/lfs/src/m4-1.4.9 root# make install


Installing autoconf


Tigershark:/ root# cd $LFS/src
Tigershark:/lfs/src root# curl http://ftp.gnu.org/gnu/autoconf/autoconf-2.65.tar.gz > autoconf-2.65.tar.gz
Tigershark:/lfs/src root# tar -zxvf autoconf-2.65.tar.gz
Tigershark:/lfs/src root# cd autoconf-2.65
Tigershark:/lfs/src/autoconf-2.65 root# ./configure --prefix=$LFS
Tigershark:/lfs/src/autoconf-2.65 root# make && make check


Make sure that the test results come up without any errors. When the test results are satisfied, install it.


Tigershark:/lfs/src/autoconf-2.65 root# make install


Installing automake


Tigershark:/ root# cd $LFS/src
Tigershark:/lfs/src root# curl http://ftp.gnu.org/gnu/automake/automake-1.9.6 > automake-1.9.6.tar.gz
Tigershark:/lfs/src root# tar -zxvf automake-1.9.6.tar.gz
Tigershark:/lfs/src root# cd automake-1.9.6
Tigershark:/lfs/src/automake-1.9.6 root# ./configure --prefix=$LFS
Tigershark:/lfs/src/automake-1.9.6 root# make && make check


Make sure that the test results come up without any errors. When the test results are satisfied, install it.


Tigershark:/lfs/src/automake-1.9.6 root# make install


Additional Step: Upgrading libreadline

Apple's implementation of the readline library has missing symbols in which Ruby (or more accurately, irb) requires in order to retrieve command line history. If you do not use irb (which I doubt, unless you never require testing some code you're uncertain of), you may skip compiling this. But I recommend you do :)


Tigershark:/ root# cd $LFS/src
Tigershark:/lfs/src root# curl http://ftp.gnu.org/gnu/readline/readline-6.0.tar.gz > readline-6.0.tar.gz
Tigershark:/lfs/src root# tar -zxvf readline-6.0.tar.gz
Tigershark:/lfs/src root# cd readline-6.0

Tigershark:/lfs/src/readline-6.0 root# curl http://ftp.gnu.org/gnu/readline/readline-6.0-patches/readline60-001 > readline60-001
Tigershark:/lfs/src/readline-6.0 root# curl http://ftp.gnu.org/gnu/readline/readline-6.0-patches/readline60-002 > readline60-002
Tigershark:/lfs/src/readline-6.0 root# curl http://ftp.gnu.org/gnu/readline/readline-6.0-patches/readline60-003 > readline60-003
Tigershark:/lfs/src/readline-6.0 root# curl http://ftp.gnu.org/gnu/readline/readline-6.0-patches/readline60-004 > readline60-004
Tigershark:/lfs/src/readline-6.0 root# patch -p0 < readline60-001
Tigershark:/lfs/src/readline-6.0 root# patch -p0 < readline60-002
Tigershark:/lfs/src/readline-6.0 root# patch -p0 < readline60-003
Tigershark:/lfs/src/readline-6.0 root# patch -p0 < readline60-004

Tigershark:/lfs/src/readline-6.0 root# ./configure --libdir=/usr/local/lib
Tigershark:/lfs/src/readline-6.0 root# make && make check


The instructions also contains the additional patches that was released since libreadline 6.0. Make sure you follow those additional instructions to apply the patches correspondingly.

Also, note that the ./configure parameter has changed. In this case, we are installing a library, so the path to install to is different. We are installing it to '/usr/local/lib', which will make sure that we won't conflict with the original libreadline in '/usr/lib'.

Finally, make Ruby!


Tigershark:/ root# cd $LFS/src
Tigershark:/lfs/src root# curl ftp://ftp.ruby-lang.org/pub/ruby/1.9/ruby-1.9.1-p243.tar.gz > ruby-1.9.1-p243.tar.gz
Tigershark:/lfs/src root# tar -zxvf ruby-1.9.1-p243.tar.gz
Tigershark:/lfs/src root# cd ruby-1.9.1-p243
Tigershark:/lfs/src/ruby-1.9.1-p243 root# ./configure --prefix=$LFS LDFLAGS=-L/usr/local/lib
Tigershark:/lfs/src/ruby-1.9.1-p243 root# make && make install


Note the additional parameter 'LDFLAGS=-L/usr/local/lib' that we pass to './configure'. This is required so that when ruby gets compiled, it'll first search '/usr/local/lib' for it's library dependencies before looking at its system default paths. Because we have our new 'libreadline' installed, this makes sure that Ruby is compiled with our newer library instead of the system one.

Congratulations! Once you've reached here, you have your new shiny Ruby 1.9 interpreter to play with! To check:


Tigershark:/ root# which ruby
/lfs/bin/ruby
Tigershark:/ root# ruby --version
ruby 1.9.1p243 (2009-07-16 revision 24175) [powerpc-darwin8.11.0]
Thursday, January 29, 2009

Ways of Solving the Slow Gem Install Problem

I've written previously on how slow gem install was, which has been causing me much annoyance. But the tradeoff of having ease of installation for all the useful libraries that Ruby offers is just too hard to not fall back to using Ruby Gems again.

There are a few ways of solving the issue, which depends on which version of Rubygems you are using. Find this out by issuing the following command:


% gem -v

If you are using gem version < 1.2.0

The best way of solving this problem in this case is to install the gem directly from source, thereby bypassing the database load problem, e.g. getting stuck at this message for a long, long time:


% gem install curb
Bulk updating Gem source index for: http://gems.rubyforge.org/

For example, I wanted to install Ruby's version of libCurl called 'curb', to which the way in installing it while avoiding the database load by downloading the gem and installing it locally:


% wget http://rubyforge.org/frs/download.php/23825/curb-0.1.4.gem
% gem install --local curb-0.1.4.gem
Building native extensions. This could take a while...
Successfully installed curb-0.1.4
1 gem installed
Installing ri documentation for curb-0.1.4...
Installing RDoc documentation for curb-0.1.4...

That should take you less than 30 seconds, as opposed to 30 minutes if you waited for the silly gem database to load.

Use gem version = 1.2.0

The other way of solving this problem, is to use gem version 1.2.0. It has taken away the unnecessary function for the database to load, and goes straight into the task of installing the gem. To upgrade your ruby gem to the latest version, download it locally and give it an upgrade:


% wget http://rubyforge.org/frs/download.php/38844/rubygems-update-1.2.0.gem
% gem install rubygems-update-1.2.0.gem
Successfully installed rubygems-update-1.2.0
1 gem installed
% update_rubygems

[.. tons of install messages ..]

= Announce: RubyGems Release 1.2.0

Release 1.2.0 adds new features and fixes some bugs.

New features:

* RubyGems no longer performs bulk updates and instead only fetches the gemspec
files it needs. Alternate sources will need to upgrade to RubyGems 1.2 to
allow RubyGems to take advantage of the new metadata updater. If a pre 1.2
remote source is in the sources list, RubyGems will revert to the bulk update
code for compatibility.

[.. more install messages ..]

Yay! From their release notes, the problem has been addressed, but it's only a fix according to the authors.

Not by a sliver of chance am I convinced that they are able to reconcile the problem with their bulk update system, so I will stay with 1.2.0 for a long, long time, thank you very much!
Thursday, November 06, 2008

If you think Rubygem is slow, that's because it is


Update: This there is a solution for the slow rubygem problem now, please see Ways of Solving the Slow Gem Problem instead.


If there is a good example of bad software, Ruby's Gem package management system has to be it. I can't say how much irritation I've had every single time I had to do a gem installation, and I've really lost count of the times that I had given up waiting for it to complete execution.

It's incredible just how much memory that rubygem requires to work. I can't even use it on my laptop with 512M of memory, when if it's enough to run an entire operating system with all daily use applications, it should be enough for a package management system. But how very wrong I am! Rubygem uses so much memory that it swaps a gigantic amount of data into virtual memory, trashing my harddisk and driving my laptop into a state of near unresponsiveness. (Of course, that would have meant nothing if I was running Windows, but it's certainly nothing less of an amazing feat when it can bring down a Linux box.)

Perhaps it's time to start classifying rubygem as a DOS malware?

Since I couldn't get the bloody thing to run on my laptop to show you a measurement of how slow it is, I had to resort to using my higher-end desktop that has 1.5GB of RAM in it. Here's the result from the output from 'top':


To help you understand how much of a memory hog rubygem is, I've underlined in red how much memory it's been consuming. If you take a glance at the row underlined in red, that indicates rubygem using up 359M of RAM, which is even more than a well-known memory-hog, Netbeans, which uses up 273M of RAM (underlined in blue, where Netbeans is shown as a single Java instance.) Also, as you see from the screenshot, besides being a memory hog, rubygem was 47 minutes in execution and it still hadn't completed installing the gem that I've instructed it to.

I'm certainly not the only person encountering problems with rubygem, and so far, there aren't any solutions in resolving the situation. Plenty of unhelpful advices I've been able to google up, which include things like updating rubygems (I already have, till the latest version of 1.1.1), and other discussions and solutions that just don't work[1][2].

To quote Charles Nutter, a core developer of JRuby:
"Even on a high-end box, it's so intolerably slow that there's got to be a key fault keeping the speed down."

That observation was made in 2006. If you've noticed the result from his execution, it took rubygem 62 minutes to complete execution, not unlike what I've observed myself, but two years later. And that's just dismaying.

To put it simply, Rubygem is just a piece of rotten software - avoid using it like plague. If a package management system like Debian's Apt can deal with the entire ecosystem of Linux software packages without chewing up massive amount of computer resources to do it, it's certainly no excuse for a smaller universe of packages like Ruby to perform that much substantially worse.

References:
[1] gem install SUPER SLOW in linux virtual machine
[2] trouble with slow rubygems
Saturday, May 24, 2008

Multiple return values and assignments in Ruby

One of the things that I really liked about Ruby which extends to those non old-school computing languages as well, is the capability to return multiple values. For example:
def foo(x)
return x, x+1
end

a, b = foo (10)
#=> [10, 11]


a
and b automatically gets assigned to the values returned by the function. Besides this, Ruby has the ability to define how variables are being assigned as well. For example:

a, b, c = [1, 2, 3, 4]
p a, b, c
1
2
3

a, b, *c = [1, 2, 3, 4]
p a, b, c
1
2
[3,4]


Notice the asterisk(*) before the c variable, where the remaining values of 3 and 4 got assigned into the variable c as an array. Neat!
Saturday, February 23, 2008

Ruby Code Snippets #3

Here's a simple Ruby code puzzle for you: if an argument is optional in Ruby, what do you think the result of the method would be if you passed 'nil' to arg2?
def mymethod(arg1, arg2='default')
arg2
end
Well, (as expected?) if you pass a nil as an argument, then there is something being passed, and hence 'default' won't be passed:
mymethod('foo', nil) #=> nil
And if you passed it just a single argument, here's what it'll look like:
mymethod('foo') #=> 'default'
Friday, February 22, 2008

Helpful Methods for Ruby Debugging

Just something which may help you when trying to figure out what Ruby object you're dealing with:
object.methods   #-> returns all the available methods
object.inspect #-> returns information about the object
object.ancestors #-> where the ruby object inherits from
Thursday, February 21, 2008

Ruby Code Snippets #2

One thing I like about more 'recent' programming languages like Ruby is the ability to have multiple argument assignments, ie:
 var1, var2 = %w{ a b c }
#=> var1 = "a", var2 = "b"

var1, *var2 = %w { a b c }
#=> a = "a", b = [ "b", "c" ]
The first example, "c" vanished into the ether, while the second example, the remainder of [ "b", "c" ] is stored into var2. Multiple variable assignments isn't unique to Ruby by the way, I do know that Perl does it too, but I think that it is just that it always defaults to the second example behaviourally.

It's nice that the syntax allows you to choose between what you want and do not want.
Tuesday, February 19, 2008

Ruby Code Snippets #1

Here's yet another reason I find ruby so easy to code. Lets assume that you want to do filtering of a certain kind of input that is demarcated by 'START' and 'END' on a separate line by itself. Let's use an example like the data shown below:
This is an unwanted line 1.
This is an unwanted line 2.
START
This is a wanted line 1.
This is a wanted line 2.
END
This is an unwanted line 3.
This is an unwanted line 4.
Normally, the typical way of segregating the wanted lines with the unwanted ones is probably via writing code that logically looks something like this:
in_header = false         # variable to remember whether if in_header
while line = STDIN.gets
if line =~/^START$/ # found header, start trapping
in_header = true
elsif line =~/^END$/ # end header, stop trapping
print line # have to print the line boundary inclusive
in_header = false
end
if in_header # still in boundary, print line
print line
end
end
But in ruby, the idea of applying ranges on regular expression matches simplifies the syntax down to a bare minimum:
while line = STDIN.gets
if line =~ /^START$/ .. line =~ /^END$/
print line
end
end
This is one of the things that I have seen that's unlike any other language I've encountered before. Amazing and totally delightful!
Thursday, February 14, 2008

Non-Greedy Regular Expression Matching

This applies to Ruby, and many other languages too (eg. Perl), just that I keep forgetting it. In order to have non-greedy matching enabled, append the question mark after the quantifiers, ie.


* (0 or more) greedy matching
+ (1 or more) greedy matching
*? (0 or more) non-greedy matching
+? (1 or more) non-greedy matching


For vim, the syntax is slightly more convoluted, so it's important to put a note here for my own reminder:


* (0 or more) greedy matching
\+ (1 or more) greedy matching
\{-} (0 or more) non-greedy matching
\{-n,} (at least n) non-greedy matching


There's no direct '(1 or more) non-greedy matching' in vim, but the 'at least n' operation should be the equivalent. For vim, these should normally be default and independent of whether if the 'very magic' or 'very nomagic' mode is set. See help in pattern.txt, for more pattern matching details.
Friday, February 08, 2008

Setting up Sequel for Postgresql

For those people who are using postgresql with sequel, just in case if you are having an error message like the one below:
Sequel::Error::AdapterNotFound: Could not load postgres adapter:
no such file to load -- postgres
from /usr/local/lib/ruby/gems/1.8/gems/sequel_core-1.0.5/lib/sequel_core/database.rb:383:in `adapter_class'
from /usr/local/lib/ruby/gems/1.8/gems/sequel_core-1.0.5/lib/sequel_core.rb:36:in `method_missing'
This probably means that you don't have the postgres adapter installed. One quick way to fix problem is to install the postgres gem via rubygems:
% rubygems install -r postgres
That should solve the dependency requirement problem.
Monday, February 04, 2008

Understanding Rubygem's Load Errors

While rubygems is a great way of installing your packages without having yourself to dirty your hands, but if you installed your gems this way, it however does not mean that loading those newly installed gems is automatically.

It took me a while before I understood why my newly installed gems cannot be loaded through the 'require' statement, and giving me irksome messages like the 'no such file to load' error:
LoadError: no such file to load -- sequel
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require'
from /usr/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:27:in `require'
from (irb):1
That unhelpful message actually implies that you're missing rubygems as a requirement. So make sure you load rubygems via 'require' before you load any other gems installed by it in your source file:
require 'rubygems'
# put all other requirements after this
The other way of permanently including rubygems is to export the -rubygems flag into your RUBYOPT environment variable. Different shells may vary, but here's how you'll do it in bash:
% export RUBYOPT=-rubygems
Do make sure you check if there are any existing flags in RUBYOPT first before overwriting it though!
Thursday, December 06, 2007

What is a Ruby 'symbol'?

A symbol is something that looks like ':symbol' in ruby code, where it is like a variable name but preceded by a colon character. It is used extensively in Rails, which had been confusing me in the past, and it still does, given that I have not grasped full clarity of its significance yet.

The explanation given to me was that the definition of a symbol is 'like a string you never intend to show to the outside world'. The example told to me as an illustration was primarily utilized as hash keys, which I am told that it is cheaper than using strings (probably because it's immutability, which I suspect it's acting like a singleton object too). The closest example that I keep associating to, is the C preprocessor usage of '#define'.

Other than its extensive usage in Rails, I'm don't see how much it will be of any average coding use yet, unfortunately. There's still some way to go in the path of Ruby enlightenment for me.
Wednesday, November 21, 2007

Random Ruby Notes

I have been using Ruby much more than Perl these days to do all my dirty work in scripting most text handling tasks, which I find it is much better at doing these days. My only problem is mainly just the learning curve, which is typical of learning any software language, irregardless of how much conceptual and ideological similarities both languages may share.

Each language comes with it's own 'best practices', little idiosyncrasies and conventions that are unique, and so I'll try to present the following points that I've picked up for Ruby. Pardon me when I litter my subject headings with the 'right way' of doing things, it just means it's the conventional practice usually adopted by Ruby programmers.

The '?' or '!' behind the names of methods

They are both just a language convention. For the question mark, it is normally only for calls that return 'true' or 'false'. For the exclamation mark, it is used to mark that the method modifies 'self', rather modifying a copy while leaving the original unchanged.

It's helpful to note that having the punctuations behind the method names has no other significance besides that, something which is helpful to starters, especially if one is actually looking for an operational difference where there is none.

How do I know what class an object belongs to?

Either by:
object.class == Class

Or:
object.kind_of? Class

This applies only to Ruby being a full object oriented language. Perl does have OOP glued onto it, but seems quite ill-conceived that I hardly use it compared to the usual quick and dirty un-OOP that I'm used to.

The difference between the '==' operator and 'kind_of?' is that the former only matches the exact class, where kind_of? (probably) matches ancestor and descendant classes. I guess that's similar to the 'instanceof' keyword that I'm rather familiar in Java.

The right way for checking if a variable is defined
if defined? variable
puts "right way of checking variable is defined"
end

Where I've originally have been checking for 'defined-ness' by comparing to nil:
if variable == nil
puts "wrong way of checking variable is defined"
end

The right way for checking for array emptiness or non-emptyness

Rather than using arr.size == 0 or arr.size != 0, the two methods in ruby is arr.empty? or arr.any?. A comparison that checks the presence of an array is not a valid comparison for emptiness, i.e:
if [] then
puts "not the right way to check emptiness"
end

The above code is incorrect, because it will always return true as it checks for an array being defined, which is always true (for an empty array), rather than checking for the length of the array being zero.

Class loading mechanism in Ruby

If you needed to load a class definition dynamically, usually by passing the string of the class at Runtime, in Java the facility is:
Class c = System.getSystemClassLoader().loadClass("String");

The equivalent in doing this for Ruby:
s = Object.const_get("String");
Thursday, August 16, 2007

Some Gripes About Rails

I'm not a web-application developer, so writing Ruby on Rails code is basically just a past-time. In as much as I like Ruby, being a very elegant and expressive language to code in, I can't exactly say the same for Rails (at least not yet).

'Convention over Configuration' is a good idea, but problem is, sometimes you've got to know what conventions you to be looking out for to do something, and not knowing it can make it a rather frustrating experience, especially when you are starting out.

In order to map out all facets of an application access patterns into conventions, it is also inevitable that there will be much to read and make sense of. Probably something to take note of, and not to mistake that Rails will automatically translate to easy!

Catching all non-matching URLs on Rails

One of the early things that I needed to for a web application, was to try to map all unhandled or malformed URLs to be sent to Rails. It's important to do that especially when it's too easy to make a mistake typing on a URL, also because that instead of the typical 404 message people normally see, Rails gives you an unsightly routing error, with a "no route to match" message:


In order to change that and assign a controller to any unhandled URLs, append the following line as the last statement of your config/routes.rb:
map.connect '*anything', :controller => 'controller', :action => 'action'
Replace controller and action with the desired controller and action respectively. This will allow all unhandled URLs to be managed by the controller of your choosing.