belongs_to association callbacks fixed in rails 2.3.3

Posted: 07/20/2009

Last night I noticed certain callbacks weren’t being called for belongs_to associations in Rails 2.3.2. Here is a simple example to demonstrate:

class Foo < ActiveRecord::Base
  has_many :bars
end  
  
class Bar < ActiveRecord::Base
  belongs_to :foo
end

I overwrote the callbacks in both of these classes to print its name upon being called. Take a look at the output using Rails 2.3.2:

  Bar.create(:foo => Foo.new)

Callback order:

Bar before validation
Bar before validation on create
Bar validate
Bar validate on create
Bar after validation
Bar after validation on create
Foo before save
Foo before create
Foo after create
Foo after save
Bar before save
Bar before create
Bar after create
Bar after save

As you can see, none of the validation callbacks for Foo were called. Lucky for me, Rails 2.3.3 is out today and the problem seems to be fixed. Using the same models:

  Bar.create(:foo => Foo.new)

Callback order:

Bar before validation
Bar before validation on create
Bar validate
Bar validate on create
Bar after validation
Bar after validation on create
Foo before validation
Foo before validation on create
Foo validate
Foo validate on create
Foo after validation
Foo after validation on create
Foo before save
Foo before create
Foo after create
Foo after save
Bar before save
Bar before create
Bar after create
Bar after save

Now they are all called!

Also, it appears that this problem was introduced in Rails 2.3.2. The example above produced the same results with Rails 2.2.2 as it did with 2.3.3.

Comments



How To Send Email with Ruby and Gmail

Posted: 07/08/2009

I previously posted about sending email from Rails through your Gmail account. This is the first of two posts demonstrating sending and receiving emails from any old Ruby script. For sending emails, I wanted an interface like this:

  gmail = GmailSender.new(:login => 'yourgmail@example.com', 
                          :password => 'yourpass')
                       
  gmail.deliver(:to => 'friend@example.com', 
                :subject => 'Ricky A',
                :body => "ShirtsTasteGood has two rick astley shirts")

This is my implementation: [shrink code]

require 'net/smtp'
require 'rubygems'
require 'tlsmail'
  
Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
  
class GmailSender
  SMTP_ADDR = 'smtp.gmail.com'
  
  def initialize(opts = {})
    unless opts[:login] && opts[:password]
      raise ArgumentError.new("provide login and password") 
    end
    @login = opts[:login]
    @password = opts[:password]
    @domain = @login[/@(.+)$/,1]
  end
  
  def deliver(opts = {})
    tostr = opts[:to].is_a?(Array) ? opts[:to].join(', ') : opts[:to]
    msg = ["FROM: #{@login}",
           "TO: #{tostr}",
           "SUBJECT: #{opts[:subject]}"]
    msgstr = msg.join("\n") << "\n\n#{opts[:body]}"
    smtp_args = [SMTP_ADDR, 25, @domain, @login, @password, :login]
    Net::SMTP.start(*smtp_args) do |smtp|
      status = smtp.send_message msgstr, @login, opts[:to]
      puts status
    end
  end
end

I made this single file into a local gem, so now I’m ready to write command line email hacks to my heart’s content. Now if you are thinking, “why don’t you just use ActionMailer and tlsmail like you did in the Rails example?” Well, this is the best explanation I’ve got. Next up, receiving emails from GMail!

Comments



Top search result for "dick gallery"

Posted: 07/06/2009

Google webmaster tools shows you the most popular queries that return your pages in the search results. It looks something like this:

I was pretty excited to see we were on the front page for our grape lady t-shirt already! Then I noticed this gem a bit farther down the page, and knew I had to share:

Thank you Google.

Comments



Pre-fill forms in development

Posted: 07/05/2009

Automated testing is great, but I often want to click through the many pages of my application myself, without slowing down to fill in form data. I use three javascript functions to provide a simple way for me to pre-fill form data. Say I have an order form that takes a first name, last name, and credit card type. Like this:

  <form>
    <input name="order[first_name]" type="text">
    <input name="order[last_name]" type="text">
    <select name="order[card_type]">
      <option value="visa">Visa</option>
      <option value="american_express">American Express</option>
    </select>
  ...
  </form>

