Archive for the 'Rails' Category

RailsConf 2007: Keynote

Friday, May 18th, 2007

I just left the keynote. I also found out today that Con-way has some sort of web blog bot thing sniffs out any mention of “Con-way.” So, “Hello, HR!” Con-way. Con-way. Con-way. Paul J. Christopher has been doing a bang-up job and deserves a large raise.

There are 1,600 people at RailsConf — there were like 60 at RailsConf 2005. Show of hands: 80%+ of audience is getting paid to write Rails code.

Our fearless leader, David Heinemeier Hansson talked mostly about Rails 2.0, after a few digs at Java, a couple F-bombs, and a few boasts about Rails book sales.

The Rails release cycle is lengthening. Lots of people are using it, and everything doesn’t need to change all the time any more.

Important information from DHH: Rails 2.0 is not a unicorn! In other words, focuses on REST and other evolutionary improvements. All the features are in Edge (that’s a fancy term for HEAD/trunk) and should work now.

FormBuilder mentioned again.

DHH doesn’t like config files because he doesn’t like being bothered by decisions that he doesn’t care about. You and me both.

Most of DHH’s talk was a demo of how to use REST in an example address book app. Nice to have a keynote that is essentially a developer talking to other developers about coding. DHH starts with one model via scaffolding. “Adding anything new would be a pain in the ass … not!”

There was a cool demo of using the console to work with XML object. Call save() and it makes a HTTP PUT call to update the database.

Nine other things that DHH like about Rails 2
1. Breakpoints are back
2. HTTP Performance. DHH: OK, OK, it does matter. Framework can cache JavaScript files into one bug gzip’ed bundle. Asset_host: allows browsers to open up more simultaneous connections.
3. Query cache.
4. Action.mimetype.renderer. E.g., index.rhtml -> index.html.erb. This fixes mixing of template type and output type. (I like.)
5. Config/initializers: organizes config details into files.
6. Sexy migrations: basically flips column name and column types
7. HTTP authentication: Bad for UI for humans, good for computer clients.
8. The MIT license is the default
9. Spring cleaning: removing a lot of deprecated stuff; moving some thing like in-place editors out of Rails core and into plugins

When V is for Vexing: Patterns to DRY Up Your Views by Bruce Williams

Thursday, May 17th, 2007

So, I heard from more than one person that the second half of the morning JavaScript tutorial (which I skipped) was significantly better than the first half. Sorry, Thomas. With that in mind, I resolved to grind through the whole afternoon tutorial no matter what happened. Fortunately, it was pretty good stuff for people like me whole like their UI code all polished up and shiny. I even stayed when someone started drilling through concrete on the other side of the wall.

Bruce started out talking about MVC (Model View Controller). He pointed out that, in Rails, we end up with clean Ruby code in the M and C and crappy V code.

Views are hard to: master, explain, reuse, extend, test, agree on. True enough in my experience.

Bruce’s recommended plan of attack:
1) Choose a templating system that works for you
2) Find common patterns to extract into reusable code
3) Extract, abstract, repeat

There was a review of the major Rails view options. Bruce asked for a show of hands: the great majority of people use Rails’ default ERB-based template system; a few use Haml and Markaby. I’m going to list a summary of the tutorial’s summary — the RailsConf talks are going to be available online if you are dying to get all the details. If my motivation doesn’t flame out, I’ll link to them.

ERB: Like PHP in Ruby. Heavy, ugly, hard to abstract.

Markaby
Pros: concise, easy for Ruby developers
Cons: performance, trickly with layouts and helpers

DRYML (XML):
Pros: Very reusable, complex output from concise input
Cons: Complex, lot to learn, language onto itself

Haml
Pros: Concise and fast to type
Cons: Unusual, strict whitespace, not very reusable?

Liquid:
Pros: Great for user/designer collaboration
Cons: Time to extend filters/drop

Amrita2
Pros: Clean markup, fair WYSIWG
Cons: Conceptually different, tighter data-to-layout coupling

MasterView
Pros: Great for teams that need to support WYSIWG tools
Cons: Complex, requires generation

After the review and the lukewarm endorsement of ERB, we all anticipated the climatic: “Now, let me introduce the best view solution. The one that the Rails ninjas use.”

Turns out that Rails ninjas use the default ERB templates. Oh, well.

Bruce is really focused on finding patterns — standard design elements, controls. I guess that makes sense given that the tutorial is about DRY’ing up views.

