Quick Tip: SSH Backspace
August 26th, 2008
I just ran across this informative post by Jonathan Tron that solved an annoyance I’ve had for a while: backspace not doing what I want when I use SSH.
Change your Terminal Preferences
- In Terminal, select Preferences | Settings | Advanced.
- Select ‘Delete sends Ctrl-H’
You may need to do this again if you change your terminal style.
Specify a setting for nano
- On your server open ~/.nanorc
- Add ‘set rebinddelete’
And now you should have backspace working correctly for at least a few things…
Quick Tip: Route Associations
August 26th, 2008
Are you used to writing your routes like this?
map.resources :notes do |notes|
notes.resource :author
notes.resources :comments
notes.resources :attachments
end
Don’t fret, there may be hope for you yet. For these simple routes you can use the has_one or has_many route association options.
- has_one – use it for a singleton resource
- has_many – use it for plural resources
Refactored routes
map.resources :notes, :has_one => :author, :has_many => [:comments, :attachments]
Give it a try!
Keep in mind I said simple. If you’re doing something more complex they might not be the best choice.
Additional Resources
Quick Tip: has_many :through => checkboxes
August 25th, 2008
It’s really easy to create a many-to-many relationship that can be assigned through checkboxes. Check it out!
Let’s say you have Users and Groups. A User can belong to a Group and a Group can have many Users – we call this a Membership, like so (migrations omitted for brevity):
app/models/user.rb
class User < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :groups, :through => :memberships
end
app/models/group.rb
class Group < ActiveRecord::Base
has_many :memberships, :dependent => :destroy
has_many :users, :through => :memberships
end
app/models/membership.rb
class Membership < ActiveRecord::Base
belongs_to :group
belongs_to :user
end
We can now assign groups to members in a relatively easy manner with no extra work needed in the models. Behold!
app/views/users/edit.html.erb
<h1>User <%= @user.id -%></h1>
<h2>Group Memberships</h2>
<% form_for @user do -%>
<% Group.all.each do |group| -%>
<div>
<%= check_box_tag :group_ids, group.id, @user.groups.include?(group), :name => 'user[group_ids][]' -%>
<%= label_tag :group_ids, group.id -%>
</div>
<% end -%>
<%= submit_tag -%>
<% end -%>
Errr… something like that. Anyway, the important thing to note is the use of group_ids. The values will get submitted as group_ids, a member of the User. Where did that come from? We don’t have an attribute or method on the model for it, so where’d it come from? Well, seems that it is auto-generated for you to allow something like I just showed.
When this form is submitted, any checked Groups will be associated through Memberships to the User by way of the magic *_ids= method. Should work the other way too with user_ids checkboxes on a group. No extra code needed. Awesome, right?
Bonus: If you uncheck all the checkboxes, then nothing gets posted, doh! So make sure to merge a default value with your parameters like this to ensure the *_ids= method gets called:
app/controllers/users_controller.rb
@user.attributes = {'group_ids' => []}.merge(params[:user] || {})
Super Bonus: When you’re defaulting the group_ids in the controller make sure to use the key as a string, not a symbol. Or if you do use a symbol then make it a Hash with_indifferent_access.
Super Monkey Ball: A monkey encased in a ball who collects bananas.
Quick Tip: Capistrano SSH Ports
August 24th, 2008
If you have changed the SSH port number on your server, then you need to let Capistrano know how to connect. Luckily, it’s pretty easy.
Add the following to your deployment file, replacing 8888 with your port number.
config/deploy.rb
ssh_options[:port] = 8888
This will apply that port number to connections made by Capistrano. If you need to specify the port for each server (app, web, db) then tack it on to the end of their declarations.
role :app, "65.74.169.199:8030"
role :web, "65.74.169.199:8031"
role :db, "65.74.169.199:8032", :primary => true
I haven’t verified that one, but it supposedly works. Happy deployments!
Rails Class Collisions
August 23rd, 2008
While trying to use Integrum’s oh-so-nifty missing spec finder on a recent project, I discovered that it was not working. Hmmm… seems that somewhere along the way Rails added detection for existing constants and won’t allow you to re-generate something. Instead it calls raise_class_collision, which raises a UsageError. Damn them.
Anyway, to work around this for now, you can add the following somewhere (e.g., an initializer):
require 'rails_generator/base'
require 'rails_generator/commands'
module Rails
module Generator
module Commands
class Create
def raise_class_collision(class_name)
# Do Nothing
end
end
end
end
end
This should get around that inconvenience. Plus, you won’t be exposed to nefarious suggestions like I was:
$ rake spec:sync
The name 'User' is either already used in your application or reserved by Ruby on Rails.
Please choose an alternative and run this generator again.
Suggestions:
exploiter
drug user
substance abuser
Thanks Rails, you’re so helpful! I just don’t understand how it could have known I was building a Facebook clone for junkies…
Other Resources
Quick Tip: SSH Config
August 22nd, 2008
It’s easy to create shortcuts for all those servers you need to SSH into. There should be a file in your .ssh directory called config. Simply add a few lines to this file and you can refer to those servers by their short name.
Example (~/.ssh/config)
Host foo
Hostname some.long.hostname.you.cannot.remember.com
User myuser
Port 1234
Now you can use your new host when you SSH.
ssh foo
If you want to get even fancier, read the man page for additional options.
man ssh_config
Setup as many as you need and free yourself from SSH hostname hell!
An Experiment in Remote Pairing
August 12th, 2008
Recently, my employer, Integrum Technologies, has allowed me to work from home one day a week. This is due to rising gasoline prices combined with my distance from work. It’s great for me as I’ll save quite a bit of money each week as well as reduce my overall emissions. However, this has presented us with a slight dilemma: how do we remote pair effectively?
Pair Programming
Integrum subscribes to a variety of Agile practices. Perhaps the most prominent is working in pairs, a.k.a pair programming. I was first introduced to the idea of pair programming around 1999 when I was at the University of Arizona learning how to completing my BS. At that time we simply learned the theory from a professor, but didn’t actually try it.
About 16 months ago I was working in a contract position with my friend and phoenix Ruby on Rails developer, Josh. Toward the end of our time at that contract we attempted pairing and found it worked really well. When we were hired as contractors at Integrum we paired on a project form start to finish and then later, when we went full-time, we paired with the rest of the team members. These positive experiences with pair programming have convinced me of it’s usefulness.
Now that I work a day from home, how will I pair with my various teammates?
Remote Pairing
I’m sure there are many, many ways to pair remotely, but here I will describe our first attempts at pairing remotely. It may help that we’re an all Mac shop, but we found it rather easy to get up and running quickly.
Systems
At home and at work we are using iMacs running OS X 10.5.4. The built in iSight and microphone are great for what we need right now.
Complaint: Noise. It’s everywhere, seriously. The mic picks up everything.

