Friday, July 10, 2009

Getting ruby, rubygems, rake, mysql, imagemagick, rmagick, aspell, raspell with fink

This is really just for me to remember this. If at some point someone else benefits from this, even better.


  1. Download and Install fink

  2. Edit /sw/etc/apt/sources.list and add the following:

    deb http://fink.sodan.ecc.u-tokyo.ac.jp/apt/10.5 unstable main crypto
    deb http://sage.ucsc.edu/fink_intel_10.5_only stable main crypto
    deb http://sage.ucsc.edu/fink_intel_10.5_only unstable main crypto


  3. Install ruby:

    sudo apt-get install ruby
    sudo apt-get install ruby18-dev
    sudo apt-get install ruby18-shlibs


  4. Install rubygems:

    sudo apt-get install rubygems-rb18


  5. Update rubygems:

    sudo gem update --system
    sudo gem install rubygems-update # this is to get passed v 1.1.1
    sudo update_rubygems



  6. Install rake

    sudo gem install rake



  7. Then install mysql:

    sudo apt-get install mysql
    sudo apt-get install mysql-client
    sudo apt-get install mysql15-dev
    sudo gem install mysql

  8. If you want to use a custom my.cnf, plunk it in /etc

  9. Then install imagemagick and rmagick (this one can be a pain)

    sudo apt-get install imagemagick10-dev imagemaigck10-shlibs
    sudo apt-get install freetype freetype-shlibs ghostscript ghostscript-fonts \
    gv libpng-shlibs libjpeg libjpeg-bin libjpeg-shlibs lcms lcms-bin lcms-shlibs \
    libtiff libtiff-bin libtiff-shlibs
    sudo gem install rmagick -v 2.9.2


  10. Install aspell:

    sudo apt-get install aspell
    sudo apt-get install aspell-en
    sudo apt-get install apsell-dev
    sudo gem install raspell



  11. Install other gems:

    sudo gem install hoe -v 2.0.0
    sudo gem install nokogiri
    sudo gem install rake-compiler
    sudo gem install taka
    sudo gem install johnson -v 1.1.0 # 1.1.1 wouldn't install

Monday, March 16, 2009

Introducing cached_attribute - cached values across object instances

We've been memoizing attributes manually for a long time, and since we're still on Rails 2.1, we haven't been able to use the nifty new features for memoization. I liked the way Rails 2.2 did it, though, and revisited it when we were investigating some perf issues on the site.

Memoization is cool and all, but it didn't buy us anything when we had multiple instances of the same object on the same page, so that's where cached_attribute comes in. Cached_attribute is a plugin that stashes the result of an expensive calculation into a cache, indexed by the object's id. That way, multiple object instances will share the same cached value for the same attribute (on the same object).

The readme has more information and an example, or you could just check out the code:

ruby script/plugin install git://github.com/avvo/cached_attribute.git


And as usual, the project is available on github.

Thursday, March 12, 2009

Multiple delivery method support for ActionMailer

For our test servers (and in development), I wanted to be able to create an action that would display all the emails sent by that mongrel. When using the :test delivery method, sent emails are readily available in ActionMailer::Base.deliveries. However, for our test server I wanted ActionMailer to send the email with smtp in addition to keeping them around in memory.

So here's the resulting plugin:

http://github.com/bvandenbos/actionmailer_multiple_delivery_methods/tree/master


ruby script/plugin install git@github.com:bvandenbos/actionmailer_multiple_delivery_methods.git


Then in your development.rb (or environment.rb, or wherever) you can do this:


config.action_mailer.delivery_method = [:test, :smtp]


I've tried it with Rails 2.1.0. No guarantees with any other version, or even 2.1.0 for that matter ;)

Tuesday, January 13, 2009

Twitterss - RSS to Twitter script that can handle multiple accounts

I know there are a bunch of RSS to Twitter scripts out there in a variety of languages. There's even twitterfeed which manages all your feeds for you (which is a pretty cool service). But, I couldn't find one that did all of the following:

  1. Took updates as frequently as I wanted

  2. Could handle multiple RSS feeds to multiple Twitter accounts (ie: could be configured)

  3. Didn't require handing out my Twitter password (not that this is always a bad thing)

  4. Didn't have a bunch of dependencies (activerecord, mysqlite, etc...)

  5. Preferably written in ruby


So, I hacked twitterss together.

Twitterss is just a script that takes a YAML configuration file as a paramter which is meant to be used as a cron job:
  $ twitterss twitterss.yml


twitterss.yml might look something like this:

legalnews:
rss: http://www.avvo.com/news.rss
login: avvolegalnews
password: secret

cnn_money_top_stories:
rss: http://rss.cnn.com/rss/money_topstories.rss
login: money_news
password: secret
max: 5

cnn_money_markets:
rss: http://rss.cnn.com/rss/money_markets.rss
login: money_news
password: secret
max: 3

This config would make twitterss pull items from the CNN Money Top Stories and the CNN Money Markets feeds and push them the the money_news Twitter account. It would also pull from the Avvo Legal News feed and push to avvolegalnews.

Example result:



To make sure it doesn't post the same link twice, it keeps a list of each link it posts for each config entry in a local file (<USER_HOME>/.twitterss_history).

Thursday, November 20, 2008

Method of the Day: index_by

Just stumbled on to this one. I can't tell you how many times I've wanted this functionality.

You have an array, but you want a hash keyed by an attribute of the items in the array. Typically, you'd do something like this:

users_by_name = {}
users.each { |u| users_by_name[u.name] = u }

Which is of course silliness now that we know about index_by.

users_by_name = users.index_by(&:name)

Slick.

Thursday, November 6, 2008

Pushing to multiple user accounts on GitHub

Here at Avvo, we've started to use GitHub for publishing some of our internal libraries that might be useful to the programming community. Although we have a company account, it's nice to have a personal account, too. Unfortunately, github doesn't allow multiple accounts to share the same SSH key. This makes sense, because all communication with github works using the same ssh user account. From my perspective, it can get kind of annoying.

The key to being able to check code into multiple github accounts is setting up multiple ssh keys and using ssh aliases to use the correct key for the correct repo. First, I created a company-specific key:
justin-mac:~ jweiss$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/jweiss/.ssh/id_rsa): /Users/jweiss/.ssh/id_rsa.avvo
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

Then I set up an SSH alias in ~/.ssh/config:
host github-avvo
HostName github.com
User git
IdentityFile ~/.ssh/id_rsa.avvo

Next, I copied the id_rsa.avvo.pub key into the avvo github acccount.
Finally, when creating the clone of whichever repo I was using, I didn't use the clone path that github gave me, I translated it to use the alias I created. For example, a clone URL like
git@github.com:avvo/fuzzy-find-in-project.git

becomes
github-avvo:avvo/fuzzy-find-in-project.git

Now, when pushing to the central repository, it will pick up the id_rsa.avvo key that I tied to the avvo github account, and send the code to the right place.

Thursday, October 23, 2008

Method of the Day: Array()

Another oldy but a goodie...

Array() wraps its parameter in an array. If it's already an array, it just returns it. If it's nil, it returns an empty array. It's super useful when you want to write a method that can take a single instance of an object or an array of objects.

Array(nil) => []
Array([]) => []
Array(1) => [1]
Array([1]) => [1]

def do_stuff(model_or_models)
models = Array(model_or_models)
models.each do |model|
# do stuff...
end
end