I could write a javascript file that I only include in my development environment that would look like this:

  fill('order[first_name]', "Lou");
  fill('order[last_name]', "Zell");
  select('order[card_type]', "American Express");

The javascript functions that enable me to do this:

function find(name){
  n = document.forms.length
  for (var i=0; i < n; i++){
    k = document.forms[i].elements.length
    for(var j=0; j < k; j++){
      if(document.forms[i].elements[j].name == name){
        return(document.forms[i].elements[j])
      }
    }
  }
}
  
function fill(name, content){
  find(name).value = content;
}
  
function select(name, content){
  s = find(name)
  for (var i = 0; i < s.options.length; i++){
    if (s.options[i].innerHTML == content){
      s.selectedIndex = i;
      return;
    }
  }
}

These functions don’t rely on any library, and they also shouldn’t be used in production because they are far from optimized. Yes, I am 100% sure there is a much more efficient way to write them, but they work just fine for what I need them to do.

If you want to get fancy pants you could create different sets of data to fill a form with, and attach each fill function to a link’s click event. Something like:

  <a id="fill_with_bob">fill with bob's info</a>
  <a id="fill_with_jane">fill with jane's info</a>

  $('#fill_with_bob').click(function(){
    fill('order[first_name]', "Bob");
    fill('order[last_name]', "Jones");
    select('order[card_type]', "American Express");
  });
    
  $('#fill_with_jane').click(function(){
    fill('order[first_name]', "Jane");
    fill('order[last_name]', "Jones");
    select('order[card_type]', "Visa");
  });

I used jquery for that last part. And it’s not tested.

Comments



Steer Clear of Paypal

Posted: 06/23/2009

If you are considering using Paypal’s Website Payments Pro service for $30 per month, I would think twice. I was warned that their customer service was atrocious, but it’s much worse. If you are currently using them, you already know that every phone number they provide to reach merchant services directly takes you through the same automated system as every other Paypal number. Here are the steps I recommend to get you through to someone that can help, without losing your mind:

1. Take a shot (and one additional shot for each time you are disconnected)
2. Call any of several “direct lines” to merchant services
3. Say “no” when the automated system picks up
4. Say “agent” three times in a row, you will be placed on hold
5. You will get an agent, but they will be in the wrong department. They will inevitably discover that they cannot help you, and will transfer you to the merchant support group (which is the one you wanted in the first place). So save yourself the pain and demand an immediate transfer to merchant support. You will be on hold again for a while.

Good luck!

Comments



ShirtsTasteGood.com, YouTube™ Inspired T-Shirts!

Posted: 06/16/2009

I am very proud to announce ShirtsTasteGood.com, a collection of t-shirts inspired by our favorite YouTube™ videos. It’s a four man team consisting of Todd Hamilton on artwork and web design, Doug and George Cline on screen printing, and myself on web development. Doug and George ditched their custom screen printing business that they had been running for the last few years, and Todd and I both quit our contracting/freelancing gigs in the city to full time STG. The operation is run out of a barn that Doug and George converted to a print shop near their home in New Jersey. The video that inspired each shirt is embedded on the shirt’s home page, so even if you aren’t interested in buying a t-shirt, you can come hang out and watch some hilarious videos. There is also a suggestions page where we auto-embed any videos that you would like us to turn into shirts! The suggestions page is particularly useful during that 1-3pm slot when you pretend to be working. We hope you enjoy the site, and please feel free to post any suggestions, questions, or comments. Thanks!

Comments



The Hudson Raft Project

Posted: 06/04/2009

Over the last four years a few friends of mine, led by Dallas Trombley, have attempted to sail from Albany to Manhattan on homemade boats. They now have a site up describing their trials and tribulations. Most of their content is in the form of Wordpress pages rather than posts, so be sure to check out the left nav. It’s a really entertaining read. Good luck this year Dallas, Rob, and Co.

Comments



Disable SSL during Rails development

Posted: 05/26/2009

Assuming you are using ssl_requirement, to disable SSL in your development environment:

