Jul 23

The lastest version of VoteFu has a few useful enhancements:

  1. Protect against mass assignment forgery. The params hash will only be consulted for :vote => true or false. The rest has to be assigned in the controller.
  2. The acts_as_voteable mixin now has support for tallying votes.

The documentation will be updated tonight, but briefly, here is what you can do with the new tally() method:

1
2
3
4
5
6
7
8
@items = Item.tally(
  {  :at_least => 1, 
      :at_most => 10000,  
      :start_at => 2.weeks.ago,
      :end_at => 1.day.ago,
      :limit => 10,
      :order => "items.name desc"
  })

This will select the Items with between 1 and 10,000 votes, the votes having been cast within the last two weeks (not including today), then display the 10 last items in an alphabetical list.

More to come. Enjoy!

Jul 21

Quotes. I love quoting people. I have a ton of quotes saved in text files, on my blog, in my various mood messages on IM platforms, and who-know-where-else.

I decided to build an application to manage, organize, and syndicate quotes. You can read more about it on my project page for MyQuotable.

If you read this blog, you are invited to participate in my open alpha of MyQuotable.com.

Early Alpha image of myquotable.com

Early Alpha image of myquotable.com

Jun 08

The new Rails routing has nice support for nested reources. And, I think it handles just enough nesting. Any more support, and it’s possible to go overboard and write ugly code.

For example, here is what Rails now supports for nested routing syntax:

1
2
3
4
5
  # Simple parent child association
  map.resources :user, :has_many => :posts
 
  # A parent with many types of children
  map.resources :posts, :has_many => [:comments, :trackbacks, :pingbacks ]

Nice. That is prefectly terse and descriptive, without being too clever.

There has been some debate and consternation over why a complicated multi-nested resource can’t be set up this way. For example, if I am building a project management tool, why can’t I do this?

1
2
map.resources :projects, 
  :has_many => [ :releases,  :milestones => [:tasks, {:features => :tasks}] } ]

That is, a project has many releases AND milestones, and in turn milestones have many tasks and features. And, features can also have tasks.

That’s complicated, and too much cleveness to jam into one statement. I think Rails 2.0.2 / 2.1 has it right in making you write that routing rule like this:

1
2
3
4
5
6
7
8
9
  map.resources :projects do |project|
    project.resources :releases
    project.resources :milestones do |milestone| 
      milestone.resources :tasks
      milestone.resources :features do |feature|
        feature.resources :tasks
      end
    end
  end

I hear a crowd of people clamoring for the uber-terse syntax outlined in the second listing. I think that’s a bad idea. It encourages hard-to-follow, obfuscated code.

When you have to do something complicated, it’s worth taking a few extra lines to make it clear to the next programmer.

Jun 06

Sorry for the outage on this blog yesterday. My hosting provider upgraded to Rails 2.1, and I had cleverly forgotten to:

bash# rake freeze:rails:gems

If this happens to you, and you make the unfortunate mistake of trying to instead update Typo to Rails 2.1 using:

bash# rake rails:update

You’ll be in even worse trouble, unless you’re prepared to do a lot of fixing:

bash# Pete$ script/server
./script/../config/boot.rb:45:in `require': no such file to load -- ./script/../config/../vendor/rails/railties/lib/initializer (LoadError)
	from ./script/../config/boot.rb:45:in `load_initializer'
	from ./script/../config/boot.rb:38:in `run'
	from ./script/../config/boot.rb:11:in `boot!'
	from ./script/../config/boot.rb:109
	from script/server:2:in `require'
	from script/server:2

Your best bet? Revert from source control and freeze Typo in your dev environment. If you’re stuck without source control or a dev environment, let me know and I’ll talk walk you through the alternate fix.

May 26

In my post about clever code vs. terse code, I showed some distaste for code that attempts to put a bunch of logical statements on one line. I have a particular coding prejudice that lines of code should be short from left-to-right, if at all possible.

The reason? I like sidebar comments.

Maybe this is my showing my age. Back in the day, we didn’t have widescreen MacBook Pro laptops that could display 600 characters across the screen. (And we liked it! While walking uphill both ways in the snow to school…) Between 17″ CRT monitors and the IDE, I was lucky to get 100 characters across.

So instead of writing long lines of code, I prefer to use a couple extra lines and simplify each discrete statement. Then I will sometimes put comments (aligned with each other) out in the right margin that map to my pseudo-code (which is usually just in my head….I don’t actually write much pseudo-code in Ruby).

For example:

1
2
3
4
5
6
7
8
# Spawn a set of threads to process the queue
1.upto(threadcount) do |thread_id|
  threads << Thread.new(thread_id) do |i| # Each thread
    until @queue.empty?() do                    # grabs an item from the queue
      yield(thread_id, @queue.deq())            # and yields it to the block
    end
  end
end

Some people call this “code smell.” The meaning, I guess, is that if I have to write comments that outline what the code does, the code must be too complicated.

I beg to differ.

Imagine for a moment that you are a fresh-out-of-college programmer, and you open up my codebase to maintain it. You find this:

1
2
# Spawn a set of threads and process the queue all on one line
1.upto(threadcount) { |thread_id| threads << Thread.new(thread_id) { |i| yield(thread_id, @queue.deq()) until @queue.empty?  } }

You might run away screaming after a few dozen lines like that. I sure would. Smaller lines with comments make it easier to follow. And I think sticking them out on the right margin where they don’t interrupt the flow of code makes it easier to ignore them if you’re an experienced programmer who doesn’t need them.

May 26

In 21 Ruby Tricks You Should Be Using In Your Own Code, Peter Cooper outlines some really useful best practices that programmers could benefit from. However, I think that there’s a tendency to over-obfuscate code from time to time in the Ruby world.

I like terse code. I like beautiful code. But I dislike tricky code. For example, let’s look at two tricks Peter Cooper outlines in his post:

Trick #7: Cut down on local variable definitions.

1
2
3
4
5
6
7
 
# Cooper says do this: 
(z ||= []) << 'test'
 
# Instead of this: 
z ||= []
z << "test"

Counting whitespace characters, Cooper’s version of the code is 20 characters long. The second version of the code is 20 characters long. Personally I find the second version easier to read.

Trick #9: 9 - Use ‘and’ and ‘or’ to group operations for single liners.

1
2
3
4
5
6
7
8
9
10
11
# Cooper likes this:
queue = []
%w{hello x world}.each do |word|
  queue << word and puts "Added to queue" unless word.length <  2
end
puts queue.inspect
 
# Output:
#   Added to queue
#   Added to queue
#   [”hello”, “world”]

Hm. While I think this does terse up the code by grouping statements that do a single logical operation onto one line, I think it’s still easier to read this way:

1
2
3
4
5
6
7
8
9
# I like this:
queue = []
%w{hello x world}.each do |word|
  unless word.length < 2 do
    queue << word
    puts "Added to queue" 
  end
end
puts queue.inspect

I think this method makes it easier to modify the discrete elements of the queue operations. For example, I may want to comment out that call to “puts” someday, which would be tougher if I’d used the “and” operator to string it all together on one line. I might also want to add a debug log statement. Again, it gets tough when you’re trying to fit it all onto one line.

My opinion is that finding tricks in the language that allow you to string a bunch of steps onto one line aren’t always the best way to make good code. Sometimes, finding a way to make a set of statements look like a logical unit is a better choice.

May 08

I often have to iterate over a collection and perform some remote, or long running task on each member of the collection.

Threaded Collections is a package for iterating through collections over multiple threads. With large collections, sometimes it can be more efficient to process a collection in parallel, provided that the collected items don’t have a interdependencies, or need to be processed in a specific order.

Usage:

1
2
3
4
5
6
7
8
9
require "threaded_collections"
 
threadcount = 2
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
tps = ThreadedCollectionProcessor.new(arr)
tps.process(2) do |thread_id, item| 
  puts "Thread #{thread_id} processed item: #{item}" 
  sleep 1
end

I abstracted this pattern from a web services client that posted items from a collection, but
each request took a second to process. The remote service had plenty of threads available, so
I parallelized the task with this pattern.

I have no plans to break the interface but I do plan to make two major enhancements:

  1. Make it possible to mix this functionality in to the Ruby iterators, so you don’t have create the ThreadedCollectionProcessor.
  2. Make it work with fibers and processes in addition to threads.

If you want to check it out, you can get the source from the threadedcollections github site.

To install the gem without git:

1
bash# sudo gem install peteonrails-threaded-collections --source=http://gems.github.com
May 06

In my last post, I described an XML over HTTP service written in Java that I have to integrate with. I expressed a minor and general annoyance at the fact that the developers of this service specify that a “DateTime” parameter be specified in “milliseconds since the epoch”.

There is another typical problem with Java services that isn’t always as evident.

When Congress decides to change the Daylight Savings Time switch dates, the JVM typically needs to be patched separately from the OS it is running on. And this never happens.

So, if you are passing a message to a Java service gateway with a parameter like “delivery time” specified in “milliseconds since epoch”, and you think it’s Daylight Savings Time, but the Java service thinks it’s “Standard Time”, then your message will be delivered an hour late.

I usually deal with that case ad-hoc by specifying a variable in a YAML file, like this:

1
tz-fix: true

And then in my code like this:

1
2
3
4
  # Read in my config
  @@c = YAML.load_file(File.join(File.dirname(__FILE__), "myapp.yml"))   
# ...
  millis = millis - (60*60*1000) if @@c["tz-fix"]

If the remote service talks in “seconds since epoch”, I drop the “* 1000″.

Good luck.

May 06

Working in telecom, I have to integrate my Rails and plain Ruby apps with Java or Unix based systems running on remote hosts. Most often these systems are running remotely and are accessed via an XML-over-HTTP interface (no SOAP, no REST, blah…).

I’ve found that one of the most infuriating things that UNIX and Java “roll your own web service” writers do is specify “time” fields as “seconds since the epoch”. WORSE: Many Java service writers specify time fields as “milliseconds since the epoch”.

Come on, now, people? It’s a web service! Do you really think I care about accuracy in milliseconds?

I won’t go into a rant about this. Suffice it to say: I Find This BS To Be Lazy. It works that way so that the server software doesn’t have to do any complicated date parsing or conversions.

Fortunately, Ruby makes it easy to deal with if you know the right methods to use. Here’s how to convert to a UNIX or Java internal-time:

1
2
3
4
5
rubytime = Time.new  # => Tue May 06 11:11:05 -0400 2008
 
# .. Convert from Ruby time to Unix time. 
unixtime = rubytime.to_i            # 1210086665
javatime = rubytime.to_i * 1000  # 1210086665000

What about converting the other way? The example above are converting the “less precise” Ruby time (no milliseconds) into equally or more precise time formats. What do you do when you have a “milliseceonds since epoch” time and you want to use it in Ruby, but preserve the sub-second precision?

1
2
3
4
5
6
7
8
9
# Add just over a half second to the time used above
millis   = 1210086665555  
 
# adding .0 preserves subsecond accuracy
precise = Time.at(millis / 1000.0) 
 
precise.to_i            #  1210086665
precise.to_f            #  1210086665.555
precise.to_f * 1000  # 1210086665555.0

Now. Go convince all those legacy Java and Unix service writers to stop specifying “Epoch Time” in their interfaces! It’s Just Plain Lazy!

Apr 30

AttachmentFu is a great plugin. It’s heavily used all over the place to upload images to a Rails app. It’s also good with other file types.

I had a requirement to provide users with the ability to set up an entity (call it a Batch), then upload a number of CSV files to that batch. I used AttachmentFu, FasterCSV, and some Multi-Model editing forms to make the trickery work.

Before starting, I set up the AttachmentFu plugin. If you have never done this before, Mike Clark’s Tutorial is a good place to start. Install the plugin and take note of how you have to set up your Attachment model.

Then, I had to set up a Multi-model editing form. If you haven’t done this before, then you should read Ryan Bates’ tutorial on setting up multiple models in one view. In this situation, I had to modify some of the steps because we’re dealing with File Attachments, not Task objects. Here is what I did:

First I created my “Batch” object.

1
script/generate migration Batch user_id:integer name:string

Then I created my “Attachment” object.

1
script/generate migration Attachment

I use Oracle. In order to make AttachmentFu work, I renamed “size” to “filesize”

1
2
3
4
5
6
7
... In 002_create_attachment.rb
def self.up
  create_table :attachments do |t|
  t.integer    :parent_id # foreign key to :batches
  t.string     :content_type, :filename, :thumbnail
  t.integer    :filesize, :width, :height
end

Then, in my Batch model, I added the Multi-Model handling code. My method differs from the Rails Recipe because you cannot update an attachment once you upload it, only delete it. In the Update action, for each attachment on the model, we check to see where there is an attribute containing the ID of the attachment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# If there is not an ID in an attribute, we delete the attachment.
# ... In batch.rb
has_many   :attachments, :foreign_key =&gt; "parent_id", :dependent =&gt; :destroy
validates_associated    :attachments
 
def new_attachment_attributes=(attrs)
  attrs.each { |attr| attachments.build(attr) }
end
 
def existing_attachment_attributes=(attrs)
  attachments.reject(&amp;:new_record?).each do |attach|
    attachments.delete(attach) unless attrs[attach.id.to_s]
  end
end
 
def save_attachments
  attachments.each { |attach| attach.save(false) }
end

Then I set up the Attachment model to handle the AttachmentFu-ery.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Attachment < ActiveRecord::Base
  belongs_to     :batch
  has_attachment :storage =&gt; :file_system     # Or S3, or DB, or whatever
  validates_as_attachment
 
  ## Patch to make this AttachmentFu Model object work with Oracle.
  def size
    self.filesize
  end
 
  def size=(bytes)
    self.filesize = bytes
  end
end

Now I needed to build the view and controller support. To keep the app mostly RESTful, we let the standard “Attachment” controller be built by the scaffolding system. Since we will be primarily working with Attachments in the “Batch” view, though, I’ve omitted those details.

Here is the additional controller code in batch_controller.rb:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# GET /batches/new
def new
  @batch = Batch.new
  @batch.attachments.build
end
 
def update
  params[:batch][:existing_attachment_attributes] ||= {}
 
  @batch = Batch.find(params[:id])
 
  respond_to do |format|
    if @batch.update_attributes(params[:batch])
       flash[:notice] = 'Your Batch was updated successfully.'
       format.html { redirect_to batch_url(@batch) }
       format.xml  { head :ok }
    else
       format.html { render :action =&gt; "edit" }
       format.xml  { render :xml =&gt; @batch.errors.to_xml }
    end
  end
end

What’s left? Setting up the views. We leave the scaffolded “index” action for the Batch view in place. Attachments aren’t relevant in that view. But in the “Edit” and “New” views, we need to create a custom form that can handle attaching files in addition to setting up the Batch model object.

Step 1, make the Edit and New actions point to a shared form:

1
2
3
4
<!-- Contents of views/batches/new.html.erb
and views/batches/edit.html.erb
-->
<div class="greybox"><%= render :partial => 'form' %></div>

Then, we set up the shared form in a partial like so:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<h1>Schedule A Batch</h1>
<!-- views/batches/_form.html.erb: error display code omitted -->
  <% form_for(@batch, :html => { :multipart => true }) do f %>
  <strong>Name:</strong> <%= f.text_field :name %>
  <div id="attachments"><%= render :partial => "attachment", :collection =>  
  @batch.attachments%></div>
  <%= add_attachment_link "Add a File" %>
  Total Line Count: <%= @batch.prod_line_count %>
 
  <input name="batch[user_id]" type="hidden" value="<%= @user.id %>" />
 
  <%= submit_tag "Save Changes" %&gt or &lt%= link_to 'Cancel', batches_path %>
 
  <% end %>

The code above renders the primary Model object, and then renders the associated attachments using the “_attachment” partial. Let’s take a look at that code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div id="attachments" class="attachment"><% new_or_existing = attachment.new_record? ? 'new' : 'existing' %>
  <% prefix = "batch[#{new_or_existing}_attachment_attributes][]" %>
  <% fields_for prefix, attachment do af -%>
 
  <strong>Attached File:</strong>
  <% if attachment.new_record? %>
 
 
  <%= af.file_field :uploaded_data %>
  <% else %>
  <%= af.hidden_field :id %>
  <%= attachment.filename %>
  <%= link_to_function "remove", "$(this).up('.attachment').remove()" unless params[:action] == "show"%>
  <% end %>
 
  <% end -%>
</div>

This sets the front end up to show the attached files, and provide a link to delete each on on the front end using javascript (unless we are being rendered in the “show” action. We’ll refactor that piece of bad juju later).

The last piece of work to do is to set up the “show” action to display the child records. This isn’t hard. There is no need to modify the default scaffolded view. Just add the partial to show the attachments:

1
2
<-- Add to views/batches/show.html.erb -->
<div id="attachments"><%= render :partial => "attachment", :collection => @batch.attachments%></div>

That’s it. You still have an application that responds RESTfully to Batch and Attachment requests, but when you are a person in front of a browser, you can attach multiple files to your Batch object.