Articles with tag ‘ruby‘

 
 

Installing Ruby 1.8.7 on Mac OS X 10.5.3

Yah, this week is all about solving problems. I run into a lot of them, but it gives me something to blog about. But hey, if I can spend 20 minutes writing down a solution to a couple hour problem that I had, then I could save you a few hours too.

Problem

Trying to install Ruby 1.8.7 (or even 1.9) on my Leopard machine produces warning messages on “make” that look like this:

gcc -I. -I../../.ext/include/i686-darwin9.1.0 -I../.././include
-I../.././ext/readline -DRUBY_EXTCONF_H=\"extconf.h\"    -fno-common
-g -O2 -pipe -fno-common   -o readline.o -c readline.c
readline.c: In function 'filename_completion_proc_call':
readline.c:659: error: 'filename_completion_function' undeclared
(first use in this function)
readline.c:659: error: (Each undeclared identifier is reported only once
readline.c:659: error: for each function it appears in.)
readline.c:659: warning: assignment makes pointer from integer without a
cast
readline.c: In function 'username_completion_proc_call':
readline.c:684: error: 'username_completion_function' undeclared
(first use in this function)
readline.c:684: warning: assignment makes pointer from integer without a
cast
make[1]: *** [readline.o] Error 1
make: *** [all] Error 1

Solution

I originally came across this problem right around new years and eventually found a solution thanks to Han Kessels on the Ruby Forums. It involved the following steps:

  1. Download the newest version of readline (version 5.2 at the time of writing) at GNU.org. You may have to apply the following patch. Thanks to Michael Biven for showing a nice simple way to do this from the command line:
    $ curl -O ftp://ftp.gnu.org/gnu/readline/readline-5.2.tar.gz
    $ tar xzvf readline-5.2.tar.gz
    $ cd readline-5.2
    $ curl -O http://ftp.gnu.org/gnu/readline/readline-5.2-patches/readline52-012
    $ patch -p0 < readline52-012
    $ ./configure --prefix=/usr/local
    $ make
    $ sudo make install
    $ cd ..
  2. Now you can download the 1.8.7 version of ruby, and install it but you should point to the version of readline that you just installed (to /usr/local) like so:
    $ curl -O ftp://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.7.tar.gz
    $ tar xzvf ruby-1.8.7.tar.gz
    $ cd ruby-1.8.7
    $ ./configure --prefix=/usr/local/ruby1.8.7 --with-readline-dir=/usr/local
    $ make
    $ sudo make install
    $ cd /usr/local/ruby1.8.7/bin
    $ ./ruby -v
    ruby 1.8.7 (2008-05-31 patchlevel 0) [i686-darwin9.3.0]

The End Result

If you followed my terminal commands from above you should have a working Ruby 1.8.7 version installed in your “/usr/local/ruby1.8.7/bin”. If you wanted ruby in a different directory then change the “–prefix=/usr/local/ruby1.8.7″ option on ./configure to instead point to the directory you wanted it.

Why put it in its own directory at all? Well, I happen to have multiple version of ruby. By default I have 1.8.6, I have this version of 1.8.7, I even have a 1.9 version I installed a while ago. Its easy to remember where each is if the directory they reside in clearly states the name. This way I can test a script, maybe even run benchmarks, in each version of ruby. However, you might not want to take this extra measure.

Dot Files For Your Shell and Even Ruby

I have come across a number of programmers who don’t know what dotfiles are. Thats a shame. Every programmer should know common dotfiles and actively seek to add aliases, functions, and other tidbits to increase their productivity and make the shell more usable. I recently went on a binge and updated a few of my dotfiles. I’ll share some useful tricks that I found on not only my ~/.bashrc file but also ~/.irbrc for my ruby IRB prompt!

I won’t show off my entire ~/.bashrc file, only because it is rather long. I just want to get across some of the usefulness of such a file:

