MacPorts man pages

If you're using MacPorts, don't forget to add it's man page path to your environment. I did, and I got all pissed off when there were "no manual entries" for commands I knew should have some.

To fix that, in .bash_profile (in my case anyway), I added:

export MANPATH=/opt/local/share/man:/opt/local/man:$MANPATH

and all was good.

Tags: macports  Meta: 10 comments, permalink

I'm a full-time working stiff now

I done got me a for real job. On monday I joined the crew over at ADS. I love the way Rob runs things over there. I think it's going to be a great fit.

Meta: 0 comments, permalink

Available

Update: I'm no longer available.

Just a quick note to say that Megablaix is available for new projects. You can contact if you're interested.

Meta: 0 comments, permalink

A better Basecamp

I've been using and loving Basecamp for a while, but I'm starting to feel the hurt for using it to manage software projects. Trac is great for software projects but terrible for client interaction. I really want the best of both worlds in one shiny app, plus a few extra bells and whistles. If I was designing something from scratch (hint), I'd probably want...

User types

  • Admin
  • Developer
  • Client
  • Vendor
  • Public

Projects

Normal projects are only viewable by admins, developers, clients, and vendors who have been added to the project by an admin. Some projects can be marked as public (e.g. open source projects) which will be viewable by anyone (i.e. public users).

Milestones

Basically the same functionality provided by Basecamp.

Tickets

Basically the same functionality provided by Trac, except that they should be updatable via email to ease client interaction. Getting clients to use Basecamp or (even worse) Trac has proven difficult.

Messages

Basically the same functionality provided by Basecamp, except there should be an option of text formatting that preferably defaults to Markdown which is much easier on clients. You should also be able to reply via email for the same reason.

Docs

Basically the same functionality we get from Basecamp writeboards, but again, with an option of text formatting.

Hours

You should be able to provide hour estimates for milestones as well as individual tickets. You should also be able to add actual hours worked to both as well. Hours would only be viewable by admins and developers. The reporting should be more flexible than Basecamp's, letting you filter by multiple projects instead of just one or all, and should somehow incorporate the estimates. Marking hours as invoiced needs to be in there too. Maybe even handling invoicing duties as well...

Client visibility

Almost everything should have the ability to be marked as private, which would hide it from client, vendor, and public users.

Update: Some things I don't need:

  • Todo lists (in favor of tickets)
  • Ghant charts

I think that's it. This is just off the top of my head. So... who wants to help?

Update 2: Unfuddle looks pretty close to what I'm after, although it doesn't have the client/developer separation I want... I'm going to give it a shot though.

Tags: project management  Meta: 5 comments, permalink

Getting a jump on Merb 0.9

Update 2: Ok, within hours of my last update, it looks like 0.9 is out. You can sudo gem install merb and ignore this post... move along... nothing to see here...

Update: Actually there's no need to install from source to get 0.9, you can simply install the development gems:

sudo gem install merb --source http://merbivore.org

Thanks to the Meet Merb Peepcode PDF for enlightening me.

If you still want to install from source, keep reading...

As of this writing, Merb 0.9 is not out yet, but I wanted to play with it anyway.

Fair warning, I am completely new to Merb and this may not be the best way to go about this, but it's working for me so far.

  1. Dependencies:

    sudo gem install merb -y # yeah...
    sudo gem install erubis -y
    sudo gem install json_pure -y
    sudo gem install json -y
    sudo gem install rspec -y
    sudo gem install rack -y
    sudo gem install rubigen -y
    sudo gem install hpricot -y
    sudo gem install haml -y
    
  2. Get git!

    I'm on OS X, and I use macports, so I did:

    sudo port install git-core
    
  3. Clone, build, and install merb-core, merb-more, and merb-plugins:

    git clone git://github.com/wycats/merb-core.git
    cd merb-core
    rake gem
    sudo gem install pkg/merb-core-0.9.0.gem
    cd ..
    
    
    git clone git://github.com/wycats/merb-more.git
    cd merb-more
    rake gem
    sudo gem install pkg/merb-more-0.9.0.gem 
    rake build_gems
    rake install_gems
    cd ..
    
    
    git clone git://github.com/wycats/merb-plugins.git
    cd merb-plugins/merb_rspec
    rake gem
    sudo gem install pkg/merb_rspec-0.9.0.gem 
    cd ../merb_datamapper # or whatever orm you choose...
    rake gem
    sudo gem install datamapper -y # if you don't have it already...
    sudo gem install pkg/merb_datamapper-0.9.gem
    
  4. Generate your app

    cd ~/Sites
    merb-gen my_site
    

