Code Golf: 99 Bottles of Beer

Jan 12, 2007  -  Comments

Here is my submission for the 99 Bottles of Beer challenge. Code size: 242 bytes.

a=' bottles of beer'
b=' on the wall'
d=a.tr 's',''
puts e+f+b+', '+e+f+'.'
puts 'Take one down and pass it around, '+(x-1).to_s+(x<3?d:f)+b+".\n\n"if x>1}
puts "Go to the store and buy some more, 99#{a+b}."

Tagged: code golfruby


Jan 22, 2007  -  Comments

Shawn recently turned me onto a really cool site: Code Golf. Every week (or so) they post a coding challenge. The challenges themselves aren't overly difficult (well, most aren't). The real challenge is to complete the challenge with as little code as possible. . . literally. Your code submissions are first evaluated to determine if they work like they should, then they count how many bytes your program takes up. The shortest program for each accepted language (Perl, PHP, Python, and Ruby) gets 10,000 points, with each longer program getting points based on their size relative to the winning submission.

I've only been able to complete two challenges so far. Both have fallen around the middle of the group with regards to size. I'm not sure I'll ever know the shortcuts to get my 228 byte program down to 102 bytes! It is a great excuse for exercising your brain, though.

UPDATE: I've started posting my submissions to the challenges that I've been able to complete. Just look for posts tagged with code golf.

Tagged: rubycode golf

Rails eager loading of associations

Feb 18, 2007  -  Comments

I ran into an interesting problem with table associations at work the other day. Below is a simple data model of the tables I was working with. Basically, here's how it breaks down: A user is part of any given group (but only one group per user). A document (any type) can be uploaded and assigned to a folder. A group is used to assign viewing privileges to each document, so that every user in the group can see the document. See below:

simple data model

The problem came up because once a user is logged in, I need to get all of the folders that contain documents that the user's group has permission to see (a folder could contain documents not viewable by the group). I spent a few minutes scratching my head on how best to do a find to get the results I needed. I really couldn't come up with anything that would work.

So, of course, when this happens, I do a little leg-stretching and walk over to Adam and Shawn's space to ask them how they would do it. After explaining the situation and a little white board art, they reminded me of eager loading of associations (which I've never really had to use).

By using the :include option in my find method call, I can pre-load table associations to make my complex query a lot easier. My code ended up looking like this:

# find the logged-in user
user = User.find(session[:intranet_user])
# get all of the folders that contain documents they have access to
@folders = Folder.find(:all, :include => {:documents => {:groups => :users}}, :conditions => "users.id = #{user.id}" )

This worked perfectly!

A note about eager loading of associations: they can save a lot of resources when used correctly. Say you have a table called books and a table called authors, and each book has one author. To get all of the books for display, you might put:

@books = Book.find(:all)

Then, in your page, you might have:

<% for book in @books -%>
	Title: <%= book.title %>
	Written by: <%= book.author.name %>
<% end -%>

Not only do you run a SQL query to get all of the books, you then run an additional query for each book to find it's author. You can simplify this down to only one query, by using eager loading, like so:

@books = Book.find(:all, :include => :author)

This pre-loads all of the data with only one SQL query.

Tagged: eager loadingrailsactiverecorddbtutorial

Rails inline ERb effects on HTML structure

Mar 31, 2007  -  Comments

When using Ruby on Rails, ERb (embedded Ruby) is used a LOT in the X/HTML. There are two types of ERb,

An evaluation block:

<% some_code %>

And an output block:

<%= @print_this_variable %>

These blocks are necessary when using Rails, and I've noticed that when I do a 'View Source' (via the Web Developer addon for Firefox, of course), I see a lot of funky spacing and line breaking where the ERb's have been evaluated. Probably fine for most people, but it makes reading the outputted HTML code a hassle.

It turns out that there are really three ways to use the evaluation ERb that can affect your spacing and line-breaking.

Firstly, the output block is used just like you'd expect to use it. If your code says this:

  Text before ERb.
  <%= "code_goes_here" %>
  Text after ERb

The resulting HTML will look just like this:

  Text before ERb.
  Text after ERb

Evaluation block use #1: If you just put a block, it will cause a line break after the block in the HTML, so if you had this in your code:

  Text before ERb.
  <% some_code %>
  Text after ERb

The resulting HTML code would look like this:

  Text before ERb.

  Text after ERb

Evaluation block use #2: If you add a dash(-) at the end of the block, it will prevent it from adding a line break. So, if your code looks like this:

  Text before ERb.
  <% some_code -%>
  Text after ERb

The resulting HTML code would look like this:

  Text before ERb.
    Text after ERb

The line break is gone, but the space taken by the block is still there. That leads us to. . .

Evaluation block use #3: If you add a dash(-) at the beginning AND end of the block, it will prevent it from adding a line break AND remove the leading space it would have taken up. So, if your code looks like this:

  Text before ERb.
  <%- some_code -%>
  Text after ERb

The resulting HTML code would look like this:

  Text before ERb.
  Text after ERb

