<body><script type="text/javascript"> function setAttributeOnload(object, attribute, val) { if(window.addEventListener) { window.addEventListener("load", function(){ object[attribute] = val; }, false); } else { window.attachEvent('onload', function(){ object[attribute] = val; }); } } </script> <iframe src="http://www.blogger.com/navbar.g?targetBlogID=7625526986034013157&amp;blogName=Tim%2C+the+Enchanter&amp;publishMode=PUBLISH_MODE_HOSTED&amp;navbarType=BLUE&amp;layoutType=CLASSIC&amp;homepageUrl=http%3A%2F%2Ftim.theenchanter.com%2F&amp;blogLocale=en&amp;searchRoot=http%3A%2F%2Ftim.theenchanter.com%2Fsearch" marginwidth="0" marginheight="0" scrolling="no" frameborder="0" height="30px" width="100%" id="navbar-iframe" title="Blogger Navigation and Search"></iframe> <div></div>

About

I'm a ruby developer passionate about developing clean code that makes for programming happiness. I'm also am passionate about freedom, liberty, and capitalism, and enjoy jamming out some good rock or jazz on the piano.

I'm a family man and a I'm a member of The Church of Jesus Christ of Latter Day Saints (AKA the "Mormons") and I wield a strong testimony of my Savior Jesus Christ (yes we're Christians).

I'm currently employed by:

Universal Healthcare Tuesday, June 16, 2009 |

In response to those who claim that Universal Healthcare is our right because it promotes the general public welfare: I’m with you that there are some issues with our current health care system. But do you really thing that letting the government take it over is the way to go?

From my perspective it seems that less government interference (and less big pharma special interests group pushing policies that big them a leg up on others) would best promote the general welfare you speak of. Consider veterinarians. Or, contrast private and public health care service in any country that has implemented the scheme. Consider the benefits of competition.

It seems that placing it all in the hands of a bureaucracy would be much worse that what we have now: no accountability to produce and no competition to innovate = less health care available, less efficiency, and less (virtually no) medical advances. Also, why would you want to become a doctor, only to become a slave to what will sure to be a bureaucratic mess, especially one where your rights are considered to be inferior to those who are ill. Thus we lose the incentive to attract (and reward) the best talent.

I believe we have a right to choose whom to exchange with to acquire health care, and even to study medicine ourselves and provide for ourselves and our family healthcare. But, when we start to claim right to the fruits of the labor of others, we are on dangerous ground. We are only respecting freedom so long as it applies to us, and we are infringing on the blessings of liberty of those around us.

I believe we both have the same values and want to bless the lives of others – no-one wants more people to go hungry or sick. This is sincerely what I believe on the subject.

Thanks for sharing your opinion.

How to escape arguments in bash Friday, February 20, 2009 |

Today I was trying to write a convenience wrapper script that ran commands remotely on a server (for one of the people we work with). But, for some reason, ssh handles arguments in a completely suprising (and annoyingly inconvenient) manner that completely ignores quotes.

For example:

timcharper@timcharper:~ $ ssh my_server grep "4 5 6" ./
grep: 5: No such file or directory
grep: 6: No such file or directory

Grrr…. this made me feel ANGRY. Because of this, I couldn’t use the “$@” trick to splat all the arguments on the end and just move on with life. But it’s cool, because I’ve got a thick table to bang my head against, combined with an overly-aggressive problem-solving drive that won’t accept no for an answer.

So, I came across an awk trick to escape every character in a string, and another trick to iterate over arguments. Combining the two techniques did the trick, and I can now properly pass command line arguments through an ssh wrapper script. Since it depends on bash and awk, and bash and awk are on EVERY POSIX system out there, it’s a winner.

The working script:

#!/bin/sh
CMD=""

for (( i = 1; i <= $# ; i++ )); do
  eval ARG=\$$i
  CMD="$CMD $(echo "$ARG" | awk '{gsub(".", "\\\\&");print}')"
done

ssh my_server cd /path/to/app \&\& RAILS_ENV=production $CMD

Surprisingly, this is quite bullet broof, and properly escapes strings and preserves arguments like:

./remote.sh grep "hello there" . -R
./remote.sh grep "So I says to the typewriter, \"Hey, I'm in quotes\"" . -R
./remote.sh grep "\"" . -R

I wish somebody had posted a solution like this for me to find, so, here you go. If you came here looking for this solution, I probably saved you an hour of your life, and a lot of stress to boot. You’re welcome.

Have you ever wasted more than an hour on a trivial problem like this? Is there an easier way to do this?

The Most Rockin' Carpool Site on the Web Saturday, November 22, 2008 |

Introducing MyCarpoolRocks.com

This blog post marks the second launch party for MyCarpoolRocks.com, a ride sharing site so easy to use your 80 year old grandma could figure it out, and so awesome it’s going to be the talk of every college and work party.

Why ride sharing is awesome

For the past several months I’ve been actively pursuing ride sharing. My reasons are more economic than environmental (interestingly enough the two intersect here). Here’s why I think ride-sharing is awesome:

  • We (my wife and I) continue saving an extra car payment, and get along just fine with our vehicle which we’ve completely paid off
  • Save wear and tear on said vehicle
  • Lower monthly payment for auto insurance
  • Less gas money
  • The ability to be productive during my commute time (I’ve got a stomach of steel when it comes to getting car sick, my stomach is awesome!)
  • Opportunities to socialize with car-pool partners.
  • Helping to shrink government by being less dependent on government to make my transportation more cost effective. (OK, this will not be a political post)

Why I created a ride sharing site

Months ago when I was searching for a carpooling website to organize carpools in my church and community, and I found myself in Goldie Locks’ shoes, except the baby cub spit in his porridge and wet his bed. I couldn’t find a carpooling site that was “just right” – one I could recommend without any reservations. They were either difficult to figure out, or it was difficult to modify your commute once you’ve recorded it, or protect your privacy without listing your house as 5 miles away, or required WAY TOO MUCH information to sign up.

I don’t pretend to be so smart that I can create the perfect carpooling site, but I decided I was certainly going to try. I started out with these objectives in mind:

  • Any user must be able to INSTANTLY understand the tool
  • The sign up form should be as short and quick as possible (no email verifications!)
  • It should be fun
  • It should use be very visual (IE – if you can convey the information visually on a map, or control input visually without using a drop down box, do it)

How I built MyCarpoolRocks.com

I used the following libraries / gems

  • open_id_authentication (with ruby-openid) – providing services to authenticate against open id servers. This plug-in is FANTASTIC.
  • restful_authentication – very great plugin by technoweenie to handle user authentication.
  • gravatar – Does the job to display user gravatars on your site.
  • indicator – indicator helper methods and javascript.
  • recaptcha – Put recaptcha’s on your website. Worked great!
  • rspec and rspec story runner to test.
  • uber-builder – A fine form builder library. Render the same form partial as a static form and get your view for free. Supports various layout styles like tables, ul / li, etc. and does not get in your way.

Other:

  • To host, I got a Linode slice. They’ve been really great so far.
  • Bought the domain from http://danggood.com/
  • I made heavy use of rails ActiveRecord named_scopes. Man they are awesome.
  • As for Google maps, I coded straight against their JavaScript API. I wrote a resizable rectangle control for Google Maps even (contact me if you’re interested in it). Google Maps’ API is very awesome and does not need any Ruby on Rails helpers to work with maps.

Lessons Learned (so far)

User case studies are KING

I can’t tell you how important this is: after you implement any idea, find somebody who has never seen what you’ve been working on, and preferably is not well acquainted with what you have been doing. Watch them try to go through the site, take notes on what confused them, and try to see things from their point of view as they are stumbling through it. Resist the urge to help them, unless they get totally frustrated. Just sit back and quietly observe. Then, take feedback by the shovel-full.

After EXCRUCIATING user testing from my good friends and family (thanks, you guys so rock), I was able to iron out some pretty serious road blocks that would not have even been aware of otherwise.

Don’t fall in love with your own ideas

Your love affair with your ideas will almost inevitably lead to failure. Why? Because we all have blind spots, and it often takes the collaboration of several minds to get a clear picture.

When you get feedback from your user case studies, don’t be afraid to throw away code, or completely rearrange or restructure things.

For example: at first, the sign up process consisted of two parts: “search for matches” and “register your commute”. I really liked it that way – it provided flexibility. I even had the search address being stored in a session and auto-populating in the commute registration form.

When my tester got very confused, and couldn’t understand why she was being asked for her address twice, I was tempted to explain to her why it was so awesome that way. Instead, I sought to understand her point of view. Her view was more enlightened than mine, and I saw that the flexibility I as in love with was ultimately wasn’t adding value but detracting from it by complicating things. The refactoring was painful, but was also one of the greatest improvements I’d made since the first prototype of the site.

Be an information elitist

Don’t be afraid to scrap things – put every piece of information on trial, especially when you are asking your user for information: are you needed to get the job done, is your existence warranted? Persecute without mercy.

Make a clear path for the user that involves sign up.

I believe you’ve got to guide a user down a path that leads them to sign up. In my first launch attempt, I just showed a search form and let them search. Not wanting to force people to register, people got on the site, searched, and said “oh, that’s cool”. Then they missed the tiny “add your commute now!” link and closed their browser. Gone, probably never to return again.

Conclusion

Building MyCarpoolRocks.com has been a fun and rewarding. I hope it gets to live up to its potential and create widespread value in my community wherever it finds itself getting heavy use.

Feedback and criticism in the spirit of peer review is most welcome.

How to has_many :through a has_many :through Thursday, October 2, 2008 |

So, I’ve got 3 models:

  User -< UserConversation >- Conversation -< Message

  (where -< is has many, >- is belongs to, ... etc)

I wanted, in this application, to be able to filter to all messages for a given user.

  User#messages.find(message_id)

So, naturally, I first reached for this:

  class User < ActiveRecord::Base
    ...
    has_many :user_conversations
    has_many :conversations, :through => :user_conversations
    has_many :messages, :through => :conversations
  end 

  class UserConversation < ActiveRecord::Base
    belongs_to :user
    belongs_to :conversation
  end

  class Conversation < ActiveRecord::Base
    has_many :user_conversations, :dependent => :destroy
    has_many :messages, :dependent => :destroy
  end

  class Message < ActiveRecord::Base
    belongs_to :conversation
  end

Which… is completly WRONG and yields results like the following:


  >> User.first.messages

  ActiveRecord::StatementInvalid: SQLite3::SQLException: no such
  column: conversations.user_id: SELECT "messages".* FROM "messages"
  INNER JOIN conversations ON messages.conversation_id =
  conversations.id    WHERE (("conversations".user_id = 1)) 

So, apparently ActiveRecord doesn’t support joins like that. Sure, I could resort to manually specifying the finder_sql in the join and skip the has_many :through business, but then I’d lose the that cool ability to apply additional scopes after this – major FAIL.

So, I came up with a clever way to get around it.

  class User < ActiveRecord::Base
    ...
    has_many :user_conversations
    has_many :conversations, :through => :user_conversations

    def messages
      Message.for_user(self)
    end
  end

  class Message < ActiveRecord::Base
    belongs_to :conversation
    
    named_scope :for_user, lambda { |user| user = user.id if user.is_a?(User); { :joins => {:conversation => :user_conversations}, :conditions => ["user_conversations.user_id = ?", user]}}
  end

And… now we can do things like:

  user.messages.find(1)
  user.messages.matching_subject("boogy man")

etc., etc. Hurray for named_scope. So.. there's still a few issues. Namely, it's not REALLY an association - no "create" or "build" methods.

Dear web: what do think about this? Got a better way to implement the above scenario?

Labels:

Now we know they're lying Sunday, August 24, 2008 |

Autoscroll in Safari, Firefox Saturday, August 23, 2008 |

The Autoscroll Bookmarklet

Bookmarklets are actually a cool little concept – make a link that runs a JavaScript command and inject code into any web-page. Brilliant! Combine this with an obsessive computer nerd with some free time on a Saturday evening (for example, me), and you get following:

AutoscrollThe Bookmarklet

Works in Safari and Firefox. If you’re lucky it might work in Opera, Camino, and Konqueror. If you’re at least as lucky as this guy, it might work in IE.

Usage

Click the really big link above to activate auto-scroll (you may want to make your window small enough to have significant scroll space

Here’s the buttons to push:

0-9 : Set scroll speed, 0 being stand-still and 9 being skim-speed
: Decrease speed
= : Increase speed
shift + – : Decrease speed quickly
shift + = : Increase speed quickly
escape : Quit

Installation:

If you’d like to pack this sweet action with you, drag the “Autoscroll” link to your bookmarks tool bar.

How to Daemonize Any Process |

I’ve been passively looking for a tip like this for a while. Often times, I’ll need to run a command on a server that takes a good 30 minutes to run (like loading a database dump for example). Normally, I’ll run the command in the background, followed by this:

while true; do sleep 60; date; done

This has been my timeout prevention to keep commands from dying – yes it’s a pretty stinking lame solution.

Especially lame when the server drops the connection anyways.

nohup saves the day

If you need to run a REALLY long command remotely that won’t die with an SSH time out, then “nohup” is your friend.

nohup shields the commands from “HUP” signals – a signal that is sent to all child processes upon disconnecting from a terminal, that normally will stop your process (gracefully).

For example:

nohup cat the_entire_internet.sql.bz2 | bunzip2 | mysql the_internet_production &

And then, nohup will probably say something like "nohup: ignoring input and redirecting stderr to stdout", but it’s of little consequence. You’re safe to quit your terminal and your process will be safely fostered by /sbin/launchd after you take it’s parent away. Ya big mean lug.

Tim, the Enchanter

"What manner of man are you that can summon up code without C# or Java?"

Open Source