Now have fun! To run the site cd into my_site and run merb then pull up localhost:4000

Tags: merb  Meta: 1 comment, permalink

Foxy Fixtures Gotcha

When I first tried to use foxy fixtures in rails, it didn't work. The ids it was assigning for foreign keys were way off. The problem seemed to be the fact that I was specifying the primary keys explicitly. I removed the id: attribute on all my fixtures and everything worked.

So this...

# in authors.yml
justin:
  id: 1
  name: Justin

# in articles.yml
how_to_fry_turkeys:
  id: 1
  author_id: 1
  title: How to Fry Turkeys

Didn't work when I changed it to this:

# in authors.yml
justin:
  id: 1
  name: Justin

# in articles.yml
how_to_fry_turkeys:
  id: 1
  author: justin
  title: How to Fry Turkeys

But did when I changed it to this:

# in authors.yml
justin:
  name: Justin

# in articles.yml
how_to_fry_turkeys:
  author: justin
  title: How to Fry Turkeys

Tags: fixtures rails  Meta: 1 comment, permalink

Keepin it simple

When working on model specs with rspec, it helps to have a hash of valid attributes for the model you're working with. This makes it easy to spec validations, save valid records when needed, etc. I used to use the method in this excellent peepcode of creating a helper module in the same file as my model spec. For example, if I was spec'ing a User model:

# The way I used to do it...

# In spec/models/user_spec.rb:

module UserSpecHelper
  def valid_user_attributes
    { :username => "user", :password => "pass" }
  end
end

describe User do
  include UserSpecHelper
  ...

That worked great, until I started wanting to spec complex associations, interactions between models, etc. In many cases I needed valid records of multiple different models. At first I simply moved the helper modules into external files that were required in spec_helper. That soon became cumbersome as I was including many modules in many different describe blocks. It just seemed like a lot of extra code simply so everything could stay pretty and proper and namespaced. So I said screw it, what's the harm in making these all top-level methods? And started throwing them directly in spec_helper.rb:

# The way I do it now...

# In spec/spec_helper.rb

...

def valid_user_attributes
  { :username => "user", :password => "pass" }
end

def valid_biscuit_attributes
  { :butter => true }
end

...

Now I can get a hash of all valid attributes for any model in any of my specs. This probably isn't the bestest most proper way to go about it, but it makes me happy.

Tags: rspec  Meta: 0 comments, permalink

can't activate rails, already activated rails?

After a fresh install of Leopard (good stuff), I installed ruby, installed rails, and fired up script/server on one of my sites, fully expecting it to barf out some gem I was missing. Instead, I got this error:

$ script/server
...
/opt/local/lib/ruby/vendor_ruby/1.8/rubygems.rb:246:in `activate': can't activate rails (= 2.0.2), already activated rails-1.2.6] (Gem::Exception)

Turns out there's a bug in rails 2.0.x causing MissingSourceFile exceptions to not bubble up to script/server. Being the lazy (busy?) man that I am, I found a solution that gets around the issue, rather than digging in, finding the problem, and creating and submitting a patch: Simply run mongrel_rails start instead of script/server. That seems to handle MissingSourceFile errors just fine:

$ mongrel_rails start
...
/opt/local/lib/ruby/vendor_ruby/1.8/rubygems/custom_require.rb:27:in `gem_original_require': no such file to load -- ferret (MissingSourceFile)