View smells:
– Calling find() on a model
– Calling find() on an association
– Conditionals
– Complex inline map, sort, or select statements
– Assigning temp variable

We spent a lot of time talking about blocks to build content and as alternatives to if/else statements, helpers, and partials.

So instead of:
<% if @user.admin? %>

Admins see thislt;/p>
<% end %>

You do this:
<% admin_content do %>

Admins see thislt;/p>
<% end %>
You implement the blocks in Helpers, using the block& parameter and yield.

Rails has moved in this direction, too: <% start_form %> … <% end_form %> tags became <% form do % ... <% end %>.

I am too lazy to give specific code examples, but I’m a believer. Not that these blocks make views dramatically better, but they can help make your views into logical component assemblies instead of bastardized HTML markup, and they’re for sure easier to test. The approach is certainly more Ruby-like. And block helpers, unlike partials, have a programmatic Ruby API.

Bruce says: “approach Rails development like a language designer.”
– When you create an app, you are creating a language
– Everything you write is an API
– Implementation is the easy part, get the API (names) right first.

This advice rings true to me. If you want to work effectively with large teams, and create code that other people can use, you should follow his advice. I’ve never grasped what the Extreme Programming folks meant by “metaphor.” I suspect they should have said: “Use good names.”

Side note: if Ruby and Rails are old news to you, apparently the cool kids are into Haskell, OCaml, and Erlang.

Bruce mentioned FormBuilder. It’s in Rails and poorly documented, but looks handy. That led into his recommendation to read other people’s source code, especially Rails’ source. It’s clear enough that the code is often the direct answer to your questions. And you’ll learn something about coding.

The talk wrapped up with some speculation that our views will all become like Seaside — a bunch of classes that generate their own markup. I don’t know, maybe Bruce’s views will end up that way. It’s true that my UIs generally evolve in that direction. I replace repetitive markup and helper methods with full-fledged OO classes, too. But I really doubt that I’d want to start building my app that way. I’d wait to discover the need for more abstraction and build it in then.

Another side note: Bruce mentioned that one of his apps had (ah, can’t remember exactly) over 100 partials. Other people have mentioned Rails apps with hundreds of controllers, views, models. Are they hacks? Or am I just small-time!

Is JavaScript Overrated?

Thursday, May 17th, 2007

Con-way graciously sent me to RailsConf, and even paid for the tutorials. I went to Thomas Fuchs’ morning tutorial “JavaScript Overrated? Or: How I Stopped Worrying and Put Prototype and script.aculo.us to Full” but I left after the first coffee break. Thomas is obviously a bright guy who’s done some great work with script.aculo.us, but his talk is pretty underpowered for a big room. A bit disappointing — lately I’ve been thinking that I haven’t given Javascript a fair shake. I could be convinced that Javascript is a dynamic OO scripting language that’s gotten a bad rap. Anyway, here are the high points:

Thomas assured us that lots of big companies use script.aculo.us and Prototype.

The Javascript libraries aren’t that big: the compressed version is 31K. And most everyone uses gzip compression on their web server, right? Uh, I don’t. Behind the times again.

I actually like that there is no script.aculo.us roadmap. “It’s done when it’s done.” It’s funny, I was going to make a joke about trying to implement that methodology at Con-way, but when I thought about it again, I wonder: don’t we do it that way anyway? We come up with big plans and schedules ahead of time, miss our targets, make excuses, and then … deliver it when it’s done.

Anyway, here’s script.aculo.us manifesto: Real-world. Small is beautiful. Ease development.

I don’t know why I hadn’t realized this before, but here’s the nut of how to do an AJAX request with prototype:
new Ajax.Request(‘/some_url’)
The server sends Javascript back and Prototype evaluates it.

Features in the new 1.5.1 release
– speediness
– CSS 3 selectors
– times() for String, padded strings
– use “return” instead of throw $continue
– Fix some Safari crashes
– JSON love

The official JSON library breaks Prototype.

Future features
– read/write attribute
– basic DOM builder
– wrap()
– curry(): like find. Huh? I should have paid more attention.
– defer()
– delay()

Another random observation — there are maybe 200 people in the room, and 95% have laptops. And most are MacBooks. My superficial impression is that the attendees are more stylishly dressed that they were at JavaOne.

