Archives for Aug 2006

Busy Railers Guide to BDD

Update: I have a simply_bdd plugin now.

Luke’s Developing a Rails model using BDD and RSpec, Part 1 is a very good read if you’re just getting into Rails testing, or just want to check out how the folks in the BDD camp do things.

I’ve been interested in the whole BDD thing for awhile, ever since I started prefixing my test methods with should_*. So far I’ve found three main advantages of using BDD, and none of them are good enough (for me personally) to jump ship:

  • Nudge TDD newbs towards writing better tests specs for their code.
  • Nicer DSL-ish tests specs. context "should do this" do or @user.name.should_equal 'bob'

And my favorite:

  • Group tests under a common context with the same setup methods.

I typically extract common setup stuff to a private method in the Test Case, or make a specific fixture for it. Using BDD’s context method seems to be more DRY than using a private method. So, throw this in your test_helper.rb:

def context(name, &block)
  Object.const_set(name.to_s.gsub(/ +/, '_').camelize + 'Test', Class.new(Test::Unit::TestCase, &block))
end

# context "New User" do
#   becomes
# class NewUserTest < Test::Unit::TestCase

This will define multiple test cases in your test suite, but should run just fine. You can do everything inside the context block that you can do while defining the new TestCase.

So, you like the specify method too?

# test_helper.rb
class Test::Unit::TestCase
  self.use_transactional_fixtures = true
  self.use_instantiated_fixtures  = false

  def self.specify(name, &block)
    define_method 'test_' + name.to_s.gsub(/ +/, '_'), &block
  end
end

# specify "should require password" do
#   becomes
# def test_should_require_password

Think of this as a quick 6-line hack to test the BDD waters.

0 comments | posted 29 Aug 09:46

why should we use microformats?

John Allsopp has written a very insightful piece on the Digital Web MagazineThe Big Picture on Microformats. It goes into what sites are publishing with them, and what products are actually taking advantage of them. It’s clear we’re still in the very early days of microformats. Frankly, you don’t get a whole lot of benefit taking the time to implement them. But, as the pioneers push on, more services will pop up, and it’ll become more and more important to take advantage.

0 comments | posted 28 Aug 20:04

Managing local subversion repositories

Piston looks like it could be a nice alternative to svk.

Piston is a utility that enables merge tracking of remote repositories. This is similar to svn:externals, except you have a local copy of the files, which you can modify at will. As long as the changes are mergeable, you should have no problems.

0 comments | posted 25 Aug 06:23

Got Docs?

I’ve recently discovered gotAPI, and started using it for my own rails documention needs. What sets it apart from other tools, is the addition of documentation on other topics. I currently have tabs for HTML DOM, CSS, and Prototype, as well. All have their uses during regular Rails development.

0 comments | posted 23 Aug 18:48

Donate

I’ve had a number of people ask how they might be able to say thanks for my contribution to the open source projects I’ve worked on (like Mephisto, Beast, and Rails Weenie). I was a bit hesitant to put this page online, but I’m even more resistant to putting ads on my sites, so I figured this was the lesser of the two evils.

In any case, if you’d like to make a donation, you can use the Paypal donate button below. I split all donations for Mephisto with Justin, and Beast with Josh, so be sure to let me know what the donation is for.

0 comments | posted 22 Aug 11:52

Reloading Killed My Attachments

Update: Nicholas tried some fixes for this, but ultimately came to the conclusion that perhaps reloadable plugins weren’t such a hot idea. He’s going to add a Dependencies.only_once_paths configuration option that lets you specify libraries that should only be loaded once. This way, current plugins should continue to work. If you want reloadable plugins, there’ll be a way to enable that, as well.

If you happen to be one of those cutting edge developers using my Acts as Attachment plugin on edge Rails, you may have started noticing this:

uninitialized constant Technoweenie::ActsAsAttachment::ClassMethods::Technoweenie

In fact, _whynot goes over this in more detail on rails weenie. I’ve seen a few workarounds for this:

  • Freeze your app to edge Rails revision 4727 temporarily (this is the approach I’ve taken on Mephisto).
  • Replace references of Technoweenie with ::Technoweenie:
delegate :content_types, :to => Technoweenie::ActsAsAttachment
# becomes
delegate :content_types, :to => ::Technoweenie::ActsAsAttachment
  • Josh Peek suggested manually requiring the module in init.rb. I this keeps the module from reloading in development mode.
require 'technoweenie/acts_as_attachment'
ActiveRecord::Base.send(:include, Technoweenie::ActsAsAttachment)

Frankly, all these workarounds suck. I’d much rather see Rails fixed, as I’m still convinced it’s a Dependencies issue, not an issue with my plugins. I’ve been working with Nicholas on a satisfactory fix. If you have any more broken plugins, or even have a failing test case for ActiveSupport, please let me know.

0 comments | posted 16 Aug 04:35

Mephisto 0.5: Thanos released!

It’s out, read the excitement over at the Mephisto Blog.

0 comments | posted 10 Aug 09:19

Introducing the Mephisto Blog

We decided to go ahead and announce the new Mephisto Blog. Mephisto 0.5 is just around the corner though, I’m still finding and squashing some minor odd bug

0 comments | posted 07 Aug 18:28

Dynamic Restful Scaffolding

It seems this interest in restful rails apps is bringing out a number of restful scaffolding frameworks too. Once you make a few resource controllers, they all start looking the same. The main differences usually lie in the model scoping and authentication filters. It’s natural to look at this and try to devise some DRY way to define these actions. Jeremy is not the first to attempt this, with his experimental Rapid Resource macros. I took a stab too: http://pastie.caboo.se/7319.

This approach seemed to work well in my basic tests. However, it became apparent that I would have to allow for customizations on nearly every line of code. Take this standard create action and note the areas you may want to configure:


  def create
    @post = Post.new(params[:post])
    @post.save!
    redirect_to post_path(@post)
  rescue ActiveRecord::RecordInvalid
    render :action => 'new'
  end
  • Does Post have a parent model? Maybe you want @user.posts.build(params[:post]) ?
  • Do you want to redirect somewhere else?
  • Do you want to Flash notices?
  • Do you want to respond to alternate content types such as XML, YAML, Atom?

The dynamic scaffolding code could get pretty complicated with all these customizations. The application developer now has to remember various new methods to overwrite to customize various aspects of the app. None of this feels right, especially when the initial controller code is so basic. Maybe instead of working on this, I’ll focus on the app and let these similar controllers evolve naturally. However, I do have a very basic resource generator that I threw together.

0 comments | posted 04 Aug 20:38

Restful Authentication Plugin

People have been asking me about it, so I decided to write it on the next small project I tackled. That day came last week, so here’s the plugin!


script/plugin source http://svn.techno-weenie.net/projects/plugins
script/plugin install restful_authentication

script/generate authenticated user sessions

I have no idea how restful logins are going to pan out. This plugin differs from acts_as_authenticated by generating two controllers and requiring special routes. But if you’re a restful geek this should appeal to you.

users controller

The nice thing about this is that the new/create actions relate to the resource that’s created during the signup. Simple apps will just use users/new and users/create. Larger hosted apps may use accounts, etc.

sessions controller

I’m a bit iffy on this. Though you’re not really exposing a session, it keep let this login/logout process separate from the rest of the app. This would also be a good place to hook into if you’re auditing logins or just tracking who’s currently online.

0 comments | posted 01 Aug 11:38