Bingo! That's what I was looking for!

On a side note, rest assured the fact that I'm still torturing myself with ferret causes me great shame and embarrassment.

Tags: rails  Meta: permalink

undefined method `last' for {}:Hash

I was getting this error on some pre-2.0 rails sites when trying to run rake after upgrading it to 0.8.1:

rake aborted!
undefined method `last' for {}:Hash

Luckily gem lets you have multiple versions installed and I was able to add this to my .profile:

alias old_rake="rake _0.7.3_"

Now I just run old_rake whenever I want to use rake on those sites and I don't get the error. I know this is a sucky, hackish solution, but I'm too lazy to find the real problem. Especially when I only work on a couple sites not on rails 2 yet.

Tags: rails rake  Meta: permalink

Putting myself in their shoes

Something I've been doing lately in my ongoing client projects is syncing my development database with the production database regularly (i.e. replacing all my test data with really for real live data). Sometimes there are issues I just don't notice until I see everything exactly as the user sees it. Maybe something I thought would have 10, maybe 20 entries ends up having thousands. Maybe something I thought would have thousands of entries only ever has 2 or 3. Maybe they're pasting in content from MS Word and I'm not properly handling some of the wonky characters...

Seeing live data can also reveal areas where a user completely misunderstands how something works, but I would have never known because they thought they did understand it. Seeing what data they're actually entering can sometimes reveal otherwise.

It also helps me notice where things are painfully slow. My test data is usually pretty speedy, since there's never that many rows in any particular table, but having live data in my development db could bump many of those up to thousands of rows, potentially causing some things to go pretty slow. Now, I could stick to just load testing, filling tables with random data, etc., but this doesn't reveal where the "real" load is. I don't want to waste my time optimizing something to handle a million billion rows of data when the user only ever has two in it.

This also forces me to actually address these issues right away instead of adding them to a todo list to be addressed 20 years from now. If I'm trying to develop and I keep getting annoyed by wonky characters, broken layouts from long strings, and slowdown from a fat table, I'm going to drop everything and take care of it, so I can get to work. Well, the user needs to get to work too, so that's a good thing.

(Plus, Navicat makes syncing as easy as clicking a button.)

Meta: 0 comments, permalink

One model to proxy them all?

Thinking of doing something like this for cases where I need to search or list records from multiple models:

class AnyItem
  def self.find(*args)
    returning([]) do |items|
      all_models.each do |model|
        items << model.find(args)
      end
    end.flatten
  end

  private
  def self.all_models
    # TODO: Best way to implement this?
    # Possibly something like this? http://pastie.caboo.se/130731
  end
end

(Obviously needs to be fleshed out a bit)

Terrible idea? Probably...

Tags: rails  Meta: 0 comments, permalink

Deploying a PHP site with Capistrano 2

I had no idea how easy it was to deploy a PHP site with capistrano. Assuming you have control over where your web root is (i.e. it would be much harder on a shared host), pretty much all you have to do is overwrite the restart tasks and you're good to go.

Here's what I did in more detail:

Lets say I have a php site called php_site. At the bare minimum, I should have my directory structure set up like this:

php_site/config # => Config scripts that should not be hit through the browser
php_site/public # => Public scripts and files that are meant to be hit through the browser

Now I just have to create the capistrano files:

cd /path/to/php_site
capify .

Now I alter config/deploy.rb as normal. The only difference is I want to override the start/stop/restart tasks since there are no mongrel or fastcgi processes to worry about. Here's an example:

# ============================================================================
# REQUIRED VARIABLES
# ============================================================================

set :application, "php_site"
set :repository,  "svn+ssh://user@php_site.com/var/svn/php_site/trunk"

# ============================================================================
# ROLES
# ============================================================================

# Only one role for this php site, easy!
role :app, "php_site.com"