class ApplicationController < ActionController::Base
  include SslRequirement
  
  protected
  def ssl_required?
    RAILS_ENV != 'development' && super
  end
end

Comments



Deploying Wordpress with Rails on Passenger

Posted: 05/20/2009

I just finished integrating a Wordpress blog into a soon-to-be released Rails app, and I would like to share the steps I took to get it deployed on Phusion Passenger. Getting the permalinks working correctly had me hung up for a bit, so I’ll show you how to get around that.

To get started we can drop the blog right into the public directory of our rails app:

  cd /yourapp/public
  wget http://wordpress.org/latest.tar.gz
  tar xzvf latest.tar.gz
  mv wordpress blog     <--- blog will be at http://yourapp/blog
  cd blog
  mv wp-config-sample.php wp-config.php

Now edit the wp-config.php file (instructions are in the file) and be sure to grant database privileges to the user you specify.

Next, you have to edit your apache config file to disable passenger for the blog directory:

<VirtualHost ...>
    ServerName ...
    DocumentRoot ...
    <Location /blog>
       PassengerEnabled off
    </Location>
</VirtualHost>

I found that snippet here.

Restart Apache and point your browser to http://yourapp/blog/index.php to setup the rest of your blog through Wordpress’s web interface. One thing you will probably edit is the default permalink structure (Found at settings > permalink). I prefer to set a custom structure of ‘/%postname%’. Regardless of the structure you use, wordpress will tell you to edit the .htaccess file in your blog directory. For the life of me I could not get .htaccess file to be recognized, so as a workaround I copied the snippet that wordpress specified into my apache config as follows:

<VirtualHost ...>
    ServerName ...
    DocumentRoot ...
    <Location /blog>
       PassengerEnabled off
       <IfModule mod_rewrite.c>
         RewriteEngine On
         RewriteBase /blog/
         RewriteCond %{REQUEST_FILENAME} !-f
         RewriteCond %{REQUEST_FILENAME} !-d
         RewriteRule . /blog/index.php [L]
       </IfModule>
    </Location>
</VirtualHost>

Finally, restart Apache.

Comments



A more readable sort by

Posted: 04/03/2009

Suppose we want to sort a collection of accounts by their account balance. We could put them in ascending order like this:

  @accounts.sort {|x,y| x.balance <=> y.balance}

Or descending order like this:

  @accounts.sort {|x,y| y.balance <=> x.balance}

To me this isn’t very readable. How about this as an alternative:

  @accounts.sort_by_ascending(:balance)
  # or 
  @accounts.sort_by_descending(:balance)

Much more readable. The implementation is pretty simple, first create the methods:

  module ReadableSortBy
    def sort_by_ascending(method)
      sort {|x, y| x.send(method) <=> y.send(method)}
    end
    def sort_by_descending(method)
      sort {|x, y| y.send(method) <=> x.send(method)}
    end
  end

Then include them in Array:

  class Array
    include ReadableSortBy
  end

You could also make sort_by_ascending! and sort_by_descending! methods that modify the collection itself. Do this by replacing sort with sort! in both cases.

Comments



Introducing Nickel

Posted: 03/29/2009

A natural language date and time parser, with message extraction

Nickel is a client for Natural Inputs

  sudo gem install lzell-nickel

Then try it out:

  require 'rubygems'
  require 'nickel'
  n = Nickel.query "party this friday at 10pm"
  
  n.message # => party
  n.occurrences.first.start_date # => 20090403
  n.occurrences.first.start_time # => 22:00:00

Many more examples here.

Comments



A cheap abstract class in ruby

Posted: 03/29/2009

When I create a class that I don’t want to allow anyone to instantiate, I use the following pattern:

  class MakeMeAbstract
    def initialize
      raise "Don't instantiate me!" if abstract_class?
      puts "Instantiated!"
    end
    private
    def abstract_class?
      self.class == MakeMeAbstract
    end
  end

It can’t be instantiated:

  MakeMeAbstract.new rescue puts "I'm abstract"   # => "I'm abstract"

But it can be subclassed, and the subclass can be instantiated:

  class Child < MakeMeAbstract
  end
  Child.new   # => "Instantiated!"