# -----------
#   General
# -----------
alias ..='cd ..'
alias ll='ls -lh'
alias la='ls -la'
alias ps='ps -ax'
alias du='du -hc'
alias cd..='cd ..'
alias more='less'
alias mkdir='mkdir -p'
alias today='date +"%A, %B %d, %Y"'
alias yest='date -v-1d +"%A %B %d, %Y"'
alias recent='ls -lAt | head'
alias ebashrc='mate ~/.bashrc'
alias mbashrc='mate ~/.bashrc'
alias sbashrc='source ~/.bashrc'
alias htdocs='cd /Applications/MAMP/htdocs/'
alias mampmysql='/Applications/MAMP/Library/bin/mysql -u XXXXX -p'
alias desktoptopia='open /Users/joe/Library/Application\ Support/Desktoptopia/.Backgrounds/'
alias ql='qlmanage -p "$@" >& /dev/null' # Quick Look alias

# -------------
#   Shortcuts
# -------------
alias c="clear"
alias m="mate"

# --------
#   SSHs
# --------
alias rit="ssh holly.cs.rit.edu -l XXXXX"
alias vega="ssh vega.it.rit.edu -l XXXXX"

# -------
#   Git
# -------
alias ga='git add'
alias gs='git status'
alias gd='git diff'
alias github="open \`git config -l | grep 'remote.origin.url' | sed -En 's/remote.origin.url=git(@|:\/\/)github.com(:|\/)(.+)\/(.+).git/https:\/\/github.com\/\3\/\4/p'\`"

# --------
#   Ruby
# --------
alias irb='irb -r irb/completion -rubygems'

# ---------------
#   Environment
# ---------------
export PATH="$PATH:/usr/local/bin:/usr/local/sbin:/usr/local/mysql/bin"
export PATH="$HOME/bin/:$PATH"
export HISTSIZE=10000
export HISTFILESIZE=10000
export PAGER=less
export CLICOLOR=1
export EDITOR="/usr/bin/mate -w"

Hopefully this wasn’t too overwhelming. But lets take a look at some of these. There are a bunch of aliases at the top which simply replace the older version? It just makes sense that when you do a ps you really want `ps -ax`. Likewise a few others there are printing disk usage with human readable output.

Nothing completely interesting however everything is extremely useful. I’m cutting my keystrokes in half and getting better output. I have a bunch of more exciting tricks in the rest of my ~/.bashrc. Its not just reserved for aliases and EXPORTS, take this function for example:

# cd directly to a dir and list contents
cdl() {
  if [ "$1" ]
  then builtin cd "$1" && ll
  else builtin cd && ll
  fi
}

Cd to a directory and list the directory. I even reference my ll alias up above to list long. You can take a peek at my entire .bashrc file on dotfiles.org. Lets move on to something you may not have known about. Let me walk you through parts of a nice ~/.irbrc file, which you might want for yourself:

# Load and Start Wirble, a gem to beautify irb
require 'wirble'
Wirble.init
Wirble.colorize

Probably one of the most popular inclusions in a .irbrc file. Wirble is a Ruby gem built for improving the irb interactive ruby console. That means you may also have to ‘require “rubygems”‘ in order for this to work. Take a look at the gem documentation for Wirble to find out more of its capabilities. But that also means you can include a number of other useful rubygems. For instance, what_methods, map_by_method, hpricot, yaml, the list goes on and on. Instead I’m going to point out some other neat additions you can add to your .irbrc!

# Awesome benchmarking function
# Source: http://ozmm.org/posts/time_in_irb.html
def time(times=1)
  require "benchmark"
  ret = nil
  Benchmark.bm { |x| x.report { times.times { ret = yield } } }
  ret
end
alias bench time

# A cool way to index in a hash
# h = { :alpha => 'bet', :beta => 'blocker' }
# h/:beta #=> 'blocker'
class Hash
  def /(key)
    self[key]
  end
end

# Simple regular expression helper
# show_regexp - stolen from the pickaxe
def show_regexp(a, re)
  if a =~ re
    "#{$`}<<#{$&}>>#{$'}"
  else
    "no match"
  end
end

# Convenience method on Regexp so you can do
# /an/.show_match("banana") # => "b<>ana"
class Regexp
  def show_match(a)
    show_regexp(a, self)
  end
end

There, now you’re building some really useful tricks! Check it out. Thanks to a few different sources for those code snippets I can easily benchmark any code run at any number of times. There is a neat way to pull an element from a hash, without having to put [brackets] around the key. Finally, a little helper for regular expressions which is useful every now and then.

