articles tagged with ruby

RVM, REE and Postgres on OSX Snow Leopard

2 comments

I have jumped on board the RVM bandwagon for managing my development environments. I recently sold my Mac Pro on eBay and have a fresh new 27" iMac on the way. So I thought I’d document this part of the install process and a couple of gotcha’s.

First, grab the Postgres one-click installer and run it. Or you can build & compile it from source. Then for RVM and the latest REE follow these instructions;

# install readline for OSX if needed - check if it already exists in /usr/local/lib
wget ftp://ftp.cwru.edu/pub/bash/readline-6.1.tar.gz
tar -xvzf readline-6.1.tar.gz
cd readline-6.1
./configure && make && sudo make install

# install RVM from github
bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )
 
# edit your .bash_login (or profile) and add this at the bottom
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"

# check RVM has installed OK, look for 'is a function'
. ~/.bash_login
type rvm | head -n1
rvm notes

# install REE, or whatever Ruby you'd like
rvm install ree -C --enable-shared,--with-readline-dir=/usr/local

# show what rubies are installed
rvm list

# set REE as the default and current ruby
rvm --default ree

# check your working directories
which ruby && which gem

# In general I use Bundler for apps, but for .irbrc and some scripts I need these too
gem install wirble awesome_print hirb bundler mysql heroku

# and finally for the postgres (pg) gem
sudo env ARCHFLAGS='-arch i386' gem install pg

I’m surprised by how few steps it takes these days (to get Ruby & Rails up and running with a database), four years ago this was a different story altogether. With tools like RVM and Bundler, it couldn’t be simpler.

July 02, 2010 13:13 by

Rails 3 preparation

no comments yet, post one now

Here’s a few links on Rails 3 I’ve collected in preparation for its release. I haven’t read these all through yet, or started using Rails 3 in any way, but I have a couple of production apps primed and waiting to be upgraded as soon as it launches.

Start with this one from RubyInside, 36 links to get you going

And finally some official release notes;

April 15, 2010 14:27 by

Fake it till you make it!

2 comments

I’d like to share another handy little rake task that helps you fill up your Rails application with realistic ‘fake’ data. Here it is

Using the very excellent Faker gem by Benjamin Curtis this task can be configured to populate your models with random amounts of fake information. This can a be a real time-saver for load testing, preparing demos/screencasts, or just filling up your pages with realistic data so you can get to work on your views.

The classic 'comb-over', a traditional fake.

The classic 'comb-over', a traditional fake.

The task includes the following features;

  • Assign relationships between models with a random object picker
  • A random tag picker, for populating tag lists
  • Fake out your app at different different sizes; tiny, small, medium and large
  • Clean task, to clear stuff out before you start your faking
  • Disables mail sending before faking out, since before/after and other code hooks in your app might trigger sending mails
  • Helper to fake out a randomly picked time object within the last year
  • Prompts to ask before deleting any data on cleaning task.
  • Summary report after faking out, explaining exactly how many objects were created

Simply configure it (see code comments for help on this), drop it into your Rails lib/tasks folder and run like so;

sudo gem install faker # if you haven't got the gem already OR 
sudo gem install ffaker # use the faster faker gem from Emmanuel Oga 
rake fakeout:small # or tiny / medium / large

Cleaning all ...
Faking it ... (small)
  * Users: 53
  * Questions: 53
  * Answers: 38
  * Tags: 38
  * Taggings: 160
Done, I Faked it!

Along with this subdomain script from last month, I have pushed this code to github as a gist, so you can track it and grab updates to it whenever. The example there shows the task configured for a small Question & Answer app I’ve been working on.

And yes, I have started drawing a bit again, maybe it’ll make these posts more interesting to look at until I properly build this blog out.

Update – I have amended the task definitions to take a single argument; no_prompt. This turns off the confirm prompt and is useful for non-interactive running, e.g. with heroku rake commands for instance.

Update – This rake task is also fully compatible with the faster ffaker gem by Emmanuel Oga

February 07, 2010 15:31 by

A timesaving subdomain rake task

1 comment

A time saving rake task for adding or updating your local /etc/hosts file. I created this for Bugle, allowing me to quickly configure my development machine hosts file with subdomains used in the app. See the inline comments for an explanation.