You'd never know there was a code block there! Is this useful? I don't know... maybe.

Tagged: erbxhtmlrails

Generate random text with Ruby

Jun 07, 2007  -  Comments

UPDATE: Changed the generate_password method slightly based on commenter Dave Burt's suggestion.

I'm working on a project where the user can reset their password if they've forgotten it. So, I need to generate a random password and email it to them so they can login and change it. Fortunately, I found this neat little Ruby snippet that will generate random text of a given length:

def generate_password(length=6)
  chars = 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ23456789'
  password = ''
  length.times { |i| password << chars[rand(chars.length)] }

Some examples:

>> U48ydn

>> QzWXdAkDy5

Tagged: tutorialscriptruby

Parsing an RSS feed with Ruby

Jun 09, 2007  -  Comments

Parsing an RSS feed is insanely simple with Ruby. Two lines is all it takes. . .

require 'rss'
rss = RSS::Parser.parse(open('/feed/posts/index.html').read, false)

Now you'll have an Array of the results, so you can do something like:

rss.items.each { |i| puts "#{i.title} - #{i.date}" }

Tagged: tutorialrssruby

Adding multiple email attachments with Ruby on Rails

Jun 20, 2007  -  Comments

I was building some forms for a client that required the user be able to upload supporting documents along with the application. I had implemented emailable forms before with single attachments, but never multiple. Turns out, it was just as simple to do, I just needed to call the attach function for each file I wanted to attach.

Here is the method in my controller that calls the ActionMailer class to send the email, where params[:file1], params[:file2], and params[:file3] are the file_field_tag's from the form:

UPDATE: I've re-factored this after Shawn suggested that it could be simplified into an array and iterated over.

def submit_application
  @uploaded_files = []
  @uploaded_files << params[:file1]
  @uploaded_files << params[:file2]
  @uploaded_files << params[:file3]
  ContactMailer.deliver_email_with_attachments(params[:application], @uploaded_files)
  flash[:notice] = 'Your application has been submitted.  Thank you!'
  redirect_to application_home_url
rescue Exception => ex
  flash[:notice] = 'Uh oh!  There was an error sending your application.'
  redirect_to :back

And here is the ActionMailer method that attaches the files. I just need to iterate over the files, calling attach for each one.

def email_with_attachments(application_fields={},files=[])
  @headers = {}
  @sent_on = Time.now
  @recipients = 'client@domain.com'
  @from = 'info@domain.com'

  @subject = 'Here are some file attachments'
  application_fields.keys.each {|k| @body[k] = application_fields[k]}

  # attach files
  files.each do |file|
    attachment "application/octet-stream" do |a|
      a.body = file.read
      a.filename = file.original_filename
    end unless file.blank?

The "application/octet-stream" is the generic MIME type for attaching unknown file types.

Pretty simple!

Tagged: tutorialrailsemail attachmentactionmailer

HTTP GET and POST requests with Ruby

Nov 07, 2007  -  Comments

A while ago, I was working on a project for a client that used a third-party newsletter generator for capturing and storing email addresses. To add an email address, the application spits out some code for a form that you can put on your site. A user supplies his name and email address, then submits the form and it gets stored within the third-party app's database.

The problem arose when they wanted to automatically subscribe not only people who requested subscriptions, but also everyone who used the online contact form AND anyone who used the 'email to a friend' feature on one of the interior pages. Obvious misgivings aside, I set out to do what I was told (like any good drone).

The problem was, I needed to do a POST request to subscribe the person to the third-party app, but I couldn't do that with a regular form because I was already posting to the actual action being invoked. Luckily, Ruby has a built in Net::HTTP class for generating GET and POST requests from within the code.

Here is the method I needed to add the POST request to:

def email_to_friend
  ...other code...
  # now, do the dirty work
  require 'net/http'
  # get the url that we need to post to
  url = URI.parse('http://www.url.com/subscribe')
  # build the params string
  post_args1 = { 'email' => params[:email] }
  # send the request
  resp, data = Net::HTTP.post_form(url, post_args1)

The post_form method returns a Net::HTTPResponse object and an entity body string (in Ruby 1.8, it only returns the Net::HTTPResponse object). You can also use the post method.

Similarly, you can perform a GET request on a URL like so:

require 'net/http'
result = Net::HTTP.get(URI.parse('http://www.site.com/about.html'))
# or
result = Net::HTTP.get(URI.parse('http://www.site.com'), '/about.html')

The get method returns a String.

That's simple enough, right?

Tagged: railsgetposttutorial

Code Golf: Numeric Diamonds

Dec 08, 2007  -  Comments

Here is my submission for the Numeric Diamonds challenge. Code size: 219 bytes.

j.times{a<<[" "*w]*j}
1.upto(n){|t|a[x][y]=t.to_s.rjust w
t%s<1 ?(x=f+1;f=x;y=g-1;g=y):(x+=1;y+=1)}
a.each{|r|puts r.join.rstrip}}

Tagged: rubycode golf