Command history meme
Why not? Everyone else seems to be.
history | awk '{a[$2]++}END{for(i in a){print a[i] " " i}}' | sort -rn | head
125 git 66 gs 64 rake 56 cd 45 cap 33 ls 18 g 16 ./script/server 9 mv 8 svn
g is an alias for git. gs is an alias for git status. I like Chu’s alias of ss for script/server. I think I’ll do that.
cap deploy:pending
Running `cap deploy:pending` displays the commits since your last deploy. I wanted it’s output to be a bit different primarily so I could send a message to the others on the team about what’s just been deployed.
Specifically, I wanted the output to look something like this:
Deployment revision 49c45b7 I deployed the latest. It includes: * Added avatar support (Duff) * Cleaned up the project switcher (Alex)
To do that, I added the following capistrano recipe:
namespace :deploy do namespace :pending do desc <<-DESC Show the commits since the last deploy DESC task :default, :except => { :no_release => true } do deployed_already = current_revision to_be_deployed = `git rev-parse --short "HEAD"` puts "\n\nDeployment revision #{to_be_deployed}" puts "I deployed the latest. It includes:" puts system(%Q{git log --no-merges --pretty=format:"* %s %b (%cn)" #{deployed_already}.. | replace '<unknown>' ''}) puts "\n\n\n" end end end
Then I added a hook in my deploy.rb to run this automatically whenever someone deploys:
before "deploy:update_code", "deploy:pending:default"
The next piece of automation I’d like is to have it automatically post a message to basecamp.
Rails plugin - svn_messages (updated)
I created a rails plugin to help me keep clients up to date on the status of projects. This post is an update to the original svn_messages plugin.
The plugin now uses capistrano 2 (Multistage). I use it in 2 instances – whenever I deploy a site, and whenever I send a weekly status report. For a deployment, this is what I type at the command line:
cap staging svn:deployment_report
This gives me the following output:
Deployment to staging (Revision 34) I deployed the latest. It includes: * Started adding user registration system. (domelia) * Now translating validation errors and their attribute names. (bjones) * Reorganized views a bit. (domelia) * Now sending activation email when user signs up. (fsmith) * Added support for "remember me" when logging in. (domelia)I could have also typed:
cap production svn:deployment_report
For a weekly status report, I type the following:
cap svn:messages r=70 u=domelia
70 is the oldest subversion revision I care about. domelia is me. I specify this because I only care about the svn commits that I personally made. This gives me the following output:
* Started adding user registration system. * Reorganized views a bit. * Added support for "remember me" when logging in.
I like the plugin because I can keep clients up to date and spend very little time doing it.
To install:
svn export https://terralien.devguard.com/svn/projects/plugins/svn_messages vendor/plugins/svn_messagesbefore "deploy:update_code", "svn:deployment_report"
Rails Plugin - svn_messages
UPDATE: This plugin has been updated.
I created a rails plugin to help me keep clients up to date on the status of projects. I use it in 2 instances – whenever I deploy a site, and whenever I send a weekly status report. For a deployment this is what I type at the command line:
rake svn:messages r=70
70 is the oldest subversion revision I care about. This gives me the following output:
* Started adding user registration system. (domelia) * Now translating validation errors and their attribute names. (domelia) * Reorganized views a bit. (domelia) * Now sending activation email when user signs up. (domelia) * Added support for "remember me" when logging in. (domelia)
For my deployment report, I typically remove the svn messages that aren’t immediately visible in the site or that don’t matter too much to the client. So, I’d remove “reorganized views a bit”.
For a weekly status report, I only care about the svn commits that I personally made. In that case, I’d say something like:
rake svn:messages r=32 u=domelia
This would give me similar output, except it will only show me the commits made by the domelia user.
I like the plugin because I can keep clients up to date and spend very little time doing it.
To install:
svn export https://terralien.devguard.com/svn/projects/plugins/svn_messages vendor/plugins/svn_messagesCustom Mephisto
I’ve really been enjoying Mephisto, the blogging software that’s running this site.
I wanted to create another blog for some reviews I’ve written. So I started with the standard Mephisto and chose a theme from a Mephisto theme gallery and things were looking pretty nice. Then I wanted to start making some customizations. I considered using the plugin system that ships with Mephisto but I thought I’d just opt for a completely custom system and see if it would be difficult to have complete flexibility.
It turns out that it was super cinchy to do. Mephisto is open source, and it’s a well-written rails app. The technology world sure is changing in some fascinating ways. When you put some things together like ruby, rails, open source, the mac, quicksilver, and textmate, things start to get pretty exciting for developers.
I’ve made a few customizations so far and I’m not sure if I’ll ever want to customize it further. For now though, it’s much easier to mark a review as thumbs up or thumbs down and it’s easy to specify an amazon url for a review and know that it’ll show up with the correct amazon associates url.
One of the many amazing things about Rails is that you can so easily sit down and completely modify a Rails app you’ve never seen before, primarily because the framework makes it painful to step outside convention. I couldn’t even imagine doing something like this in some of the other web frameworks out there.
Here’s what Revnut looks like so far.
RJS for local javascript
There are times when I need to write a local javascript function (without needing a round trip to the server) and I’d like to use RJS rather than writing the function in pure javascript. Why would I want to use RJS?
- The syntax is clean and it’s often less code than pure javscript.
- When writing this function, I can mix in powerful Ruby constructs.
- It’s consistent with the other RJS in the project.
- I automatically get the function wrapped up in a CDATA tag.
- I automatically get exceptions handled by giving me an alert of the problem.
- It’s easy to conditionally exclude some of the javascript.
- My rails views look cleaner.
Here’s an example from a rails view (new.erb):
<%= define_js_function(:my_cool_local_function) do | page | page[:choice_entry_area].hide unless @question.multiple_choice? page[:add_answer_link].show page[:add_answer_button].hide end %>
So where’d this define_js_function method come from? I added it to ApplicationHelper. Here it is:
def define_js_function(function_name, &block) parens = function_name.kind_of?(Symbol) ? "()" : "" update_page_tag do | page | page << "function #{function_name}#{parens} {" yield page page << "}" end end
<script type="text/javascript"> //<![CDATA[ try { function my_cool_local_function() { $("choice_entry_area").hide(); $("add_answer_link").show(); $("add_answer_button").hide(); } } catch (e) { alert('RJS error:\n\n' + e.toString()); alert('function my_cool_local_function() {\n$(\"choice_entry_area\").hide();\n$(\"add_answer_link\").show();\n$(\"add_answer_button\").hide();\n}'); throw e } //]]> </script>
If the javascript function you’re creating takes no arguments, then you simply pass a symbol to define_js_function to specify the function name. If your function takes arguments, then you can pass in a string which contains those arguments like so:
<%= define_js_function("add_tag(tag)") do | page | page << "$('tag_list_str').value += tag" end %>
TUAW category feeds
I’ve been subscribed to the Unofficial Apple Weblog for quite awhile. It’s in my NetNewsWire folder entitled “Can’t Keep Up” (the place containing feeds that have so much content that I’ll never be able to read them all.)
I’m probably the last person in the Mac universe to realize that there are category specific feeds available so that you can subscribe to a subset of TUAW. This is outstanding because there are certainly parts of TUAW that are quite interesting to me.
I started out by subscribing to the following categories: Mac 101, Hacks, Tips and Tricks, Cool Tools, Terminal Tips, How To’s, and Productivity.
Rails Plugin - cadillac_edge_deploy
Is your deployed rails application frozen to a particular revision? If so, when a new version of rails is released how easy is it for you to upgrade?
Are you living on the edge of rails? If so, how do you move to a more recent revision when you notice an enhancement you want to take advantage of?
Switching to a different version of rails should be easy.
Mike Clark described a number of ways to manage your rails versions in this blog post.
Mike wrote of a “Cadillac Edge Deploy Approach” in referring to Rick Olson’s code that makes managing rails versions quite cinchy.
This plugin is basically a rip-off of that blog post and Rick’s code.
I refactored things a bit primarily because I needed the approach to work even if Rails wasn’t installed on the server I was deploying to. I’ve also changed it since to work with git rather than svn.
Example Usage
To use the plugin, all you need to do is add the following to your deploy.rb:
set :rails_revision, '745359a49452da34978724144eaa318b8a363e08'
When you’d like the server to start using a different revision of rails, just adjust the rails_revision variable.
To install the plugin:
./script/plugin install git://github.com/duff/cadillac_edge_deploy.gitTextMate ternary operator command
Ever have a simple conditional that you’d like to quickly switch to ternary operator syntax? For example, you have a simple piece of code like this:
if x > y result = "Fred" else result = "Joe" end
and you’d rather it look like this:
result = (x > y) ? "Fred" : "Joe"
Or, you’ve got this:
if x > y "Fred" else "Joe" end
And you’d like this:
(x > y) ? "Fred" : "Joe"
I wrote a little TextMate command to help. It allows you to select the 5 lines of the conditional and convert it to ternary operator syntax by pressing a keyboard shortcut. Here’s what it looks like:
#!/usr/bin/env ruby original = STDIN.read result = original begin lines = original.split("\n") if lines.size == 5 space, conditional = /(\s*)if\s(.*)$/.match(lines.first)[1..2] if_parts = lines[1].split("=") if if_parts.size == 2 variable = if_parts.first.strip if_result = if_parts[1].strip else_result = /.*?=(.*)/.match(lines[3])[1].strip result = "#{space}#{variable} = (#{conditional}) ? #{if_result} : #{else_result}" elsif if_parts.size == 1 result = "#{space}(#{conditional}) ? #{lines[1].strip} : #{lines[3].strip}" end end rescue Exception => e ensure print result end
- Save : Nothing
- Input : Selected Text or Nothing
- Output : Replace Selected Text
- Activation : Key Equivalent (Specify whatever Key Equivalent you’d like)
- Scope Selector : source.ruby
Prettied up test output using assert_arrays_equal
I’ve got a pretty simple test:
def test_relationships wellspring = churches(:wellspring) cleaning_crew = Group.create!(:name => "Cleaning Crew", :church => wellspring) assert_equal([cleaning_crew], wellspring.groups) end
The problem is that when this test fails, I get a ridiculous amount of output and it’s difficult to quickly determine why the test is failing. Here’s the output I get:
1) Failure: test_relationships:10 <[#<Group:0x3492918 @attributes= {"name"=>"Cleaning Crew", "church_id"=>1, "id"=>32, at top level in "created_at"=>Thu Mar 01 15 at line 56 @church= at top level in #<Church at line 0 @attributes= {"name"=>"Wellspring Community Church", "account_owner_id"=>"1", "timezone"=>"Alaska", "subdomain"=>"wellspring", "id"=>"1", "tz_name"=>nil}, @groups= at top level in #<Group at line 0 @errors= at top level in #<ActiveRecord::Errors at line 0 @new_record=false>]> expected but was <[#<Group:0x348c0a4 @attributes={"name"=>"Elders", "church_id"=>"1", "id"=>"1", "created_at"=>"2007-03-01 10:01:58"}>, #<Group:0x348c07c @attributes={"name"=>"Children's Ministry", "church_id"=>"1", "id"=>"4", "created_at"=>"2007-03-01 10:01:58"}>, #<Group:0x348c054 @attributes={"name"=>"Cleaning Crew", "church_id"=>"1", "id"=>"32", "created_at"=>"2007-03-01 15:56:38"}>]>. 1 tests, 1 assertions, 1 failures, 0 errors
This is what I’d like the output to look like:
1) Failure: test_relationships(GroupTest) method assert_arrays_equal in test_unit_extras.rb at line 8 method test_relationships in group_test.rb at line 11 <"Cleaning Crew"> expected but was <"Elders, Children's Ministry, Cleaning Crew">. 1 tests, 1 assertions, 1 failures, 0 errors
To me, that’s a bit easier to read. Here’s how I did it. The test has a small change. Instead of calling assert_equal, it calls assert_arrays_equal. So the test now looks like this:
def test_relationships wellspring = churches(:wellspring) cleaning_crew = Group.create!(:name => "Cleaning Crew", :church => wellspring) assert_arrays_equal([cleaning_crew], wellspring.groups, :name) end
Where did assert_arrays_equal come from? You can get it by installing the plugin I just created:
./script/plugin install git://github.com/duff/assert_arrays_equal.git
assert_arrays_equal allows you to specify which method you’d like to be called on the objects in your arrays for the output message. It still asserts that the arrays are actually equal. The failure error message now uses the method you specify. In the test above, I specified the :name method because I want Group.#name to be called rather than Group#inspect. If you don’t specify a method, it defaults to :to_s.
Viewing a page in a browser
I’ve been doing a bunch of integration testing of a rails site lately. I have found it quite useful to be able to quickly view the current page in a browser.
I added the following method to my integration testing DSL:
module IntegrationDsl def view filename = File.dirname(__FILE__) + "/integration/.integration_test_output_for_browser.html" File.open(filename, "w+") { | file | file.write(response.body) } `open #{filename}` end end
It simply writes out the response body to a file and then opens it (using the `open` on a mac).
So now in my integration test, I can view the current page in a browser like this:
def test_feature s = new_session_as :duff s.view end
Clicking a link
There have been times when integration testing a rails site that I’ve wanted to click a link on a page without caring about it’s route or url.
So let’s say the following exists on a page in my app:
<html> <a href="http://meresheep.com/users/4;resend_activation_email"> resend your activation email </a> </html>
In my integration test, I can now do things like this:
def test_non_activated_user s = new_session_as :duff s.click_link("resend your activation email") s.assert_template("invitation_sent") end
module IntegrationDsl def click_link(link_text) assert_select("a", link_text, "Trying to click a link named '#{link_text}' that did not exist") do | links | get_via_redirect links.first.attributes['href'] end end end
The test fails if the link doesn’t exist on the current page.
TDD - Rails integration style
I’ve been writing unit tests for many years. I can’t live without them. Writing code from a test-driven perspective became second nature for me a long time ago.
I’ve played with Rails integration tests on a few different projects now and each time I did, I found that there was a slight learning curve for using them. I also found that the tests were often larger than the code I was actually testing. The tests seemed brittle and they seemed to take such a long time to write.
Recently I decided that I just needed to keep writing them for awhile to see if I could get good enough at them such that they were no longer a burden to write. A conversation with Robert certainly played a part in this decision. Since I was working on a personal project this past week, it was a perfect opportunity.
What I’ve found is this. Rails integration tests are amazing. They were taking such a long time to write because I was new at it. They were brittle because I didn’t know what I was doing. The tests were long because I was testing things more than once and I wasn’t refactoring to a Domain Specific Language (DSL) like Jamis wrote about.
The result is that my integration tests are now slim. They’re cinchy to write and they’re getting easier as the DSL for the project improves. I’ve gotten good enough at it that I can now write the integration test before implementing the feature. They’re not taking very long to write at all. It feels amazing knowing that the regression tests are accumulating and it’s becoming harder and harder to break the site I’m working on.
I realize now that the unit testing I did when starting out wasn’t test-driven at all. I wrote unit tests after I wrote the code I was testing. After developing some competence, I was able to switch over to test-driven unit tests. A similar process has now happened with integration tests.
The 2 or 3 days it took to get up to speed was quite worth it.