Has the added feature of an array of default hosts to always add when you run it. Work is done on a tmp file then, then sudo copied on top of /etc/hosts. It exists as a gist on github so i’ll be sure to post any updates to it there.

# subdomains.rake (in /lib/tasks)
namespace :subdomains do

  desc "adds the necessary hosts to your /etc/hosts file from current subdomains in your application"
  task :setup => :environment do
    # NOTE: default_hosts is used as a locator for the line to update in /etc/hosts
    tmp_file, changed = '/tmp/etc_hosts_copy', false
    default_hosts, hosts    = %w(blog.local emptyblog.blog.local), []

    # find all the subdomains used in your app (push to hosts array) - modify this to suit your app
    Blog.find(:all).each { |blog| hosts << "#{blog.subdomain}.blog.local" unless blog.subdomain.blank? }
    
    # build hosts line to add/edit
    host_line = "127.0.0.1 " + hosts.sort.unshift(default_hosts).join(' ')

    # work with a copied hosts file in tmp
    %x[cp /etc/hosts #{tmp_file}]

    file = File.new(tmp_file)
    lines = file.readlines
    lines.each do |line|
      changed = true if line.gsub!(/^127.0.0.1 #{Regexp.escape(default_hosts.join(' '))}.+$/, host_line)
    end

    # add line, if no line found for update
    lines += ["\n", host_line, "\n"] unless changed
    file = File.new(tmp_file,'w')
    lines.each { |line| file.write(line) }
    file.close

    # copy hosts file from tmp - may ask for sudo password
    %x[sudo -p "Password:" cp #{tmp_file} /etc/hosts]
    
    # explain what happened
    puts "\nAdded the following domains:"
    hosts.each { |host| puts "* http://#{host}" }
    puts "\nAlso added defaults:"
    default_hosts.each { |default| puts "* http://#{default}" }
    puts "\n"
  end
end

To run simply type

rake subdomains:setup
January 14, 2010 16:53 by

Handy Aliases

4 comments

Working on the rails day in and out now, I’ve found the following aliases to come in handy;

# General Commands
alias ls='ls -al'

# TextMate, mate all of current dir and crucial rails folders only
alias et='mate . &'
alias ett='mate app config lib db public test vendor/plugins &'

# RAILS,  (run these from your rails folder)

# rails scripts
alias ss='./script/server'
alias sc='./script/console'
alias sg='./script/generate'
alias sp='./script/plugin'
alias mr='mongrel_rails start'

# rails testing 
alias att='autotest'
alias tu='rake test:units'
alias tf='rake test:functionals'    

# tail logs
alias tl='tail -f ./log/development.log'
alias tt='tail -f ./log/test.log'      

# clean the logs
alias ctl='cp /dev/null ./log/test.log'
alias cdl='cp /dev/null ./log/development.log'

I should credit Peep Code for the idea. To use, (e.g. in OSX) place the above in a ~/.bash_aliases file and in ~/.bash_profile, load it in with this command;

if [ -f ~/.bash_aliases ]; then . ~/.bash_aliases ; fi

Also, (and before I forget it myself) – here’s a quick session cleaner command to put in your cron, (for day old, mysql session clearage action); rather than build a rake task, or extra controller to clean them out.

#!/bin/bash

cd /u/apps/matthewhutchinson.net/current
echo "<== CRON TASK ==> clear day old sessions data on matthewhutchinson.net"
ruby script/runner -e production "ActiveRecord::Base.connection.delete(\"DELETE FROM sessions WHERE updated_at < NOW() - INTERVAL 1 DAY\")"

A Lesson In Computational Complexity

1 comment

What is ‘Computational Complexity’ ?

Basically a theory describing the scalability of algorithms. “As the size of the input to an algorithm increases, how do the running time and memory requirements of the algorithm change?” Wikipedia has a more complete description. Complexity can be considered in terms of;

  • Time Complexity – the number of steps that it takes to solve an instance of the problem as a function of the size of the input, using the most efficient algorithm.
  • Space Complexity – the amount of space, or memory required by the algorithm.

If you consider an array with n elements, and in solving a problem on this array, it takes n times n (or n2) steps. You could say the algorithm used had a complexity of n2. Now with different programming languages there may be additional steps in the algorithm necessary to solve the problem. To describe a general level of complexity across any language, the Big Oh Notation is used. So the time-complexity for this algorithm would be ?(n2)

‘?’ basically indicates that we are ignoring any language dependent factors, allowing complexity to be expressed purely in terms of the size of the input.

An Example

if you take a simple problem like, finding the ‘mode’ average on an array. I.e. the most frequently occurring element in a sequence (lets say of numbers) – You could do this an number of ways. Here is a brute force attempt (in Ruby).

def calculate_mode(nums)
  hi_count = 0
  mode = nums[0]
  nums.each do | search_for |
    count = 0
    nums.each do |num|
      if search_for == num
        count += 1
      end
    end
    if count > hi_count
      hi_count = count
      mode = search_for
    end
  end
end

It should be obvious that this algorithm has a complexity of ?(n2) – since every element of the array must be searched by each element to find the highest count value (and hence the mode).

Could it be done any faster? If the array of elements was sorted (ordered numerically) – the mode could be found by finding the longest continuing sequence in the array, that should only take n iterations. Employing a quick sort algorithm first; which can sort (on average) with ?(n log n)

def quicksort(a)
  return a if a.size <= 1
  pivot = a[0]
  quicksort(a.select {|i| i < pivot }) +
      a.select {|i| i == pivot } + 
      quicksort(a.select {|i| i > pivot })  
end

def calculate_mode_fast(nums, time_start)
  # sort array first
  sorted_nums = quicksort(nums)

  hi_count = 0
  mode = nums[0]  
  count = 1
  idx = 1

  sorted_nums.each do | search_for |
   if search_for == sorted_nums[idx]
     count += 1
     if count > hi_count
       hi_count = count
       mode = search_for
     end
   else
     count = 1
   end
   idx += 1 if idx < sorted_nums.length
  end
end

So we could say that this approach has (on average) a complexity of ?(n+(n log n)) which is significantly less that ?(n2)

I’ve posted this code listing which implements both algorithms running to compute the modal average on identical arrays of random integers. You can vary n (the number of elements) to see how each method performs. From the results (below) its clear that the 2nd algorithm is more time-efficient in this case.

calculate_mode
====================
mode => 3 (it occurs 44 times)
array length was 1000
num loops was 1000000
completed in 0.71737

calculate_mode_fast
=========================
mode => 3 (it occurs 44 times)
array length was 1000
num loops was 1040
completed in 0.011247

REST and Rails

1 comment

Here are some links that may be of use to anyone getting started with REST Resources in Rails.

January 26, 2007 11:59 by

Basecamp > ActiveCollab Importer

no comments yet, post one now

For some time now I have been trying out ActiveCollab, a free project management tool, to see if it could be a decent competitor to Basecamp

As far as I know, ActiveCollab started out as a free alternative to (and almost straight copy of) Basecamp – It is open source, written in PHP, and version 0.7 was released just a few weeks ago. After installing and setting up an example project I really needed to see how the thing would run with some real data, y’know some real life stuff.

After playing around with the (very useful) Basecamp API I had created a little Ruby class that allowed me to import projects, users, messages, comments and categories into ActiveCollab from Basecamp.

Run from the command line, the class outputs SQL (to the screen or a file) – which you can run against your ActiveCollab database after a default install. Read on if you’re interested in how it works.

First, some information about the class;

  • Start by installing a fresh copy of ActiveCollab 0.7, run through the installer, but don’t create any projects just yet
  • View/Download my Ruby class from here (usage instructions described at the bottom)
  • The script only generates SQL for importing Projects, Users, Messages, Comments and Categories (milestones, tasks etc. arent included)
  • Since Categories don’t exist in ActiveCollab, Messages are organised by category using single Tags
  • The user specified in the connection to the Basecamp domain is automatically assigned as an ‘administrator’ in ActiveCollab
  • ALL USERS imported are automatically given the same password ‘123’ – since the Basecamp API does not expose raw user passwords for use
  • To run, you’ll need Ruby installed, with the MySQL and RedCloth gems – and the basecamp.rb wrapper should be sitting along-side this class.

Second, some assumptions and configuration;

  • No dates are extracted for messages/comments (to just fill the database with info, I didn’t bother looking at :posted-on)
  • By default the prefix ‘ac_’ is assumed for all existing ActiveCollab tables (this can be changed on the class constant CollabTablePrefix)
  • By default, the script assumes all imported data will be assigned to the default ‘Company’ that is created after installing ActiveCollab
  • By default ‘TRUNCATE’ statements are generated for all affected tables, (clearing the before INSERTS) this can be switched off
  • By default the class is configured to export all it can (in the generate_sql function) – however this can be tailored to generate SQL for different ActiveCollab tables in isolation.

Much more could be done with this, but it was enough for my evaluation purposes. There has been some talk (for some time) in the ActiveCollab camp for something like this script to be built-in to their next release.

After all this, I have to say I’m sticking with Basecamp, it just feels better – better UI, somehow more responsive, faster and it continues to make project management, more well, manageable. From what I can see, ActiveCollab is still in its infancy and things like their database structure and code base change frequently – so this class may not be of much use in the future.

Rails Conf Europe - Day 2

no comments yet, post one now

So its all over, if I learnt one thing from this conference, its how popular Rails is. Its has been spreading like wildfire for a while now and is not letting up. At least 3 other Rails/Ruby conferences in Europe were confirmed for next year, with rumours of many more events this side of the pond.

The official conference site promises to post video’s of the main presentations and a podcast featuring most of the other talks.

All this talking about Rails/Ruby at the conference, on blogs, irc and forums has lead me to realise i’m not proportionally spending enough time doing Rails compared to hearing about it. So less talk more action from now on – Anyway, to go against just that, I’ll sum up some notes I made from day 2;

Jim Weirich – Playing it safe with Ruby

Jim started off showing this excellent video from World of Warcraft, and proved that even if one person doesn’t ‘work well in a team’ then the whole thing can fall apart. Much like developers working on Ruby and extending existing Classes and Methods in their plugins or applications. A lot of tips on how to code defensively when using the power behind Ruby;

  • if modifying existsing classes, if possible choose to ‘add behaviour’ – not take away or modify
  • avoid top level constants and functions
  • use namespaces – (hoping selector namespaces (with priority) come out soon in Ruby)
  • overwrite const_missing to catch deprecated methods, but remember to hook
  • take care to keep the hook chain in overwritten methods (grab aliases at the start)
  • make use of method contracts, overwritten pre-conditions should be less forceful, and post-conditions more forceful

Why the lucky stiff

This talk was the best of the day and fetaured comedy, cartoons and a guy who hints at having a bit of a passion for Ruby. There’s no way I can sum this up so you’ll have to wait for the video, I do vaugely remember him talking about sandboxing Rails – and his love for ‘the splat’.

Rany – Turning your enterprise job into a Rails playground

A great insight into how a developer (Rany) working for a large German bank, managed to sneak Rails development in the door, impressing his boss and getting the application deployed past the uber Swedish Architect and DB Admin. Techniques involved;

  • Lull management into a false sense of security
  • Steal (or convince some developers to join you)
  • Cheat (avoid some problems by not tackling them at all)

And since he is no longer at the Bank, he’s hiring Rails folk for his new startup company.

Jan Kneschke – Optimizing MySQL for Rails

Jan couldn’t make, but the talk went ahead with someone else from the MySQL team presenting. Confessing he didn’t know much about Rails or Ruby, he laid down some basic points for performance boosting in MySQL;

  • avoid queries if possible (caching, coding around them)
  • instead of Rails generated joins, code th MySQL for the joins manually
  • always only select back the coloumns you want from a query (no select star)
  • use smaller more selective indexes (e..g. index index_name (long_text_field(12))
  • for max. performance, optimise for only one type of database (e.g. MySQL)
  • myISAM preferred for Rails Session storage using ActiveRecord, use InnoDb for transaction based storage (useful in tests)
  • make use of the MySQL slow query log

Dominic Mitchell – Unicode for Rails

What you can do to ‘improve’ Unicode support in your Rails app. Its still not 100% there yet, but there are some steps you can take with plugins. Proves effective enough for English and most European langauges.

  • DB should be all in UTF-8 – just easier
  • in database.yml just use encoding: UTF8
  • serve HTTP with correct UTF8 header
  • form should use correct encoding
  • use Unicode wrapper methods from plugins around all string manipulation in code
  • test using Rails, throw in strange chars and see what comes out

(the remaining talks of the day I didnt bother with notes, not that they were’nt deserved – they’ll be better covered in the vidcasts anyway)

Rails Conf Europe - Day 1

no comments yet, post one now

With the first day of RailsConf Europe over, I have to say I was very impressed. The line-up was great, plenty of quality talks to choose from, and even a good wifi connection. I made some notes from each of the talks I attended (see full post below) – and I’ve also started a flickr group for the event and posted some pictures (with descriptions) myself.

David’s Keynote Address

DHH set the ball rolling from the start describing what we can expect to see from simply RESTful and ActiveResource in Rails 1.2 – using the convention of file extensions to offer a RESTful API. He also demonstrated simply Helpful, a new approach to convention over configuration in the view. Running out of time, he stopped short and promised to finish off the presentation at the end of the day.

Kathy Sierra – Creating Passionate Users

This was one of the best talks of the day (I thought) All about getting users into the ‘Flow’ – cutting out distractions and helping them feel always one ‘compile’ away from achieving their goals. Users need something to strive for, and motivation (shown through steps, or what others have done) to get there. Don’t spend time explaining only how the tools work, spend time demonstrating what the user can do with the tools. (recommended reading)

Dan Webb, Unobtrusive Ajax with Rails

A run through demonstration of using the UJS plugin for Rails, which (among other things) extracts all your AJAX/javascript out to a single file and decouples extra calls to similiar AJAX actions (e.g. on a products page listing) – A strong emphasis was mentioned on getting the application working first with semantic HTML (non-javascript) – then ‘hi-jacking’ the page with UJS behaviors. All very good stuff indeed

Jamis Buck, Capistrano

Introduced Capistrano 1.2 – including the new capistrano shell, a stateless ssh prompt that allows you to interact with all of your servers in the cluster. He warned that this could be dangerous in the wrong hands. The cap shell makes use of environment variables you can set to apply capistrano commands to just a select few servers (or all). A couple of extensions were also shown, namely ‘uptime’ and ‘watch_load’ – both very useful.

Alex Payne, Securing Rails: A Whole-Stack Approach

This guy knows his stuff, Alex Payne has been competing at DefCon and currently works as a security consultant to some ‘firms’ in Washington DC. He’s also a web developer so he concentrated on the Rails part of the full stack, explaining that there really is no silver bullet here, and that SQL injection, cross-site scripting, cross-site request forgery and web service API’s all need to be secured. He recommended using Mongrel (since it has a ‘fuzzer’, rfuzz) and suggested writing attack scripts in your Rails functional tests.

Gavin Bell, Everything is interconnected

An overview on the powerful nature of a tagging community – the example being the Boston Science community site. Using Rails and acts_as_taggable, most of the site navigation is presented to the user as tag’d links. One thing they didn’t mention was GeoTagging – giving things a ‘physical place’ as it were – using a pin on Google Maps for example. The site is still in development and is due to get busier later this year.

Thomas Fuchs, Adventures in JavaScript Testing

Not much to say on this one, was a tough topic to cover and it was by no means an ‘adventure’ – but Thomas did a good job covering the bases. He mentioned that there is still no integration for auto-testing RJS generated Javascript.

Rails Core Team, Panel Discussion

Half of the full Rails Core team sat down to take questions gathered throughout the day, and a number from the floor. A couple of stickler’s were defended – including ‘when should I not use Rails?’ and ’couldn’t this/that be in the core?’ — DHH was also faced with the ’isn’t ruby/rails too slow?’ – which was (and has been) easily defended.

DHH, ‘we don’t owe you shit’ finale

Finally David rounded off the day with the most entertaining talk. His own personal suggestions and opinions (which many shared) with the Rails community including the reaction to the most recent security issue (resolved in 1.1.6) Using slide with comedy pseudo Ruby code (he forgot to bring Keynote with him on the plane over) – David’s main point was don’t expect anything from the Rails community by just downloading the framework. Summarizing, you start with zero credits here, and earn them from the community by contributing to it, getting involved, writing patches, tutorials, plugins, applications, documentation etc. Constructive criticism from non-contributing members in the community is very welcome (and necessary) – but ‘be nice’ – put together an argument, complaint, suggestion in a constructive manner and them expect a response, everything else will get a ‘f**k you!’ — a more detailed summary at the Copenhagen Ruby Brigade

So with that fresh in our minds, heres looking forward to tomorrow.

← (k) prev | next (j) →