iChat
Yep, that’s right, iChat – video chat specifically. We simply fire up our iChat instances using our Integrum Jabber IDs and request a video session. Seriously, that’s all we do. The sound and video quality have been more than adequate for pair programming 7 hours a day.
Our first attempt at this was flawless, well… until it just stopped working that is. After a little research we found that I probably needed to open the right ports to maintain a consistent connection (this post on iChat Routing Problems helped). After I did that we haven’t had a problem.
Complaint: Video chat over iChat can sometimes lag or have artifacts, especially during peak times. It’s good enough, but would be nice if it were smoother and clearer.
Screen Sharing
While we’re pairing we share the screen on one of the computers. When we’re done we turn it off. This allows us to both have control of the keyboard/mouse if we need it and has helped immensely in making us feel like we’re both working. We take turns driving while the other gives advice or comments and we can smoothly transition from one driver to the other.
Complaint: From my end the connection latency can sometimes hinder progress. If I hit one of the Exposé areas of the screen and all the windows separate it can almost bring rendering on my side to a halt. There also seems to be a problem with select via the mouse. When I click and drag to select some text the screen jumps to the top or bottom immediately, selecting all text between. I’ve had to get better with the keyboard.
iSight + built-in microphone + iChat + Screen Sharing = Adequate Pairing
I do have some complaints about the current setup, but I’m willing to keep going until we find better solutions. Perhaps we should try using Xbox Live as I’ve heard some people suggest.
I think the next steps are to secure some good microphone headsets that will reduce the noise and allow us to hear one another more clearly. Then we can look at replacing iChat and Screen Sharing.
As tools for remote pairing progress I can see more developers turning to this as a solution to save money and time while still retaining their communication with their team, especially with their pair. Pairing remotely can reduce cost for the developer and the company, save time and reduce emissions because the developer no longer commutes. And if their whole company is remote then all the better!
Everything I Need to Know About Pair Programming Etiquette, I Learned From My 4 Year Old
August 5th, 2008
The folks at Integrum recently had a discussion about avoiding distractions while pair programming. We all know how many distractions there are in today’s world, everything from email to blogs to Twitter. It’s hard to not get distracted by all of these things, as they have become so prevalent in our lives. We want to be in the know and there are many tools out there that let us do just that. They constantly run in the background or popup, they email us, they text message us, they demand our attention…
Look at me, I’m a tweet!!
No, I’m working.
But I’m a direct message from iJustine!
Well… okay, just this once!
But it’s not once, it’s all the time… constantly interrupting (seriously Justine, stop, I’m not going to respond). When someone is paying you for your time, they don’t want to be competing with all these distractions.
So what’s appropriate etiquette for a person working in a pair programming environment? I asked my 4 year old over dinner to see what he thought.
The Interview
me. Do you know what it means to work in a pair?
ethan. When 2 people are working together.
me. Good. What about focus? Do you know what that means?
ethan. Stay on track. Concentrate. Keep an eye on what you’re doing.
me. How about respect, do you know what that means?
ethan. Be nice?
me. Okay good, let’s get started.
me. When you’re working with someone as a pair is it okay to check your email, instant messenger or twitter?
ethan. No.
me. Why is it not okay?
ethan. Cause we might lose focus.
me. If we were working together and I was having trouble solving a problem, how could you help me?
ethan. I could tell you how to do it.
me. What if you didn’t know how to do it?
ethan. We could think of an idea and do it.
me. Should we think by ourselves?
ethan. No we should talk and hear… and choose what we want to do.
me. If were working together and I get distracted, what should you do?
ethan. Daddy, what are you doing? Please pay attention. You made me distracted and I don’t know what I was working on.
Conclusion
This interview proves beyond a doubt that my 4 year old knows what it takes to work in a pair programming environment. He was polite, but forceful in his remonstration of my lack of focus. His answers were not overly complex, he kept it simple. Which is as it should be since it really isn’t all that complex – there’s a reason the acronym KISS exists.
So there you have it, think like a 4 year old and you’ll do just fine in any pair programming environment :)
Ethan's Dance Recital
June 25th, 2008
Ethan had a hip-hop, tap dance recital recently. Here’s a video of him, he’s the fourth from the left in the front row with his hat backward.
TwitterBot Gem Released
June 11th, 2008
Tonight, at one of our (in)famous hack-a-mania nights at Integrum, we released a gem for accessing Twitter through XMPP. Read the full Integrum release article and then go get hacking!
I’m excited because not only did I have a hand in the creation of the twitter_bot gem, but I also helped in the development of Props & Drops, aka. TwitterProps, a Twitter application that uses this gem. So If you want to see it in action, give someone props (or drops) via twitter:
props @username for doing something cool
OR
drops @username for being a jerk
Go try it out!
DISCLAIMER: TwitterProps and twitter_bot only work when Twitter has their track feature enabled, which recently has been scarce…
RailsConf 2008
May 26th, 2008
I’ll be heading to RailsConf 2008 this week in beautiful Portland, OR. I can’t wait to be in one of my favorite cities again. Especially because I’ll not only be enjoying the city, but also learning from and interacting with the Rails community. If you’re going to be in Portland this weekend, then feel free to contact me.
This trip is brought to me by the awesomest rails development shop, Integrum! And if you see any of the other Integremlins there, say “Hi”, you never know what could happen. That’s what I did last year and now I get to work there building amazing Rails applications every day. Oh, and we have stickers.
GoRuCo 2008 Wrap-up
April 28th, 2008
As I stated in a previous post, I attended the Gotham Ruby Conference this past weekend in NYC. It was a great time with many interesting talks. The weather was amazing as well. I don’t want to spend a lot of time rehashing the conference because you can view the GoRuCo 2008 presentations for yourself, but I did want to mention a few things I got out of it.
Bryan Helmkamp gave an interesting introduction to story driven development using rspec and story runner. This is something we’ve been talking about at Integrum, but haven’t had a chance to use in a real setting yet. Derek and I got to spend some time at the WePlay offices (where Bryan works) and they showed us some of the stuff they’re doing, including using story runner. It was awesome to hear about their experiences and hopefully we’ll get a chance to use it soon.
Next up was “Archaeopteryx: A Ruby MIDI Generator.” I was skeptical about this one, but was blown away by Giles Bowkett’s presentation. From recounting his life adventures, including a “psycho throwing rocks at his dad until he threatened him with a piece of rebar” to calling venture capitalists “weasel-brained muppet fuckers… they’re not fools, they’re liars.” He kept the crowd well entertained, but threw in some really interesting and well-delivered points about startups and life. It is well worth watching.
Another one that really stood out was Ryan Davis’ presentation about “Hurting code for fun and profit.” He had a lot of really great things to say about being a developer, so go watch it already!
These speakers helped me to become aware of a few things:
- I don’t read enough. Ryan mentioned that the average developer reads 1 book a year. Is one book a month really so hard?
- I don’t hurt my code enough. I don’t use flog or heckle consistently and I often don’t take the time to correct code that I know should be improved.
I definitely have some things to work on… how about you?
Caching Locale-specific Dynamic JavaScript Files
April 23rd, 2008
I was recently inspired to create some cached, dynamic JavaScript files for a project I am working on after watching Ryan Bates Railscasts episodes 88 and 89.
The basic concept is to create a JavaScript controller that dynamically renders some JavaScript file(s). This allows you to take advantage of ERB in your JavaScript files. However, this can become slow as every request for that JavaScript file must be processed by Rails. In episode 89, Ryan showed how to cache the dynamic JavaScript file to improve performance. These episodes were great, except I had one problem… The dynamic portion of the JavaScript files I was working with were translated strings.
This meant that I couldn’t just cache the JavaScript file because the translation would need to be different based on the locale setting of the user. It turns out there’s a pretty easy solution to this. If you follow the lessons from the episodes then you will have a general caching mechanism for the dynamic JavaScript files. Assuming you are using a translation mechanism like Globalize then you have access to a locale for the current session. Simply use this locale when including the JavaScript file (e.g., dynamic_states):
Your layout file<%= javascript_include_tag "#{locale}/dynamic_states" -%>
This will try to include the dynamic_states.js file from the javascripts/locale directory where locale is something like en, es, zh, etc. The only other thing to do is define a custom route to handle this new pattern.
routes.rbmap.connect ':controller/:locale/:action.:format'
That’s it. You should now have locale-specific dynamic JavaScript files. For what I was working on, I also nested the locale directory within another directory (e.g., cache) just for ease of removal in case you need to wipe out the entire cache of dynamic JS.
Resources
GoRuCo 2008
April 15th, 2008
Next week I will be traveling to New York for the Gotham Ruby Conference courtesy of my favorite Ruby on Rails consulting company in Phoenix. I’ll be attending with Integrum’s resident Agile methodology expert. If you’re in NY or attending the conference, be sure to look us up – see my contact information.
Rails counter_cache problem
April 11th, 2008
I ran into a strange Ruby on Rails counter_cache problem today. Given the following example models:
class Poll < ActiveRecord::Base
has_many :poll_choices
has_many :poll_votes
end
class PollChoice < ActiveRecord::Base
belongs_to :poll
has_many :poll_votes
end
class PollVote < ActiveRecord::Base
belongs_to :poll, :counter_cache => :votes_count
belongs_to :poll_choice, :counter_cache => :votes_count
end
We want to ensure that the Poll maintains the total vote count. We also want the PollChoice to maintain the votes for that specific choice. In our controller we might be tempted to add a PollVote through either the Poll or PollChoice association with PollVote, but that’s where the problem appears.
It turns out that both of the following approaches will only update the votes_count for one or the other instance, but not both.
@poll.poll_votes.create(:poll_choice_id => @poll_choice.id)
OR
@poll_choice.poll_votes.create(:poll_id => @poll.id)
Instead, if we create the PollVote directly we will get the desired result of both the Poll and PollChoice having their votes_count updated appropriately.
PollVote.create(:poll_id => @poll.id, :poll_choice_id => @poll_choice.id)
Strange behavior or expected result?
Update: Another solution is to not assign using the ID, but instead assign using the object itself.
@poll.poll_votes.create(:poll_choice => @poll_choice)
OR
@poll_choice.poll_votes.create(:poll => @poll)
A quick test showed this worked as well. (Thanks Arya A)