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
testsspecs for their code. - Nicer DSL-ish
testsspecs.context "should do this" door@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.
why should we use microformats?
John Allsopp has written a very insightful piece on the Digital Web Magazine – The 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.
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.
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.
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.
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.
Mephisto 0.5: Thanos released!
It’s out, read the excitement over at the Mephisto Blog.
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
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.
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.