But wait, there is more. This time a little more system specific:

# Textmate helper
# Source: http://dotfiles.org/~lattice/.irbrc
def mate *args
  flattened_args = args.map {|arg| "\"#{arg.to_s}\""}.join ' '
  `mate #{flattened_args}`
  nil
end

# Clear
def c
  system('clear')
end

You can now open up TextMate from within irb! I’ve also grown so used to using my ‘c’ alias to clear the terminal prompt that I added the same functionality to irb. Just make sure that you don’t name a variable c!

Now let me blow your mind:

# Why's aorta method to edit an object in YAML, awesome!
# Source: http://rubyforge.org/snippet/detail.php?type=snippet&id=22
require 'yaml'
def aorta( obj )
  tempfile = File.join('/tmp',"yobj_#{ Time.now.to_i }")
  File.open( tempfile, 'w' ) { |f| f << obj.to_yaml }
  system( "#{ ENV['EDITOR'] || 'vi' } #{ tempfile }" )
  return obj unless File.exists?( tempfile )
  content = YAML::load( File.open( tempfile ) )
  File.delete( tempfile )
  content
end

Why is a famous member of the Ruby community. This function here actually takes a Ruby object, exports it as YAML to a file, opens the File for editing, and once saved reloads the file from YAML. Essentially it allows you to edit the contents of an object in YAML. Absolutely amazing, let that stir in your mind for a minute!

Now, I have started building my own library of functions that I have deemed semi-useful but not worthy of turning into a gem. These functions include some simple String extensions like my TXT helpers. I include all these files in a directory and I auto-load them like so:

# Load all my non-test libraries in '~/.util/irb'
util_dir = File.expand_path('~') + '/.util/irb/*'
Dir[util_dir].each do |f|
  require f unless File.basename(f) =~ /\Atest/
end

Notice how I ignore any files starting with “test”. I have gotten into the habit of creating test files for my libraries and the naming convention I use is the exact same as the majority of Ruby developers, you just create a new file called “test_library.rb” to test “library.rb”. Simple yes, and helpful in this case where I want to avoid loading these test files. This means I have all my useful functions pre-loaded whenever I open the irb. I’d like to see what additional stuff you have!

Finally here are links directly to my .bashrc and .irbrc files. Enjoy, and please give me additions!

Ruby Can Help you TXT

I’ve never been a “Txter.” I’d much rather call my friends or have them call me. Its a pain to have to search for this small letters, push keys 1-4 times, search for shift, etc. Its a pain ever time I have to text. Hopefully this will be completely avoided as I consider replacing my iPod Touch with an iPhone this coming week after the WWDC Keynote. Either way I decided to employee Ruby to help me out.

It all started with a simple function to convert phone numbers with letters to their numbered equivalent. For instance converting “555-HELP” to “555-4375″ like so:

# Extend the String Class
class String

  # Converts a phone number with letters to numbers
  # Ex. AAA-FFFF => 222-3333
  def convert_to_phone_number
    letters = 'abcdefghijklmnopqrstuvwxyz'
    numbers = '22233344455566677778889999'
    self.downcase.tr(letters, numbers)
  end

end

puts "555-HELP".convert_to_phone_number # => 555-4357

I decided to take it a step further. Why don’t I have Ruby tell me what I should push to text a string? So with a few modifications, and some studying of my cellphone I came up with the following function, also extending the String class (not shown):


  # Converts the given string to the sequence of
  # numbers that you would need to push to create
  # that string. Shift = *, Space = #
  # Input: "Hello hi"
  # Output: "*44 33 555 555 666 # 44 444"
  def how_to_text
    letters    = 'abcdefghijklmnopqrstuvwxyz '
    numbers    = '22233344455566677778889999#'
    multiplier = '123123123123123123412312341'
    str = ''
    self.each_byte do |char|
      char = char.chr
      if char =~ /[A-Z]/
        str += '*'
        char.downcase!
      end
      str += if letters.include? char
        index = letters.index(char)
        numbers[index].chr * multiplier[index].chr.to_i
      else
        char
      end + " "
    end
    str.chop
  end

  # Converts the given numeric sequence back to
  # a text string.
  # Input: "*44 33 555 555 666 # 44 444"
  # Output: "Hello hi"
  def decode_text
    letters = 'abcdefghijklmnopqrstuvwxyz '
    numbers = '22233344455566677778889999#'
    str = ''
    self.split.each do |part|
      shift = part[0].eql?(?*) ? true : false
      part = part[1,part.length] if shift
      pos = numbers.index(part) + (part.length-1)
      str += if shift
        letters[pos].chr.upcase
      else
        letters[pos].chr
      end
    end
    str
  end

