s

Code Golf: Choose

Jan 16, 2008  -  Comments

Here is my submission for the Choose challenge. Code size: 88 bytes.

def g(r)(1..r).inject(1){|m,n|m*n}end
x,y=gets.split.map{|n|n.to_i}
p g(x)/(g(y)*g(x-y))

Tagged: rubycode golf

Site Rewrite

Jun 08, 2008  -  Comments

I've been really lazy about updating the blog lately. I'd like to say that I've been busy working on some cool new project, but the reality is that I bought a PS3 a few months ago, and all of my free time has been taken up by Call of Duty 4 and Grand Theft Auto. By the way, if you're on PSN, send me a friend request (deadwards).

To try and force myself to get back into the blog, I decided to re-write it since Rails 2.1 was recently released. It was really funny looking at some of my old code (keep in mind, I originally wrote this blog as my first foray into Rails, circa May 06). All of the code has at least been refactored, and in many cases totally re-written. I've also added caching where I can to increase the speed a bit. Hopefully, this will be the kick in the ass I need to get back to blogging.

ps I finally broke down and created a Twitter account.

Tagged: railstwitter

Rails Tips

Jul 13, 2008  -  Comments

While there are no shortages of posts listing tips for Rails, or lesser-known Ruby methods, I decided to write this post because these are shortcuts or helpers that I didn't know about until fairly recently. I'm going to try and update this post as I discover new railties and rubyisms along the way, so check back every now and then.


Symbol#to_proc

This is really a Ruby method, but it makes running a collect or map on ActiveRecord objects much easier. Whereas before, you would do this:

@members = Member.find(:all).map { |member| member.name }

Now, you can simplify it to this:

@members = Member.find(:all).map(&:name)

Model Calculations

