Are those pants made of mirrors, because I can see myself in them...

No, I'm not going to tell you how to seduce the comic book superhero with an evening of dinner, cocktails, and smooth talk while demonstrating impeccable manners and etiquette.

What I am going to tell you is how to correctly use the handy Rails tool for passing objects between actions.  Now, this is no huge secret or stunningly clever trick.  In fact, you probably already know what I'm about to tell you.  It's just one of those things that I never think to do until after it's a problem.

In the typical Rails app, there a snippet/partial/whatever that displays anything from the flash hash with either :notice or :error keys.  If, in your controller action, you set flash[:notice] equal to some message and then redirect to another action, that message will persist through the redirect and get displayed on the subsequent view.

Here's the problem.  If, in your action, you just render a view template instead of redirecting, then the user will see that message like you intended but it will also still remain on the following request which may or may not be confusing.  Fortunately, there's an easy way to avoid this.

If you know you'll be redirecting, then there's nothing to worry about.  Business as usual.  But if you're not redirecting, just rendering a view, then you can use flash.now[:key].  The 'now' method only maintains the flash contents through the current request and is cleared before the next action.  Check it out.

def create
  @thing = Thing.new(params[:thing])
  if @thing.save
    flash[:notice] = "Oh snap!  You created a thing!"
    redirect_to @thing
  else
    flash.now[:error] = "Damn dog, you messed up"
    render :action => :new
  end
end

Notice how when the thing save without errors we use flash[] and redirect, but when there are errors we use flash.now[] and there's no redirect.  This will keep your app users from seeing any strance, out of place errors.

So that's it.  Like I said, it's nothing monumental.  As you were...

Comments (0)    rails flash

feat-shamwow.jpg

Remember my post from a few weeks back about temporarily disabling ActiveRecord callbacks?  Well, I decided to extend the functionality a bit and wrap it all up in a plugin.

You can now specify one or more callbacks to disable, or specify nothing and disable all callbacks by default.

You can check out the project page or jump over to the Github repo.

Comments (0)    git rails active_record callbacks plugin

I ran into a strange issue while attempting to checkout a remote tracking branch of an Intridea project earlier today, so I thought I'd post up my work around.

I ran my normal checkout command, like so...

brent:~/Intridea/earthaid[master]$ git checkout -b prod origin/prod

which resulted in this error message

fatal: git checkout: updating paths is incompatible with switching branches.
Did you intend to checkout 'origin/prod' which can not be resolved as commit

After a bit of googling, I'm still not sure of the cause as most of the search results were related to issues around deploying tags, and I was merely attempting a checkout.  What I did find out was that I could specify the start point of my new branch by the revision/commit sha instead of the remote branch name, like so...

brent:~/Intridea/earthaid[master]$ git branch prod 02314583a99abdc276cde968c20babbadd23
brent:~/Intridea/earthaid[master]$ gc prod
Switched to branch "prod"
brent:~/Intridea/earthaid[prod]$

Once I had applied my changes, I just had to make sure to push them to the proper branch.

[update]

farside_cartoon.jpg

Ok, I'm a retard.  About a minute or two after I typed up this post, it occurred to me that Git couldn't resolve the remote branch name because I hadn't pulled first.  Yeah, that's right.  All I need to do was pull and then everything worked properly.

Comments (0)    git brain-fart

Today I began helping out on an Intridea project that (by the client's request) uses Subversion as their revision control system instead of Git.  Initially I was a bit dismayed.  Hell, I actually felt a little sick to my stomach.  Git has treated me very well over the past year, and I hadn't touched a Subversion repo in even longer.

Git-svn had crossed my mind, but it wasn't until a coworker suggested it that I decided to give it a try.

The first thing was to get it installed.  I followed this tutorial and only had to make one small change.  Adding /opt/local/libexex/git-core to my path didn't work.  I did a quick whereis to find out that my git-svn executable is in the /usr/local/git/libexec/git-core/ directory.  I updated my path and everything was kosher.

Now to set up the repo.  Most of the tutorials that I found covered setting up a new svn repo with git-svn like this one, but in my case, the svn repo had been around for quite some time.  Being the wannabe-know-it-all that I am, I decided to just go ahead an clone the svn repo, like so:

git-svn clone http://path-to-the-svn-repo

After about ten minutes of watching the clone chug away, I thought something was up.  Well, it turns out that if you don't include the proper options, the clone will pull down all branches, tags, whatever.  I didn't want, or need all of that.  All I wanted was trunk.  After a brief glance at the git-svn docs, I tried again with the --trunk flag.

git-svn clone --trunk http://path-to-the-svn-repo

Aparently, the -s option also works.  It tells git-svn that you svn is in the standard layout with trunk, branches, tags, and whatnot.

This time it ran for only five minutes before I asked myself wtf was going on.  I realized that it was pulling down every single revision, which I really didn't need.  I would've stopped it and tried again with the --revision (-r) flag which allows you to specify a revision number, or range of revision number, but the clone was already at rev 900 out of 1100, so  I just let it ride.

Once that was done, I was good to go.  I could pretty much just treat it as a regular Git repo until I was ready to push any changes back to the svn repo.  I used this tutorial by Clinton Nixon, who I had recently seen do a talk on Scala at the Developer Day in Durham, to help guide my general git-svn workflow.

Comments (0)    git subversion git-svn svn

So I finally got around to replacing the dummy text in the sidebar with real, working archive links, and it was stupidly easy.  Check it out...

First, I added a helper method to take all published posts and group them by the month they were created.

def archives
  @archives = Post.published.in_order.all.group_by { |t| t.created_at.beginning_of_month}
end

Then I used that helper method to display links for each month in which posts were created.

    <% archives.each do |month, posts| %>
  • <%= link_to(month.strftime('%B')+" (#{posts.size})", archive_path(:month => month.month, :year => month.year)) %>
  • <% end %>

You probably noticed the archive_path named route that the links point to. Here's how I set it up.

map.archive '/posts/:year/:month', :controller => 'posts', :action => 'archive'

That route points to the archive action of the posts controller which merely retrieves the posts created within the specified month and renders the list view.

def archive
  @posts = Post.published.in_order.from_month(Time.parse "#{params[:month]}/#{params[:year]}").paginate(:page => params[:page], :per_page => 5)
  render :action => 'index'
end

The archive action uses a from_month named scope on the Post model to restrict the find to all posts created within a given month.

named_scope :from_month, lambda { |month| {:conditions => {:created_at => month..(month + 1.month)}} }

That's it. That's all it takes to set up simple archive links for your blog.

Comments (0)    tips how-to