Texting is no longer a burden. I even have a decode function to convert back from the cryptic pattern to its original string. Right now the function is limited to typing lowercase letters, uppercase letters, and spaces. I might spend the time to abstract this even more so you can pass in your phone’s texting “model”, a String/Hash/Object providing such information, and it would use that to generate the keystrokes required to text. For now I’m pleased with what I have.

>> "until next time".how_to_text
# => "88 66 8 444 555 # 66 33 99 8 # 8 444 6 33"

I use tab-autocompletion in my IRB and I load this library from my ~/.irbrc, but if you are really interested you could alias how_to_text to how_to_txt to make it a little more fun. That makes it a little harder on tab-autocompletion though.

Feel free to download and improve it. I’ll keep it out of my GitHub for now and just store it in my free directory:
Download
Test Case

Building a Ruby Gem

With all of my recent interest in Ruby I have been overwhelmed by the number of really awesome rubygems. I have talked about some and I will talk about even more in the future but I felt it would be important to learn how to make my own ruby gem. After all, I’d been using GitHub to update a few people’s gems without really knowing the best way to go about such things. It took longer then I expected to find the right resources for what I wanted but I came across three good articles which pointed me in the right direction:

I’m going to write about what I feel you most likely want to know when creating your first Ruby Gem.

1File/Directory Structure

Gem File Structure
The most basic structure for a simple ruby gem would be like so:

+ gem_name/
   - History.txt
   - README.txt
   - Rakefile
   + bin/
      - gem_name
   + lib/
      - gem_name.rb
   + test/
      - test_gem_name.rb

This is pretty straightforward but let me explain a little. There is an outermost directory that holds everything. Source files go in lib/, executables go in bin/, and test files will go in test/.

The README.txt is essentially to providing the meta-data, installation instructions, and basic information that you would want to any person downloading your gem to read. History.txt is the common name for the Changelog.

2Utilities to Help You

Now don’t go making these directories by hand! As you probably expected there are a number of tools to get this job done for you. These tools are gems themselves and are therefore simple to install and start working with. The two that I would suggest looking at are Hoe and the slightly more advanced newgem which even uses Hoe.

Both tools come with command line utilities that automate building this directory structure. I’ll start with Hoe, which cleverly named their utility “sow”.

$ sow first_project
creating project first_project
... done, now go fix all occurrences of 'FIX'

  FirstProject/Rakefile:9:  # p.developer('FIX', 'FIX@example.com')
  FirstProject/README.txt:3:* FIX (url)
  FirstProject/README.txt:7:FIX (describe your package)
  FirstProject/README.txt:11:* FIX (list of features or problems)
  FirstProject/README.txt:15:  FIX (code sample of usage)
  FirstProject/README.txt:19:* FIX (list of requirements)
  FirstProject/README.txt:23:* FIX (sudo gem install, anything else)
  FirstProject/README.txt:29:Copyright (c) 2008 FIX

That was easy. It setup a structure exactly like the above but with an additional Manifest.txt file that lists all the files. Easy enough. Lets take a look at newgem:

$ newgem new_proj
      create
      create  config
      create  doc
      create  lib
      create  script
      create  tasks
      create  test
      create  tmp
      create  lib/new_proj
      create  History.txt
      create  License.txt
      create  Rakefile
      create  README.txt
      create  PostInstall.txt
      create  setup.rb
      create  lib/new_proj.rb
      create  lib/new_proj/version.rb
      create  config/hoe.rb
      create  config/requirements.rb
      create  tasks/deployment.rake
      create  tasks/environment.rake
      create  tasks/website.rake
      create  test/test_helper.rb
      create  test/test_new_proj.rb
  dependency  install_website
      create    website/javascripts
      create    website/stylesheets
      exists    script
      exists    tasks
      create    website/index.txt
      create    website/index.html
      create    script/txt2html
       force    tasks/website.rake
  dependency    plain_theme
      exists      website/javascripts
      exists      website/stylesheets
      create      website/template.html.erb
      create      website/stylesheets/screen.css
      create      website/javascripts/rounded_corners_lite.inc.js
  dependency  install_rubigen_scripts
      exists    script
      create    script/generate
      create    script/destroy
      create  script/console
      create  Manifest.txt
      readme  readme