As a full disclaimer, this is a learning experience for me. When subclassing an abstract class I wonder if it would be better to use a mixin instead: I could overwrite mixed in methods just as easily as methods in a parent class. The structure changes from this:

  class Bar
    def status
      print "is full"
    end
  end
  class WetBar < Bar
    def status
      print "is wet, "
      super
    end
  end
  wet_bar = WetBar.new
  wet_bar.status    # => "is wet, is full"

To this:

  module Bar
    def status
      print "is full"
    end
  end
  class WetBar
    include Bar
    def status
      print "is wet, "
      super
    end
  end
  wet_bar = WetBar.new
  wet_bar.status    # => "is wet, is full"

Input is welcome in the comments.

Comments



How to backup and restore a mysql database

Posted: 03/29/2009

To dump your database:

  mysqldump -u USER -p PASS my_db > my_db.sql

Then to restore:

  mysql -u USER -p PASS my_db < my_db.sql

Or, using gzip for compression, dump with:

  mysqldump -u USER -p PASS my_db | gzip > my_db.sql.gz

And restore with:

  gzip -cd my_db.sql.gz | mysql -u USER -p PASS my_db

Comments



Using Gmail with Rails

Posted: 03/29/2009

To send email from Rails using your Google Apps account, you will need TLS support:

  sudo gem install tlsmail

Next, edit environment.rb to look like this:

  Rails::Initializer.run do |config|
    config.gem "tlsmail"
    ...
  end
  Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)

Then add this to environments/development.rb:

  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
    :address => "smtp.gmail.com",
    :port => "25",
    :domain => "your_domain.com",
    :user_name => "your_login@your_domain.com",
    :password => "your_password",
    :authentication => :login
  }

Test it out by sending an email to yourself, create the model mailer.rb:

  class Mailer < ActionMailer::Base
    def test
      from "your name <your_login@your_domain.com>"
      recipients ["your_login@your_domain.com"]
      subject "working?"
      body "sending from rails"
    end
  end

Finally, from script/console:

  Mailer.deliver_test

Comments



Use inject for nicer output in IRB

Posted: 03/29/2009

Sometimes you want to inspect an array in irb by iterating through it and printing out some key values, for example:

  events.each do |event|
    puts event.title
  end

But if the array is large, you will first have to scroll up through the returned array to get to your desired printout. We can prevent that by using inject instead:

  events.inject do |x, event|
    puts event.title
  end

Now nil will be returned instead of the events array, and your desired output is in view.

Comments



Preventing default event behavior with Javascript

Posted: 03/29/2009

with examples using jQuery and Prototype

Let’s say we want to disable all the links on a page, using jQuery we just have to return false from the click handler:

  jQuery(function(){
    jQuery('body a').click(function(){
      return false;
    });
  });

Using Prototype, we pass the event instance to Event.stop():

  document.observe("dom:loaded", function(){
    $$('body a').each(function(a, num){
      $(a).observe('click', function(e){
        Event.stop(e);
      });
    });
  });

With everyday Javascript, we again return false from the click handler:

  window.onload = function(){
    elements = document.getElementsByTagName('a');
    for (var i = 0; i < elements.length; i++){
      elements[i].onclick = function(){
        return false;
      }
    }
  }

Comments



Ruby Bitwise Notes

Posted: 03/29/2009

Start with an integer:

  x = 1

Shift by two bit positions:

  x <<= 2

OR with 1:

  x |= 1

AND with 14 (hex E):

  x &= 0xE
  # is the same as:
  x &= 14

Get binary representation:

  x.to_s(2)

Get hex representation:

  x.to_s(16)

XOR (exclusive OR) with 1

  x ^= 1

Comments



Vim single line move when :set wrap is on

Posted: 03/29/2009