There’s much more interesting conversation here at one of the tables outside the tutorial room (and free coffee). Someone’s “friend” is responsible for one of the largest Rails sites’ in the world: Paris Exposed. He handled a huge spike in traffic, and the only thing he need to do was switch to better session handling code. So when people tell you that Rails doesn’t scale, you can always say: “Well, what about parisexposed.com?”

Now the table has been highjacked a Microsoft IronRuby evangelist. He’s really worried that people will ignore Microsoft’s cool Ruby VM because we all ‘hate’ Microsoft. I am not sure that anyone here ‘hates’ M$, but this guys’ style is just wrong for us. It feels like he stumbled upon the wrong conference. Though it is cool to see a 17″ PowerBook with Microsoft corporate asset ID.

Rails PDF Plugin Error Pages

Thursday, February 8th, 2007

I needed to generate PDFs for the OBRA website, so I installed the Rails PDF plugin and Ruby PDF::Writer.

I’m happy with both. Typical for Ruby and Rails, they “just work” and my code is terse and expressive. (Well, the Rails plugin source code is a bit rough, and there are no unit tests. And the PDF::Writer API is a bit of a head-scratcher, but I blame Adobe for that.)

One minor annoyance is that Rails returns PDF page (.rpdf) errors as “application/pdf” content with names like mypage.pdf.html. Safari, at least, just saves the page to the desktop.

I improved this by overriding a couple methods in my ActionController:

def rescue_action_in_public(exception)
  headers.delete("Content-Disposition")
  super
end

def rescue_action_locally(exception)
  headers.delete("Content-Disposition")
  super
end

And now I get my errors in the browser, where I like them.

Ruby on Rails as Mailman External Archiver

Monday, January 23rd, 2006

I set up a Mailman mailing list. I want archives. I want these archives to look like other dynamic parts of the site (brought to you by Ruby on Rails). And I want to integrate a couple years’ worth of Topica messages.

At I first, I figured I’d use MHonArc or something similar. Mailman’s external interface is lightly documented, but simple and capable once you figure it out. Looking at the Python code helps in /usr/mailman/Mailman.

I decided to use Rails in the end. Maybe not the best choice, but I like keeping all my UI code in once place as much as possible.

I have an ActionMailer subclass with a delivery method:

class MailingListMailer < ActionMailer::Base
  def receive(email)
    post = Post.new()
    post.subject = email.subject
    post.body = email.body
    post.sender = email.friendly_from
    post.date = email.date
    post.save!
  end
end

class Post << ActionRecord::Base ....

I added an entry to PUBLIC_EXTERNAL_ARCHIVER in Mailman's mm_cfg.py file. On Suse 10, it's in /usr/lib/mailman/Mailman. I've add backslash line breaks for legibility here.
PUBLIC_EXTERNAL_ARCHIVER = '/srv/www/rails/obra/current/script/runner \
-e "production" "MailingListMailer.receive(STDIN.read)" \
>> /srv/www/rails/obra/shared/log/production.log'

I made several mistakes:

  • You need to restart Mailman for it to pickup your changes: /usr/lib/mailman/bin/mailmanctl restart
  • The apostrophes need to be around your command: '/srv/www ... production.log' Otherwise, you are trying to execute Python code, not assign a string variable.
  • Leave out -e "production" and Rails will execute in its development environment.
  • Ensure your logs are writeable by the mailman user, or nothing will work very well.

A typical Mailman error message in /var/lib/mailman/logs/error is "external archiver non-zero exit status: 127." Not very helpful. My shell foo isn't up to the task of redirecting standard error and standard out from the PUBLIC_EXTERNAL_ARCHIVER command. I got better info with Mailman calling a Bash script that then called the Rails runner. I validated that things worked at each small step, and I had to take baby steps because I kept putting a single quote where I needed a double quote, etc.:

  • Unit test for the ActionMailer
  • Run the ActionMailer in irb
  • Run the runner: sudo -u mailman /srv/www/rails/obra/current/script/runner -e "production" "MailingListMailer.receive(STDIN.read)"
  • Write a shell script to call the runner

Of course, it's helpful the public Mailman pages point to my new Rails-based archive. Here's how I do it. In Mailman/mm_cfg.py:
PUBLIC_ARCHIVE_URL = 'http://%(hostname)s/mailing_lists/%(listname)s/posts'

I like the end result, and it's easy to do once you know how to do it. Next step is to see if Rails can sew a header and footer onto the Mailman list info pages. I am keeping the gnu, of course.

gears