Important
=========

* Open config/hoe.rb
* Update missing details (gem description, dependent gems, etc.)

Okay don’t get intimidated. There is a little more meat this time but I know you’re hungry. Now there is a License, some more automation with rake, configuration files for hoe, a directory for a website allowing you to describe your gem, and even some scripts to make working with your ruby gem a little easier. This seems like a great choice for real large scale gem requiring some major testing.

For the purpose of this blog post I’m going to stick to the basics. I’m not doing anything major here. I’ll stick to Hoe and begin reaping my newly sowed gem. The majority of this tutorial will still apply no matter which method you decide to choose.

3Pre-Development

A few quick items before you dive into development.

If you used Hoe and sow then you can start out by changing all the occurrences of “FIX”. Most are found in the README.txt file and one more in the Rakefile. Fill out these details as you think they should be filled out. Get these minor details out of the way before you start your work.

I would suggest setting up version control right now and making an initial checkin for your project. The choices here are huge but not necessarily critical for your project. I would suggest that you take a look at Git, Subversion, and Mercurial. I’ll be using git, and hosting my project on GitHub. Its all free, easy, and most of all fun! Tutorials for GitHub are available online, its the easiest version control system I have ever used!

Finally, since Hoe works so nicely with RubyForge you will want to setup an account and install the rubyforge gem. That takes only a few minutes. Setting up the RubyForge bundle is pretty straightforward:

# Install and Setup
$ sudo gem install rubyforge
$ rubyforge setup

# (optional) FYI the location of the edit file
$ mate ~/.rubyforge/user-config.yml

# Configure and List
$ rubyforge config
$ rubyforge login
$ rubyforge names

You should be all set to start development on your gem.

4Gem Basics

Now that you’re setup you can develop like normal. Put your Ruby Modules, Classes, etc. into the lib folder. One thing that you will notice that Hoe did for you is setup a Class with your gem name and it defined a single constant VERSION. This value is important when the time comes to release and later update your gem. Each section has a well defined meaning. Here is what Dr. Nic had to say:

VERSION = X.Y.Z
X = major release number (MAJOR) - not backwards compatible
Y = minor release number (MINOR) - backwards compatible, additional features
Z = patch/bug fix number (TINY) - small bug fixes

Try to keep your versioning conventions uniform with these values. Then when you want to update your gem all you would need to do would be update the VERSION, and follow through with a release.

Make use of rake to automize testing, doc creation and more. I am still just learning rake so I’ll leave most of the discussion of rake for another time. However you should be aware of the following to get a list of all the functions rake can perform:

$ rake -T

5Create the RubyForge Package

Because you’ve used Hoe all you need to do is have a RubyForge account, the rubyforge gem configured correctly, and your source files all ready to go. Create a new package on Ruby Forge, which you can do like so:

$ rubyforge create_package bogojoker regex_replace
$ rubyforge config
$ rubyforge names

You would replace bogojoker with your group/username and regex_replace with your package name (which will be your gem name). This is also possible to do from the RubyForge website GUI if you can’t get this working.

6Release (Deploy) the Gem

Once the package is created you can configure Hoe to publish right to Ruby forge by editing your Rakefile:

Hoe.new('regex_replace', Rr::VERSION) do |p|
  p.rubyforge_name = 'bogojoker'
  p.developer('Your Name', 'Your Email')
end

Again notice this time that ‘regex_replace’ would be the name of your package, Rr::VERSION would point to your VERSION constant auto-created when you created your directory with Hoe’s sow, and that your rubyforge_name would be your group/username for RubyForge and this case ‘regex_replace’ would be.

Uploading is now breeze, just do the following:

$ rake release VERSION=1.0.0