This will let you do simple calculations on any ActiveRecord model (as long as the field you're calculating is numeric).

Student.average(:grade) # finds the average grade for all students (returns a float)
Student.maximum(:grade) # finds the highest grade
Student.minimum(:grade) # finds the lowest grade
Student.sum(:grade) # the sum of all grades

Custom ActiveRecord Associations

Let's say you have a model called BlogPost and one called Comment. A blog post has many comments, but you also have a boolean field on comments called approved that signifies if it's been decided that the comment is not spam (like most comments are). This is what your BlogPost model might look like:

class BlogPost < ActiveRecord::Base
  has_many :comments
end

You can add custom associations for approved_comments and unapproved_comments to your model to make fetching these comments a lot easier.

class BlogPost < ActiveRecord::Base
  has_many :comments
  has_many :approved_comments, :class_name => 'Comment', :conditions => 'approved=1'
  has_many :unapproved_comments, :class_name => 'Comment', :conditions => 'approved=0'
end

All you have to do is specify the class name of the associated model and the conditions of the find. This makes it possible to easily access these associations from within your views.

You can now show the number of approved comments for each post.

<%= @blog_post.title %> - <%= @blog_post.approved_comments.count %> Comments

You can also easily list out the approved comments.

<%- @blog_post.approved_comments.each do |comment| -%>
  <%= comment.author %> said:
  <%= comment.content %>
<%- end -%>

UPDATE: Shawn reminded me this week about named_scope, which was added in Rails 2.1. It makes custom associations a bit easier and more full-featured. You can get the same approved and non-approved comments with named_scope:

class Comment < ActiveRecord::Base
  belongs_to :blog_post
  named_scope :approved, :conditions => ["approved = ?", true]
  named_scope :unapproved, :conditions => ["approved = ?", false]
end

Notice that now the named_scope declarations go in the Comment model instead of the BlogPost model like the custom associations. You get the approved comments for a post with this line:

<%= blog_post.comments.approved %>

You can also combine named_scope calls when selecting records. Suppose our Comment model now has a named_scope for both approved and unapproved comments, as well as comments made by anonymous authors.

class Comment < ActiveRecord::Base
  belongs_to :post
  named_scope :approved, :conditions => ["approved = ?", true]
  named_scope :unapproved, :conditions => ["approved = ?", false]
  named_scope :anonymous, :conditions => ["name = ?", 'Anonymous']
end

You can use this to find all of the approved comments for a post where the author is 'Anonymous'.

<%= blog_post.comments.approved.anonymous %>

To add even more functionality to named_scope, you can add conditions to the call on the fly.

<%= post.comments.approved.all(:conditions => ["created_at > ?", 2.weeks.ago]) %>

This will pass the additional date condition to the find, making it possible to refine your searches even more.


Render Partial with Collection/Object

This is how I've always done my partials.

The view (index.html.erb):

<%- @posts.each do |post| -%>
  <%= render :partial => 'post', :locals => {:post => post} %>
<%- end -%>

The partial (_post.html.erb):

<%= post.title %> written by <%= post.author %>

I can simplify the call to the partial down to only one line of code (the partial itself will stay the same).

<div id="all_posts">
  <%= render :partial => 'post', :collection => @posts %>
</div>

By specifying the collection option, the view will call the partial post for each item in the @posts array.

But, let's say I wanted to call the partial for only one post. The old way:

<div id="single_post">
  <%= render :partial => 'post', :locals => {:post => @post} %>
</div>

Not terrible, but we can make it easier with the object option.

<div id="single_post">
  <%= render :partial => 'post', :object => @post %>
</div>

This will call the partial, and pass it only the object that we specify. Shorter and cleaner.


RJS with link_to_function

If you have several things on your page that need to be updated, and you want to do it with a javascript call instead of an AJAX call to the server, you can do it by passing a block to the link_to_function method.

Suppose this is my view:

<div id="list">
  <p id="list_title"><%= @list.title %></p>
  <div id="list_items">
    <%= render :partial => 'item', :collection => @list.items %>
  </div>
  <%= link_to_function 'Change it up' do |page|
    page.replace_html 'list_items', 'New Item Title'
    page.hide 'list_items'
  end %>
</div>

This is a poor example, but hopefully you can see what I'm trying to illustrate here.


Simplified FIND in Rails 2.1

With the release of Rails 2.1, they've added some much-needed find methods for easily getting all, first and last records for a model.

@all_posts = Post.all
@first_post = Post.first
@last_post = Post.last

And, of course, you can pass conditions and order options to the new find methods.

@all_posts = Post.all(:order => :updated_at)
@first_post = Post.first(:conditions => ["title LIKE ?", '%Rails%'])
@last_post = Post.last(:order => 'created_at DESC')

Tagged: tutorialtipsrubyrails

Routes Demystified

Aug 02, 2008  -  Comments

It took me a while to discover the full potential of Rails' routes. I slowly learned more and more neat stuff that made me like them more and more. They are extremely powerful and are very useful for URL re-writing. Following is all of my route knowledge. If you notice something that I didn't cover, please leave it in the comments.

A few basic routes:

# this will route domain.com/ to the index action of your main controller
map.connect '', :controller => 'main'

# this will create a custom URL for your about-us page
map.connect 'custom-url/about-us', :controller => 'about_us', :action => 'index'

Pay attention to the order of your routes in your routes.rb file. They are evaluated in order from top to bottom. Routes at the top will be used before routes at the bottom if they are too similar.

Named Routes

Instead of saying map.connect, let's get crazy and name our routes. I'll use the same routes as above and add a few.

# you can now call this route with home_path or home_url
map.home '', :controller => 'main'

# call this route with about_us_path or about_us_url
map.about_us 'custom-url/about-us', :controller => 'about_us', :action => 'index'

# symbols in the routes define options you pass when calling the route
# call product_details_path(:id => @product) to access this route
map.product_details 'products/detail-view/:id', :controller => 'products', :action => 'show'
# all-purpose route for the products controller : products_path(:action => 'search') or products_path(:action => 'buy', :id => product)
map.products 'products/:action/:id', :controller => 'products'

Route Blocks Using with_options

If we have several routes for the same controller, it makes sense to use with_options to simplify the definitions.

map.with_options :controller => 'news' do |m|
  m.news 'news-releases/list', :action => 'index' # news_path
  m.news_details 'news-releases/details/:id', :action => 'show' # news_details_path(:id => news_release)
  m.news_author 'news-releases/by-author/:name', :action => 'author' # news_author_path(:name => 'Bill')
end

Better URLs with Routes

Routes are great for creating search engine friendly URLs. Supposed you'd like to add the title of your blog post to the URL.

map.blog_details 'blog/details/:id/:title', :controller => 'blog', :action => 'show', :title => nil

Now you can call the blog_details path and give it the :id and :title as options for the URL. Also notice that I set :title => nil at the end of the route. This marks that option as optional for the route call.

# this call will generate the following URL: http://domain.com/blog/details/1/My-First-Blog-Post
# I'm using a helper method in this call entitled 'strip_chars', it is below
blog_details_path(:id => post, :title => strip_chars(post.title)) %>

# you can also omit the title when invoking the route because it is optional.
# since your 'details' method will be using the :id parameter to find the record
# we don't really need the title, it's just for search engines
blog_details_path(:id => post) %>

# this helper method takes a string, replaces all spaces with dashes, then strips out all non-letter, non-number, non-dashes
# it's good for generating URL-friendly titles
def strip_chars(string='')
  return '' if string.blank?
  string.gsub(' ','-').gsub(/[^a-z0-9\-]+/i, '')
end

Caching and Pagination

If we cache our site, and certain actions show a paginated list, then we need to add the :page attribute to the route to ensure that the cache is recorded properly. After all, to our server /blog/list looks the exact same as /blog/list?page=2 when retrieving cached pages.

map.blog 'blog/list/:page',
         :controller => 'blog',
         :action => 'list',
         :requirements => {:page => /\d+/},
         :page => nil
# blog_path
# blog_path(:page => 1)

Notice that we added something new, the :requirements option. For :page, it's a regular expression telling us the supplied value must be a number. I've also set :page => nil so that we don't always have to specify it when invoking the route.

One thing to watch out for when calling a paged route is to be careful when you're on another paged section of your site. Say I have the route above for blogs and a similar route for news releases. If I'm on the page /news/list/5 and I call blog_path it will take the :page parameter from the current URL and you'll end up on page 5 of your blog post list. Confused? Just make sure when you are calling a paged route to specify it as blog_path(:page => 1) to explicitly go to /blog/list/1 or call blog_path(:page => nil) to go to /blog/list. Both will work.

Route Conditions

Similar to RESTful routes, you can specify the method of the request with the :requirements option. While this is useful, it makes much more sense to just use map.resources to get real RESTful routes.

map.connect 'blog-post/:id', :controller => 'blog', :action => 'show', :requirements => { :method => :get }
map.connect 'blog-post/:id', :controller => 'blog', :action => 'update', :requirements => { :method => :post }

# a GET method to /blog-post/1 will route to the 'show' action
# a POST method to /blog-post/1 will route to the 'update' action

I think that's enough for normal routes. Hopefully soon I can write a post on RESTful routes, which are a whole different beast.

Tagged: tutorialrailsroutes

Working with the flash hash

Aug 17, 2008  -  Comments

The flash hash is what Rails uses to display messages (both notices and errors). Since it's a Hash, you can assign any key/value pair that you want, but I tend to stick with flash[:notice] for a success message, and flash[:error] for an error message.

In my opinion, using the flash hash is a little confusing. I haven't come across a book or tutorial that fully explains how to control it properly. So, here are the options for using the flash hash in Rails.

flash[:key] and flash.now[:key]

The following method shows how to best use the flash hash:

def create
  @user = User.new(params[:user])
  respond_to do |format|
    if @user.save
      flash[:notice] = 'User was successfully created.'
      format.html { redirect_to admin_users_path }
    else
      flash.now[:error] = 'The user could not be created'
      format.html { render :action => 'new' }
    end
  end
rescue Exception => ex
  logger.warn('ERROR: ' + ex.message)
  flash.now[:error] = 'There was an error creating the user.'
  render :action => 'new'
end

Notice that I use the flash hash in two different ways: flash[:key] and flash.now[:key]. The way I use it depends on when I want it displayed. The flash[:key] usage should only be used before redirection, because it makes the object available for the current action and the next action. The flash.now[:key] usage should be used when you only want the flash object to be available to the current action.

Here's an example why you shouldn't use flash[:key] without redirection. Let's say this is your controller:

class MainController < ApplicationController
  def index
    flash[:notice] = 'Welcome to the site!'
  end
  
  def profile
  end
end

When you visit the index page, you'll see the message 'Welcome to the site!.' If you then click a link from the index page that takes you to the profile page, you'll still see the message 'Welcome to the site!' because the flash[:key] is available to the current action and the next action.

Displaying the flash

Here is a really helpful method to display the contents of the flash hash that I modified from one of Ryan Bates' awesome Railscasts:

<%- flash.each do |key, msg| -%>
	<div id="<%= key %>">
		<p style="float:right;"><%= link_to_function 'X', "Effect.Fade('#{key}')" %></p>
		<p><%= msg %></p>
		<div class="clear"></div>
	</div>
<%- end -%>

This method will loop through each key in your flash hash and create a div with the name of the key, then put the contents inside with a link to close the message div.

I put this method in a partial called _notice_div.html.erb and include it at the top of my application layout. Here are the styles I use for notices and errors:

#notice { background-color: #A4E7A0; border: 1px solid #26722D; }
#error { background-color: #F0A8A8; border: 1px solid #900; }
#notice, #error { width: 90%; margin: 0 auto 10px auto; padding: 5px; }
#notice p, #error p { margin-left: 20px; padding: 0; font-size: .75em; color: #000; }
#notice a, #error a { text-decoration: none; padding: 0 3px; }
#notice a { border: 1px solid #26722D; color: #26722D; }
#error a { border: 1px solid #900; color: #900; }
#notice a:hover, #error a:hover { color: #333; border: 1px solid #333; }

This is a notice div.

This is an error div.

Tagged: tutorialcssrailsflash

Code Golf: Saving Time

Aug 28, 2008  -  Comments

Here is my submission for the Saving Time challenge. Code size: 319 bytes (not the worst, but close).

h,m=gets.split(':').map{|i|i.to_i}
h>11?h-=12:''
m=(m-m%5)/5
a=[]
11.times{|x|a<<[' ']*17}
b={}
c=[[0,8],[1,12],[3,15],[5,16],[7,15],[9,12],[10,8],[9,4],[7,1],[5,0],[3,1],[1,4]]
0.upto(11){|x|b[x]=c[x]}
b.map{|x,n|a[n[0]][n[1]]='o'}
a[b[h][0]][b[h][1]]='h'
a[b[m][0]][b[m][1]]=h==m ?'x':'m'
a.map{|x|puts x.join.rstrip}

Tagged: rubycode golf

Code Golf: Seven-Segment Displays

Sep 08, 2008  -  Comments

Here is my submission for the Seven-Segment Displays challenge. Code size: 292 bytes.

x=gets.chop.split ''
a=' ### '
b='#    '
c='    #'
d='#   #'
e=' '*5
f='  '
g=[a]
h=[d]*3
i=[e]
j=[c]*3
k=[b]*3
l=g+h
m=g+j
n=m+g
y={0=>l+i+h+g,1=>i+j+i+j+i,2=>n+k+g,3=>m+n,4=>i+h+m+i,5=>g+k+n,6=>g+k+l+g,7=>m+i+j+i,8=>l+l+g,9=>l+n}
9.times{|i|puts x.collect{|n|y[n.to_i][i]+f}.join.chop.chop}

Tagged: code golfruby

RESTful Routes Demystified

Sep 14, 2008  -  Comments

RESTful application design is a rails-standard way to structure your CRUD actions. It simplifies your controllers into 7 actions: index, show, new, create, edit, update, and destroy. Here are some basics for working with RESTful routes.

The simple way to get the default routes:

ActionController::Routing::Routes.draw do |map|
  map.resources :products
end

Route Options

Several options can be passed to the route to customize it. You can use the path_prefix option to customize the appearance of your URLs. The name_prefix option is used to change the way the routes are called. The controller option is used to specify a custom controller.

# start all of your URLs with /admin
# '/admin/projects/id/edit/index.html'
map.resources :products, :path_prefix => '/admin'

# start all of your routes with 'mng_'
# mng_products_path or mng_product_path(:id)
map.resources :products, :name_prefix => 'mng_'

# if you want your URLs to say '/products/id/index.html'
# but your controller is called 'store_products'
map.resources :products, :controller => 'store_products'

Adding Routes for Custom Actions

The resources method will generate the routes for the default REST actions, but what if you want to add your own actions to your controller? There are two options for adding custom routes: the member option is for routes that require an id to be passed, and the collection option is for actions that don't require an id. With each option, you must pass a hash with the action name and the HTTP method.

# return_policy_products_path => '/products/return_policy'
# submit_question_products_path => '/products/submit_question'
map.resources :products, :collection => {:return_policy => :get, :submit_question => :post}

# warranty_product_path(:id) => '/products/id/warranty/index.html'
map.resources :products, :member => {:warranty => :get}

Nested Routes

You can nest routes for objects that are related. Say the products have customer reviews with a has_many relationship. You can nest the resources call within the products route definition.

# product_reviews_path(:product_id) => '/products/product_id/reviews/index.html'
# product_review_path(:product_id, :id) => '/products/product_id/reviews/id/index.html'
# edit_product_review_path(:product_id, :id) => '/products/product_id/reviews/id/edit/index.html'
map.resources :products do |products|
  products.resources :reviews, :controller => 'customer_reviews'
end

Those are the basics, but there are a LOT more possibilities. If you're interested, there is a really great guide to all things routes.

Tagged: tutorialroutesrails

Site Redesign

Nov 15, 2008  -  Comments

My site has received a much-needed facelift. The original "design" was something I just slapped together when I was first building the site. It was really an afterthought because I was only concerned with the functionality of the site, and not so much with how it looked.

Of course, this design is not something that I'm capable of. Luckily Andrew, one of the designers at Plexus, needed someone to code his personal site. So we worked out a deal to trade code for design. I think he did a great job. The only drawback was that he wanted me to put a gaudy link to his site in my footer. Sorry.

Tagged: plexusredesign

Stop! Haml Time!

Nov 23, 2008  -  Comments

Ok, first of all I have to apologize for the title of this post, but I couldn't resist the pun.

Anyway, as the title suggests, I've recently converted all of my erb pages on this site to haml. Haml is a DSL templating language uses to generate well-formed XHTML. The documentation site claims that you can become familiar with the syntax in about 20 minutes. I think, as long as you already know XHTML, you can pick it up in about 10 minutes. The concept is pretty simple. Each tag should be on its own line, and everything contained in that tag should be indented below it. If a tag doesn't have any other tags contained in it, then the content can be on the same line as the tag. Also, div is the default tag, so you can just pass an id or class name to output a div.

%p This is a paragraph tag.
%ul
  %li First list item
  %li Second list item
#id_name Content in div
.class_name Content in div

Will convert to (with beautiful formatting):

<p>This is a paragraph tag.</p>
<ul>
  <li>First list item</li>
  <li>Second list item</li>
</ul>
<div id="id_name">
  Content in div
</div>
<div class="class_name">
  Content in div
</div>

It's really easy to include rails evaluation and output blocks too.

- @posts.each do |post|
  %p
    Written by
    = post.author
  %p= post.date

Notice that there is no need for end when a block is done. When haml sees that the indentation has ended, it automatically ends the block.

You can also pass any attributes to an HTML tag via a ruby hash.

%img{:src => "/images/picture.png", :alt => "Picture", :title => "Picture"}

I think the coolest thing about Haml is how it can assign a class and unique id to an element simply by passing an ActiveRecord object within square brackets.

%div[@post]

Will output:

<div class="post" id="post_18"><div>

If you'd like to learn more, you can take a look at the online documentation, or you can look at the code for my site on Github.

Tagged: tutorialhamlxhtmlruby

Helpful Helpers

Nov 30, 2008  -  Comments

Here is a list of helper methods that we use a lot at Plexus to make our jobs easier. A few have been referenced in previous posts, but I thought I'd list them all here in one place.

Strip text for pretty URLs

You can use this method to replace all non-alphanumeric characters to dashes in a title or name when you're including them in the URL.

This is the route I use for my posts on this blog:

m.post_details ':year/:month/:day/:title', :action => "by_date",
  :requirements => { :year => /(19|20)\d\d/, :month => /[01]?\d/, :day => /[0-3]?\d/},
  :day => nil, :month => nil, :title => nil

And here is the helper to strip out characters in the title when creating the URL:

# Replace all non-alphanumeric characters with dashes
def strip_chars(string='')
  string.gsub(/\s+/,'-').gsub(/[^a-z0-9\-]+/i, '')
end

You can call the helper when you generate the route.

post_details_path(:year => @post.date.year, :month => @post.date.month, :day => @post.date.day, :title => strip_chars(@post.title))

Generate a random password of n length

I've actually got a whole other post for just this helper, but decided to include it in this list.

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

It will generate a 6 digit password by default, but you can specify the desired length.

generate_password
=> "Q6Kfze"

generate_password(10)
=> "ZSJcmtRH5q"

Built-in rails helpers

These following helpers are built into rails, but you may not know about them.

Array#to_sentence

["this", "that", "the other"].to_sentence
=> "this, that, and the other"

number helpers

number_to_currency(123456789)
=> "$123,456,789.00"

number_to_human_size(123456789)
=> "117.7 MB"

number_to_phone(1234567890, :area_code => true)
=> "(123) 456-7890"

There are a ton of string inflector helpers

"under_scored".dasherize
=> "under-scored"

"names_and_titles".humanize
=> "Names and titles"

"lower case title".titleize
=> "Lower Case Title"

Tagged: rubyrailshelpers

Emulating RJS with Merb/JQuery/Haml

Dec 21, 2008  -  Comments

Ok, Merb is great. Rails is equally as great. RJS is great. JQuery and Haml are just outstanding. But I found that Merb not doing RJS-like behavior a little daunting in the current application that I'm working on. Of course, Merb does javascript, and you can send Ajax requests, but it's not quite as easy to accomplish RJS-type interactions with the current page. I did quite a bit of googling, and all I ever came up with was a very interesting presentation from Yehuda Katz about using JQuery with Merb. It didn't completely answer my question about getting RJS functionality in a Merb app. So, I set about trying to actually figure something out on my own!

Let's say I have an action called mark_as_complete that I can call for several items on a page, have it make a database call, then update the item without having to leave the page. The first step is to make the form for each item submit via AJAX instead of a regular HTTP POST request. Thanks to Ryan Bates' RailsCast on JQuery for help on that. All I have to do is give the form a class of remote, then this function will cause it to be submitted via AJAX (as well as any form on the site with the same class name):

// function to send the jQuery form object via AJAX
jQuery.fn.submitWithAjax = function() {
  this.submit(function() {
    // be sure to add the '/2008/.js' part so that it knows this is format:js
    $.post(this.action + '/2008/.js', $(this).serialize(), null, "script");
    return false;
  })
  return this;
};

$(document).ready(function() {
  // once the page has completely loaded,
  // make forms with the class "remote" submit via AJAX
  $("form.remote").submitWithAjax();
});

Now that's done, I need to figure out how to get the RJS stuff to fire correctly. I've already set the format of the request as .js, so the controller knows it's an AJAX request. With Merb, you have to add the provides :js line to your action so that it knows to accept js requests.

def mark_as_complete(id)
  provides :js
  # do work, son
  # set instance variable to indicate success/failure
  if stuff_done
    @complete = true
  end
  render
end

Now for the funky part. Getting my Haml template to update the page. Well, if you just name a view mark_as_complete.js.haml, then the application will use it. The hard part was figuring out what to do in the file. I could call javascript in the file and get that to work (alert(), for example), but the following bit of code did NOT work:

- if @complete
  $("#div_name_#{@record.id}").html('complete');
  $("#notes_#{@record.id}").replaceWith('

#{@record.notes}

'); - else alert("An error occurred processing your request.");

Nothing happened and I couldn't figure out why. The javascript was being run, but the ruby code inside it wasn't being evaluated. Turns out it's because I'm using Haml. I suspect that if I were using erb, then I could surround my ruby code with output blocks(<%= %>) and it would work(though I haven't tested it).

After experimenting with all sorts of variations on the above code, I finally decided to try and put the javascript code into Haml ruby output blocks(so the ruby code would be evaluated). Low and behold, the following actually worked, despite being ugly and less readable.

- if @complete
  = "$('#div_name_#{@record.id}').html('complete');"
  = "$('#notes_#{@record.id}').replaceWith('

#{@record.notes}

');" - else alert("An error occurred processing your request.");

Notice that the alert() call isn't in an output block because it doesn't have any ruby code that needs to be evaluated.

This solution worked for me, but I'm sure there is a better way to accomplish this. If anyone has a better approach, please leave it in the comments.

Tagged: rubyrjsmerbjqueryhamltutorial