Tuesday, January 27, 2009

Rails: Database-less ActiveRecord models


It's not unusual in Rails projects to have one or two model classes that don't inherit from ActiveRecord and don't require an associated table in the database. But what if we want half of that? What if we want a model that does descend from ActiveRecord but doesn't exist in the database? I finally found some code for doing exactly that. Here's an example:


class Feedback < ActiveRecord::Base
  validates_presence_of :mailfrom, :comment

  def self.columns
    @columns ||= []
  end

  def self.column(name, sql_type = nil, default = nil, null = true)
    columns << ActiveRecord::ConnectionAdapters::Column.new(name.to_s, default, sql_type.to_s, null)
  end

  column :id
  column :mailfrom
  column :comment
  column :ipaddr
end
I derived this from the code at Caboose's blog. He says he got it from Techoweenie but I can't find it on Technoweenie's site anymore.

So anyway, why would you want this? In Rails, the ActiveRecord class is super powerful. It is of course an ORM first and foremost, but it has other great features. Also, other parts of Rails, ActionView in particular, function at their best if you can provide them with an object descended from ActiveRecord. If you don't have an ActiveRecord object, you have to use form_tag() instead of form_for(), text_field_tag() instead of text_field(), etc. You don't get to use error_messages_for() and you don't get the nifty pre-fills of the model's existing values when you error flash back to the same form.

In my case, I was creating a very simple feedback form so a visitor could provide their email address and leave a comment. The comment would be mailed to the site admins via ActionMailer. I actually had a seperate model, which was descended from ActiveRecord, that made a database record of the time, date, and IP address, but there was no requirement to store the comment itself in the database, so I thought that the Feedback object didn't need to inherit from ActiveRecord. Mistake! Cutting myself off from the best helpers that ActionView offers, something that should have been a dead-simple one-page form became a tedious slog[1] to program. I finally came to my senses and googled around until I found the above code.

I've used ActiveRecord-less models before, so at first I was surprised by my unpleasant experience. Then I thought about it and realized that none of my previous ActiveRecord-less models involved user interaction. They were all "plumbing" and I never needed, or missed, the ActionView helpers. If you're making a view for a model, and that model doesn't inherit from ActiveRecord, you're not doing it The Rails Way.

 [1] "Tedious slog" being relative. I find that Rails raises the bar for ease of (web) programming, to the point where it's actually a shock to deal with the same level of drudgery that PHP inflicts on me on a good day.

Friday, January 23, 2009

EventMachine: a TCP server module for Ruby


I just discovered EventMachine. EM is, at its least, an event-driven library around which you can build a custom TCP server. The nitty-gritty of listening, sending and receiving, and multiplexing connections is all done for you.

That's selling it short, though, because EventMachine can do a lot more. In its own words, EventMachine "provides event-driven I/O using the Reactor pattern." It can be used for other client/server models like serial ports or even interactive keyboard I/O. But it really stands out for abstracting away the low-level hassles of writing a TCP daemon.

Here's a simple Echo service built using EventMachine. (Borrowed from the README file)


require 'rubygems'
require 'eventmachine'

module EchoServer
  def receive_data data
    send_data ">>>you sent: #{data}"
    close_connection if data =~ /quit/i
  end
end

EventMachine::run {
  EventMachine::start_server "192.168.0.100", 8081, EchoServer
}
Here's an example I made. You can pass a class to EventMachine::start_server, and each new connection will create a new instance of your class. That allows you to use instance variables to record distinct state for each connection. This example buffers up the client input until the client sends a ".<CRLF>" a la SMTP, or a maximum of 10 lines.


require 'rubygems'
require 'eventmachine'

class DataBuffer < EM::Protocols::LineAndTextProtocol
  def initialize
    puts "init'ing new instance of #{self.class.to_s}"
    @line_ctr = 0
    @databuf = []
  end

  def receive_data(data)
    @databuf << data
    @line_ctr += 1
    if data == ".\r\n" || @line_ctr == 10
      if data == ".\r\n"
        @databuf.pop
      end
      send_data(@databuf.to_s)
      reset_databuf()
    end
  end

  private
  def reset_databuf
    @line_ctr = 0
    @databuf = []
  end