Where the version number is the same as the VERSION constant for your gem. Hoe will make use of rubyforge to package and upload directly to RubyForge with little to no problems. Follow this up with:

$ rake publish_docs

7Problems / Troubleshooting

Remember when I said “little to no problems?” Well, what if you have problems? I’ll cover a few issues I had:

Where is my RubyForge Project?

Once you make an account you actually have to request to create a project and that request will get approved later in the day. You can go through with everything and host the gem on your own gem server or at least make your .gem available using ‘$ rake package’ and taking the .gem inside the newly created pkg/ folder in your gem’s directory. But once your RubyForge project is accepted you can proceed to upload using ‘$ rake release …’.

no <group_id> configured for <bogojoker>

Make sure you create the package on RubyForge and make sure it goes through. Run the rubyforge create_package command, then config, and names to see if the new package was created. Try a more unique name if it appears not to work.

no <processor_id> configured for <Any>

In this case something went wrong with your rubyforge config. Its not known to me why this may have happened but a few others have had the same problem. The solution is easy, edit the “processor_ids: in your your ~/.rubyforge/auto-config.yml file to be the following:

processor_ids:
  IA64: 6000
  Any: 8000
  AMD-64: 1500
  PPC: 2000
  Sparc: 4000
  Other: 9999
  i386: 1000
  Alpha: 7000
  MIPS: 3000
  UltraSparc: 5000

Finally:

$ gem install regex_replace
Bulk updating Gem source index for: http://gems.rubyforge.org/
ERROR:  could not find regex_replace locally or in a repository

I thought I had it! Well, actually I did! It just took about 5 minutes for the my gem to be picked up and indexed. So just a few minutes later it was working! If you ever want to search the gem index you can use the following command:

$ gem search -r regex

*** REMOTE GEMS ***

Bulk updating Gem source index for: http://gems.rubyforge.org/
cnuregexp (1.0.0)
regex_replace (1.0.0)
regexbuilder (0.0.1, 0.0.0)
regexp-engine (0.9, 0.8)
RegexpBench (0.5.2, 0.5.1, 0.5.0)
TextualRegexp (1.8.6)

Where ‘-r’ stands for remote and ‘regex’ would be replaced with your search term.

8Conclusions

Rubygems are part of the reason for Ruby’s massive appeal. I can download and make use of incredible ruby libraries or programs with simple ‘gem install’ commands. Now that I’ve produced my own gem I have a greater appreciation for the developers that have made this so streamlined, efficient, and easy.

I think all Ruby Developers should take the time to produce a gem. Why?

  1. Release open source code and contribute to the Ruby community
  2. It will help you when you want to work on someone else’s code
  3. Facilitates a test-driven mindset with rake
  4. Work with the automatic documentation to improve the code you release
  5. Spur creativity. Some Ruby gems are just brilliant. I wanna see more.

I hope this helps you and encourages you to spend the time to publish some of your useful Ruby code so that others like my self can start using it.

I almost forgot, you can grab my gem, which installs the rr command in your bin by running the following:

$ sudo gem install regex_replace

$ rr
usage: rr [options] find replace [filenames]
       rr [options] s/find/replace/ [filenames]

Cheers.

HAML - TextMate Command

I have been enamored with Ruby lately and one of the gems that has been stuck in the back of my mind for a very long time was HAML. HAML is a really slick way to write some html code with Ruby hooks. If you’re a Ruby on Rails user you can convert all your .rhtml files into .haml files and really reduce the file’s contents to its pure essence. To see what I mean:

!!!
%html
  %head
    %title Simple Page
  %body
    #header
    #sidebar
      %ul.menu
    #content
      %h1 HAML is awesome
      %p
        It even performs Ruby!
        = 50 * 10
    #footer
      %span{:style=>'text-align: center'} Joseph Pecoraro

Produces this super clean HTML:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
  <head>
    <title>Simple Page</title>
  </head>
  <body>
    <div id='header'>
    </div>
    <div id='sidebar'>
      <ul class='menu'>
      </ul>
    </div>
    <div id='content'>
      <h1>HAML is awesome</h1>
      <p>
        It even performs Ruby!
        500
      </p>
    </div>
    <div id='footer'>
      <span style='text-align: center'>Joseph Pecoraro