If you are editing a long paragraph with word wrap on, you may find that ‘j’ and ‘k’ jump farther than you would expect. This is because ‘j’ is moving to the next real line instead of the next wrapped line. To make vim behave more intuitively (at least for me, and probably you since you are here), put this in your vim config file (~/.vimrc in my case):

  function! ScreenMovement(movement)
     if &wrap
        return "g" . a:movement
     else
        return a:movement
     endif
  endfunction
  onoremap   j ScreenMovement("j")
  onoremap   k ScreenMovement("k")
  onoremap   0 ScreenMovement("0")
  onoremap   ^ ScreenMovement("^")
  onoremap   $ ScreenMovement("$")
  nnoremap   j ScreenMovement("j")
  nnoremap   k ScreenMovement("k")
  nnoremap   0 ScreenMovement("0")
  nnoremap   ^ ScreenMovement("^")
  nnoremap   $ ScreenMovement("$")

Thanks to rick_h in #vim

Comments



Rails 2.2 migrations without the timestamp

Posted: 03/28/2009

For Rails 1 style migrations, set this in environment.rb:

  config.active_record.timestamped_migrations = false

Note this will not work before Rails 2.2. Thanks to mikeg1a in #rubyonrails.

Comments



Edit through FTP with TextMate and Cyberduck

Posted: 03/28/2009

I do a bit of freelance php work where I need to edit files through FTP. Textmate does not support this very well out of the box, and at first it seemed like I would have to open and edit each file in its own window. But by combining this tip by subtlegradient with this tip by ciaranwal.sh we can use tabbed editing, project drawer, and cmd+t to switch files. The steps:

1. In Cyberduck’s preferences make sure external editor is set to TextMate. Also, it helps if “Double click opens file in external editor” is set to true.

2. Open up a file from your FTP project that is close to the top level directory of your project, you’ll see why in a minute.

3. In the TextMate window that popped up, hit ctrl+shift+o (Bundles > Shell Script > Open Terminal). The terminal will open at the temporary location where the file you are editing is.

4. cd .. back to the top level directory of your project and enter: mate .

Now any subsequent files you open using Cyberduck will be added as tabs in the current TextMate project.

Comments



GoLark Mobile

Posted: 03/28/2009

The GoLark iPhone Application was released this week, making GoLark one step closer to providing us with local events, anywhere, at any time.

Currently, two of GoLark’s lists are supported on the iPhone: Top Larks and Top Recurring Larks. Date and time filtering–although slightly stripped down–is also provided. The app is purposely minimal in design, providing a clear and simple interface to the best local events.

Check it out at iphone.golark.com

Comments



Create a sick game with Processing

Posted: 03/28/2009

I did a little experimenting with Processing, a language written for artists, graphics designers, and anyone interested in learning something new. I was very impressed with how easy it was to get started. The download comes with tons of simple example projects, and the API reference is easy to understand. I had hopes of Processing opening a whole, previously undiscovered, artistic side of my brain — it didn’t. But I did make a killer “blow up the falling spheres with my triangle’s laser” game. Check it out:

Wow, that screen shot makes it look even more lame than it really is (hard to do).

I know, I know, you want the code so you can try this game out for yourself. Here it is, paste into Processing and hit play:

  PFont fontA;
  int sphereDiameter = 10;
  boolean shoot = false;
  
  int randx()
  {
    return int(random(600));
  }
  
  int[] sphereXCoords = { randx(), randx(), randx(), randx(), randx() };
  int[] sphereYCoords = { 0, 0, 0, 0, 0 };
  
  void setup()
  {
    size(600,620);
  }
  
  void draw()
  {
    background(0);
    fill(color(0,255,0));
    stroke(color(0,255,0));
    triangle(mouseX-8, 580, mouseX+8, 580, mouseX, 565);
    fill(color(255,0,0));
    stroke(color(255,0,0));
  
    if(shoot==true)
    {
      sphereKiller(mouseX);
      shoot = false;
    }
  
    sphereDropper();
    gameEnder();  
  }
  
  void mousePressed()
  {
    shoot = true;
  }
  
  void sphereDropper()
  {  
    stroke(255);
    fill(255);
    for (int i=0; i<5; i++)
    {
      ellipse(sphereXCoords[i], sphereYCoords[i]++,
              sphereDiameter, sphereDiameter);
    }
  }
  
  void sphereKiller(int shotX)
  {
    boolean hit = false;
    for (int i = 0; i < 5; i++)
    {
      if((shotX >= (sphereXCoords[i]-sphereDiameter/2)) && 
         (shotX <= (sphereXCoords[i]+sphereDiameter/2)))
      {
        hit = true;
        line(mouseX, 565, mouseX, sphereYCoords[i]);
        ellipse(sphereXCoords[i], sphereYCoords[i],
                sphereDiameter+25, sphereDiameter+25);
        sphereXCoords[i] = randx();
        sphereYCoords[i] = 0;
      }    
    }
  
    if(hit == false)
    {
      line(mouseX, 565, mouseX, 0);
    }  
  
  }
  
  void gameEnder()
  {
    for (int i=0; i< 5; i++)
    {
      if(sphereYCoords[i]==600)
      {
        fill(color(255,0,0));
        noLoop();
      }
    }
  }