end

EventMachine::run {
  EventMachine::start_server "127.0.0.1", 8081, DataBuffer
}
And the best part is, I've only been playing with EventMachine for about an hour! I've only begun to understand what it can do.

So, yeah. EventMachine is badass. You should check it out.

Tuesday, January 13, 2009

The Palm Pre SDK, or, In Defense of Javascript


So the Palm Pre is generating a lot of (mostly) positive buzz.[1] There are still a lot of unknowns around it, details of the SDK are still vague, and it may yet all turn out to be sound and fury, especially since no one is allowed to touch it yet.

Most of the negativity so far has targeted the choice of Javascript as the programming language. Personally I've never had a problem with Javascript the language. I think Javascript gets a bum rap. It's a dynamically interpreted, loosely-typed, object-oriented language. Functions are first-class objects, and it has an eval() operator. Sounds a lot like... Ruby. Or Python. Or Perl. What more do you want? Closures? I suspect the Javascript hate comes out because most programmers only work with Javascript in the context of emitting Javascript code from their C# or PHP on the server side, and/or dealing with the inevitable cross-browser inconsistencies of the various Javascript runtimes. Those things do suck, but that's not the fault of Javascript the language. When I heard about an SDK with an Eclipse-based IDE that uses Javascript for programming and HTML5 for UI, my first thought was "Oh, okay, just like Flex Builder, Actionscript, and MXML."

Okay, back to the Pre: the party line is "it's just like building a web app", but we also know the Pre has features that have no analog in web app development. I'm curious to know how they handle things like the camera, or playing sounds, or playing videos. I'd guess the SDK comes with a library of Javascript APIs for interfacing with such things, but again, we don't really know yet.

 [1] I don't like that name though. "Pre", by itself, implies that something newer and better is already imminent if you wait for it. A Palm exec said they wanted to communicate the idea of "the beginning of something new." It took Thomas 5 seconds to think of "okay, how about 'Premiere'?"

Friday, January 09, 2009

iPhone: Development provisioning profiles and the Entitlements file


I found what appears to be a disconnect between Apple's provisioning documentation and what actually goes on in Xcode. If you want to build your project for development (testing) on your own device, the documentation says to select the top-level build target of your application, open the Info window, click the Build tab, and set "Code Signing Identity" -> "Any iPhone OS" to be "iPhone Developer: YourFirstName YourLastName". (Presumably you must enter your name exactly as it appears on the Team page of your developer portal.) That part works fine. Next, according to the documentation, you should set "Code Signing Provisioning Profile" to be the provisioning profile you created for your combination of name/device/application. When I go to my XCode, there is no such entry!

Instead, just above "Code Signing Identity" is an entry called "Code Signing Entitlements". What I had to do is create a new property list file in my project called Entitlements.plist. The contents of that file look like this:



Where the application-identifier is the exact App ID from your developer portal, including the 10-character prefix. And then back in the Info window, set the value of "Code Signing Entitlements" to simply be "Entitlements.plist". Drag and drop the provisioning profile onto the XCode Organizer, if you haven't already. Now you can build and push the app to your iPhone.

Monday, January 05, 2009

Two Desktop icons in Open File sidebar


I recently had a problem similar to this one:

Fix multiple ghost aliases in the Finder's sidebar

I had two Desktop icons in the sidebar of my Open File dialog boxes, in all of my applications. I had only one Desktop icon in the sidebar of my Finder, though. The advice on that page is good advice, but you don't have to trash the sidebarlists.plist file. Instead you can edit it with the Property List Editor, and under "useritems" you'll find the duplicate entries that are giving you grief. Delete one of them, save it, and then - this is key - logout and log back in.