# ============================================================================
# OPTIONAL VARIABLES
# ============================================================================

set :user, "user"                         # defaults to the current user
set :deploy_to, "/var/www/#{application}" # defaults to /u/apps/#{application}

# ============================================================================
# TASKS
# ============================================================================

namespace :deploy do
  desc "Empty stub for restart task (PHP sites don't need to restart)"
  task :restart do
    puts "Done"
  end

  desc "Empty stub for start task (PHP sites don't need to start)"
  task :restart do
    puts "Done"
  end

  desc "Empty stub for stop task (PHP sites don't need to stop)"
  task :restart do
    puts "Done"
  end
end

Note: If you're getting strange permission errors, you may need to add this to deploy.rb (See http://www.mail-archive.com/capistrano@googlegroups.com/msg02817.html):

default_run_options[:pty] = true

In this case, my site needs to be configured with a document root of /var/www/php_site/current/public. Don't forget to reload apache (or whatever webserver you're running) after configuring that.

To set up the server, as usual, just run:

cap deploy:setup

Then deploy with

cap deploy

You shouldn't have to run deploy:cold since there are no processes to start or migrations to run. Although setting up a php site to use ActiveRecord migrations would be sweet...

Tags: capistrano deployment php  Meta: 0 comments, permalink

Rails 2.0 Action Pack Record Identification with Namespaces

One of the cool new features in Rails 2.0 is smart record identification that lets you do things like this:

redirect_to(biscuit)
link_to(biscuit.name, biscuit)
form_for(biscuit)

At first, I just assumed this wouldn't work for namespaced resources (another new feature). Not true! If you are using a namespace like this:

map.namespace(:admin) do |admin|
  admin.resources :biscuits
end

You can reference them like this:

redirect_to([:admin, biscuit])
link_to(biscuit.name, [:admin, biscuit])
form_for([:admin, biscuit])

Neato!

Tags: rails  Meta: 0 comments, permalink

Rspec and associations

I'm never quite sure what the best way to write specs for assocations is. This is how I usually do it:

describe Butter do
  it "should belong to a biscuit"
    butter = Butter.new
    biscuit = Biscuit.new

    butter.should respond_to(:biscuit=)
    butter.biscuit = biscuit

    butter.should respond_to(:biscuit)
    butter.bicsuit.should == biscuit
  end
end

Really I'm just asserting that Butter has a biscuit attribute that I can use to set and get a Biscuit object. I do pretty much the same thing for all of the association types. I never really test that the association is actually a belongs_to association, or a has_one association, or any of the other types. But I'm not sure I actually WANT to test for that. Because that's technically not behavior, that's implementation. I'd just be testing rails internals instead of writing a spec for how my app should behave. Am I making any sense...?

Maybe the issue is the terminology I'm using. I considered saying "should have a biscuit attribute", but that felt... wrong. If I do that I might as well spec out all my attributes, and that is lame.

I also sometimes have a problem with the "should" terminology for associations. If I say "should belong to a biscuit" it seems to imply my object would be invalid if there was no biscuit object assigned, but that's not always the case. I considered "can belong to a biscuit", but... I just don't know.

I'm going to pretend like I have an actual reader-base and ask... any ideas?

Tags: rails rspec  Meta: 4 comments, permalink

How I BDD: Part 2

In part 1, I started using the creation of a Biscuit resource to demonstrate the way I approach Behavior Driven Development. I do not start with the business logic, domain model, or whatever you want to call it... I start by thinking at the highest possible level: "What should it do?" (in other words, how should it behave?). I determined that that there should at least be a biscuits homepage. So I created the specs for a biscuit controller with an index action and wrote the code to make the specs pass. I ended the post by thinking what the biscuits index should actually _do_. That is, of course: display a list of all existing biscuits. Sounds like I'm talking about the view, and I am. So I fire up autotest and create the index view spec:

Tags: bdd rails  Meta: 0 comments, permalink