Comments



How to modify the GNU linker's default search path

Posted: 03/28/2009

I installed GNU’s Scientific Library and Ruby’s wrapper for GSL on Ubuntu and OS X without any problems. Next up: CentOS. The install appeared to complete successfully, but a require ‘gsl’ from irb showed otherwise:

  LoadError: libgsl.so.0: cannot open shared object file: 
  No such file or directory

I located libgsl.so.0 in /usr/local/lib; so the problem is with the linker finding a shared library. The way I fixed this during the memcached install was to add the --rpath linker flag during the build. But I don’t wan’t to keep running into this in the future, so I decided to add /usr/local/lib to ld’s default search path, here’s how:

Open /etc/ld.so.conf in your editor and make sure there is a single line that reads:

  include ld.so.conf.d/*.conf

Then, from your shell prompt:

  echo "/usr/local/lib" >> /etc/ld.so.conf.d/loc_lib.conf
  /sbin/ldconfig

That should do it.

If you would like to learn more on the subject, this is the best documentation I have found on Shared Library Search Paths.

Comments



Benchmarking Ruby Time and Date instantiation

Posted: 03/28/2009

A comparison of various ways to represent dates and times in ruby. I am creating October 10, 2007 in every case, here are the tests:

  n=10000
  Benchmark.bm(10) do |test|
    test.report("Date.strptime: ") do
      n.times {Date.strptime("20071001","%Y%m%d")}
    end 
    test.report("Date.parse: ") do
      n.times {Date.parse("20071001")}
    end 
    test.report("Time.now: ") do
      n.times {Time.now}
    end 
    test.report("Date.new: ") do
      n.times {Date.new(2007, 10, 1)}
    end 
    test.report("DateTime.civil: ") do
      n.times {DateTime.civil(2007, 10, 1)}
    end 
    test.report("DateTime.parse: ") do
      n.times {DateTime.parse("20071001")}
    end 
    test.report("DateTime.strptime: ") do
      n.times {DateTime.strptime("20071001","%Y%m%d")}
    end 
    test.report("Time.local: ") do
      n.times {Time.local(2007, "oct", 1)}
    end 
    test.report("Time.parse: ") do
      n.times {Time.parse("20071001")}
    end 
    test.report("Time.quick_parse: ") do
      n.times {Time.quick_parse("20071001")}
    end 
  end

Time.quick_parse is a method that I defined, it’s going to be the fastest way to parse a string in the form “YYYYMMDD”:

  class Time
    class << self
      # Usage:  Time.quick_parse("YYYYMMDD")
      def quick_parse(date_str)
        local(date_str[0..3], 
              RFC2822_MONTH_NAME[date_str[4..5].to_i - 1],
              date_str[6..7])
      end
    end
  end

The results:

                      user        system      total        real
  Date.strptime:      2.890000    0.040000    2.930000    (  2.982972)
  Date.parse:         3.630000    0.050000    3.680000    (  3.755735)
  Time.now:           0.010000    0.000000    0.010000    (  0.008608)
  Date.new:           0.590000    0.010000    0.600000    (  0.597446)
  DateTime.civil:     1.640000    0.010000    1.650000    (  1.675539)
  DateTime.parse:     4.970000    0.050000    5.020000    (  5.066107)
  DateTime.strptime:  4.250000    0.050000    4.300000    (  4.342663)
  Time.local:         0.120000    0.000000    0.120000    (  0.123242)
  Time.parse:         1.720000    0.010000    1.730000    (  1.750917)
  Time.quick_parse:   0.150000    0.000000    0.150000    (  0.157280)

The version of Ruby that I’m using:

  ruby -v 
  ruby 1.8.6 (2008-03-03 patchlevel 114) [universal-darwin9.0]

Comments



How to install memcached on CentOS

Posted: 03/28/2009

This is a step by step guide to installing memcached from source on CentOS. The version of CentOS that I am using is CentOS release 5.2 (Final); to find what version you are using:

  cat /etc/redhat-release

First, install the dependency libevent:

  cd /usr/local/src
  curl -O http://monkey.org/~provos/libevent-1.4.9-stable.tar.gz
  tar xzvf libevent-1.4.9-stable.tar.gz 
  cd libevent-1.4.9-stable
  ./configure --prefix=/usr/local
  make
  make install

Next, install memcached:

  cd /usr/local/src
  curl -O http://www.danga.com/memcached/dist/memcached-1.2.6.tar.gz
  tar xzvf memcached-1.2.6.tar.gz
  cd memcached-1.2.6
  LDFLAGS='-Wl,--rpath /usr/local/lib' ./configure --prefix=/usr/local
  make 
  make install

Verify that memcached starts:

  memcached -u root -d 

If there were no errors, make sure it is running:

  ps aux | grep memcached

And finally, to stop memcached:

  pkill memcached

These instructions prevent the following errors:

  memcached: error while loading shared libraries: libevent-1.4.so.2: 
  cannot open shared object file: No such file or directory
  configure: error: libevent is required
  If it's already installed, specify its path using --with-libevent=/dir/

Comments



Detecting the enter key with javascript

Posted: 08/02/2008

In this how-to we will inspect a key-press triggered event instance to determine if the enter key was pressed. The event instance has a property called keyCode, which indicates the enter key when set to 13. Let’s start with a text input:

  <input type="text" id="foo">

We can write an event handler to alert the contents of this field when enter is pressed:

  document.getElementById('foo').onkeypress = function(e){
    if (!e) e = window.event;   // resolve event instance
    if (e.keyCode == '13'){
      alert(this.value);
      return false;
    }
  }

IE will append the event instance to the window instead of passing it as a parameter to the handler, so the first line of our handler ensures that e is set to the event instance, regardless of browser. Next we see if keyCode is equal to ‘13’, which indicates the enter key. If enter was pressed we alert the contents of the text box and return false. We return false in case our input is within a form and we want to prevent the event’s default behavior (i.e. submitting the form).

Let’s try it out, type something in the field below and hit enter:

I would also like to mention that there is no need to resolve the event instance if we use jquery or prototype. Here is how we would accomplish the same thing with jquery:

  $('#foo').keypress(function(e){
    if (e.keyCode == '13'){
      alert(this.value);
      return false;
    }
  });

And finally, with prototype:

  $('foo').observe('keypress', function(e){
    if (e.keyCode == '13'){
      alert(this.value);
      Event.stop(e);
    }
  });

Comments



How to use ruby variables in regular expressions

Posted: 08/02/2008

If you do not know the pattern that you are trying to match ahead of time (e.g. it is some form of user input), you can construct a regex from a string:

  str = "this string has ruby in it"
  re = "ruby"
  str =~ /#{re}/    # => 16

You can also combine components to create a new pattern:

  a = 'ruby'
  b = 'on rails'
  str = "this string has ruby on rails in it"
  str.match(/#{a} #{b}/)    # => true

If you are looking for a way to create patterns from combinations of common elements, and the elements are not derived from input, it is just as easy to combine Regexp objects:

  a = /ruby/
  b = /on rails/
  str = "this string has ruby on rails in it"
  str.match(/#{a} #{b}/)  # => true

Comments



About Me

I'm a skier, web developer, entrepreneur, freelancer, and all around stand-up guy living in Manhattan. This is me, repping one of my favorite shirts...

Follow me on twitter or send me an email.

All Posts