has_much :confusion, :about => "string #{interpolation}"

Posted over 7 years back at zerosum dirt(nap) - Home

No matter how flexible ActiveRecord’s associations become, there’s always going to be a time when you want to override it’s baked-in smarts with your own custom SQL query. Fortunately, we can do just that with the :finder\_sql option. Use it to manually specify the association that should be returned.

There’s one gotcha to be aware of though: if you need to do any variable interpolation in the string (and you most likely will), make sure to use single quotes instead of the usual doubles:

has_many :transfers, :finder_sql => 
  'SELECT * FROM transfers ' +
  'WHERE sender_id = #{id} or receiver_id = #{id}'

When you use double quotes, the string interpolation happens immediately (when the class is first loaded), thus obtaining the object ID of the class in memory. Using single quotes, the interpolation occurs within the context of your object instance, which is what you’re expecting.

Handling *the* four letter words

Posted over 7 years back at work.rowanhick.com

The boys over at 37signals have put the danger flag up over the following words. Need, Must, Can’t, Easy, Just, Only, Fast. The following comments thread has been an interesting read. But it does highlight what to do about when you hear these words, and whether they necessarily are bad. I tend to think of them as helping you, the business analyst, or developer, to extract exactly what the client wants to acheive. Harking back to the general philosophy that a client/user (be it a your paying client, your designer, your developer) just wants to get things done, when they can't the frustration level can start to increase and you start to see these words - by the time you personally get involved things might be getting a little heated... So, what do they really mean ? And how do we deal with it ? Take the case of our proverbial user. Our user is tring to do something, our system is (hopefully) helping them to do this but along the way, boom, somebody can't get past step Y, because it won't let them enter x. The following call is made "why can't it just do this..." so what's wrong here ? Well... maybe the original developer for not figuring out the requirements, or maybe the business model has changed. Either way our poor end user has gotten stuck. And we need to fix it for them. It's a mindset shift all dependent on your audience - sure you can continue down the Mr UnPleasant road and not deal with it. However, if you're an enterprise system where things have to get done, no matter what. Then simple, get down to business. If you're running a public web app with a wide audience you've got a tough decision on your hands to make. So what do they really mean? "I just need it to do X, I can't complete my task" [translation: I'm trying to do something, I know what I want to do, and I think I know what the software needs to do in order for me to do it.. so I'm telling you what you need to do, I think this will speed up the process if I express it to you like this] First off, before saying yes or no, it's part of my job to figure out what they actually need. Nearly always I ask these key questions. 1. "What are you trying to acheive?" 2. "What's the steps they took to get to X, so I know context" 3. "How did you do X before today ?" 4. "If in a perfect world, what would your preferred way of doing this.. " All of the above should provide a gold mine of information in helping you to design the best solution, and to work out whether it is really needed, or a work around can be provided. Okay so after a bit of backwards and forwards figuring out what they want to do, and the best solution we've realised that our 'please just do this' is a bit of a kicker, we've got tonnes of code to rewrite (unless you're rolling on rails of course!). So do we go straight back to our office and start coding. No. Not yet. You now explain to the user what you've got planned out in the next short term, all of which will be impacted by this change, and then how long the change will take. Ie "we'll I'm currently working on the new inventory feature, which I have 3 weeks left for. if I implement this it will take probably 1 week" and ask the really important question "What do you want me to work on ?" You will be suprised how often the decision won't be this 'critical urgent' problem that was just raised. Now, if you get the do it now, do everything else you're working on, and I don't give a damn type attitude there are two ways to handle it. One involves lots of this stuff and all nighters, the other involves giving them a business card of your competitors. Problem solved, go off and find a client who values your relationship. Going back to wether those word's are dangerous, in my world no, it's just a way of expressing a need. I think the occurence of those words is inversley proportional to the happiness of our client - a good system that is returning value and have content users will see very little of these. A system constantly hindering our users workflow will see a tonne of those words.....

Revolution Health Traffic Doubles in 4 Weeks

Posted over 7 years back at Revolution On Rails

Hitwise has recently publish traffic statistics on our growth over the past month.

This Wednesday AOL Founder Steve Case spoke at D5 about his new venture, Revolution Health. Revolution Health is setting out to be far more than just a health information source on the web, but it is already succeeding on that front. For the week ending May 26, 2007, Revolution Health was ranked #11 in the Health & Medical - Information category, and traffic increased by 113% since the week ending April 28, 2007, when it was ranked #23.

Revolution Health Traffic Doubles in 4 Weeks

Posted over 7 years back at Revolution On Rails

Hitwise has recently publish traffic statistics on our growth over the past month.

This Wednesday AOL Founder Steve Case spoke at D5 about his new venture, Revolution Health. Revolution Health is setting out to be far more than just a health information source on the web, but it is already succeeding on that front. For the week ending May 26, 2007, Revolution Health was ranked #11 in the Health & Medical - Information category, and traffic increased by 113% since the week ending April 28, 2007, when it was ranked #23.

Episode 40: Blocks in View

Posted over 7 years back at Railscasts

If you try to create a helper method which accepts a block, you will run into a few gotchas. Learn the secrets of blocks in views in this episode.

Ruby vs. JRuby - The path to consistent behavior + OpenSSL

Posted over 7 years back at Revolution On Rails

In Ola Bini's recent post There can be only one, a tale about Ruby, IronRuby, MS and whatnot, he stresses the importance of documenting Ruby's API so that other implementations can match MRI's behavior. I have to strongly agree. We've recently been bitten by this, which I'll outline using OpenSSL as an example.

Ruby's OpenSSL library does not strictly enforce a ciphers's initialization vector (IV) size specification. It simply truncates to the appropriate size.

Ola's JRuby OpenSSL library (which is awesome btw!) leverages the Bouncy Castle's JCE implementation which strictly enforces IV specifications.

Below is a simple example that works fine on MRI, and fails on JRuby.

require 'openssl'
text = "abc123"
cipher = OpenSSL::Cipher::Cipher.new("des-ecb")

#The DES Cipher specifies a length of 8 bytes, the below IV exceeds that
key, iv = "1234567890", "1234567890"

cipher.encrypt
cipher.key, cipher.iv = key, iv
encrypted = cipher.update(text) << cipher.final

cipher.reset
cipher.decrypt

#I double the length of the cipher here, just to prove that MRI truncates it.
cipher.key, cipher.iv = key*2, iv*2
decrypted = cipher.update(encrypted) << cipher.final
puts "#{text} == #{decrypted}"



> jruby test_openssl_iv.rb
java.security.InvalidKeyException: DES key too long - should be 8 bytes
at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(Unknown Source)
at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(Unknown Source)
at javax.crypto.Cipher.init(DashoA12275)
at javax.crypto.Cipher.init(DashoA12275)
at org.jruby.ext.openssl.Cipher.doInitialize(Cipher.java:416)
at org.jruby.ext.openssl.Cipher.update(Cipher.java:432)

> ruby test_openssl_iv.rb 
Result is: abc123 == abc123



Yes, this is obviously an edge case, and one could argue that the Java implementation is more correct than MRI's, but the goal is any piece of code should run the same on either platform.

Charles Nutter (Headius) has started a RubySpec Wiki where I've noted this issue there.

I've submitted a bug against JRuby to track the issue, but arguably its not a JRuby bug. Its a difference between BouncyCastle and SSLeay's implementation. I'd be interested in some community feedback on how to correctly implement this. For now, we've worked around this by simply truncating if the RUBY_PLATFORM =~ /java/, which I know if horrible, but it allows me to move on.

Ruby vs. JRuby - The path to consistent behavior + OpenSSL

Posted over 7 years back at Revolution On Rails

In Ola Bini's recent post There can be only one, a tale about Ruby, IronRuby, MS and whatnot, he stresses the importance of documenting Ruby's API so that other implementations can match MRI's behavior. I have to strongly agree. We've recently been bitten by this, which I'll outline using OpenSSL as an example.

Ruby's OpenSSL library does not strictly enforce a ciphers's initialization vector (IV) size specification. It simply truncates to the appropriate size.

Ola's JRuby OpenSSL library (which is awesome btw!) leverages the Bouncy Castle's JCE implementation which strictly enforces IV specifications.

Below is a simple example that works fine on MRI, and fails on JRuby.

require 'openssl'
text = "abc123"
cipher = OpenSSL::Cipher::Cipher.new("des-ecb")

#The DES Cipher specifies a length of 8 bytes, the below IV exceeds that
key, iv = "1234567890", "1234567890"

cipher.encrypt
cipher.key, cipher.iv = key, iv
encrypted = cipher.update(text) << cipher.final

cipher.reset
cipher.decrypt

#I double the length of the cipher here, just to prove that MRI truncates it.
cipher.key, cipher.iv = key*2, iv*2
decrypted = cipher.update(encrypted) << cipher.final
puts "#{text} == #{decrypted}"



> jruby test_openssl_iv.rb
java.security.InvalidKeyException: DES key too long - should be 8 bytes
at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(Unknown Source)
at org.bouncycastle.jce.provider.JCEBlockCipher.engineInit(Unknown Source)
at javax.crypto.Cipher.init(DashoA12275)
at javax.crypto.Cipher.init(DashoA12275)
at org.jruby.ext.openssl.Cipher.doInitialize(Cipher.java:416)
at org.jruby.ext.openssl.Cipher.update(Cipher.java:432)

> ruby test_openssl_iv.rb 
Result is: abc123 == abc123



Yes, this is obviously an edge case, and one could argue that the Java implementation is more correct than MRI's, but the goal is any piece of code should run the same on either platform.

Charles Nutter (Headius) has started a RubySpec Wiki where I've noted this issue there.

I've submitted a bug against JRuby to track the issue, but arguably its not a JRuby bug. Its a difference between BouncyCastle and SSLeay's implementation. I'd be interested in some community feedback on how to correctly implement this. For now, we've worked around this by simply truncating if the RUBY_PLATFORM =~ /java/, which I know if horrible, but it allows me to move on.

Hobo Sightings

Posted over 7 years back at The Hobo Blog

Hi folks, sorry to be a bit quiet of late. Just thought I’d update you with a few bits and bobs from the Hobo world.

There’s been a few interesting sightings of Hobo out there. By now you’ve probably seen Dr Nic’s myconfplan, which uses Hobo. I’ve been meaning to ping some questions over to Dr Nic about the experience of using Hobo in that app, so hopefully that’ll be a blog post soon.

If you’ve paid attention to RailsConf, you may have noticed that a very tiny corner of Hobo – the compact create_table migration syntax – has found it’s way into core Rails. It seems DHH came across the “Sexy Migrations” post on err the blog. Nice!

The guys over at Bugzilla have taken a look at Hobo as one option (of many!) for a new implementation of Bugzilla.

Niko Dittmann will be doing a presentation on Hobo at the German language Rails Konferenz (German language link, here’s the hilarious automatic translation)

Meanwhile I’m hoping to get my proposal accepted for a talk on Hobo at RailsConf Europe.

Behind the scenes things are very busy at Hobo Central. We have a ton of client work on, all of which will be pushing the quality and feature-set of Hobo along in leaps and bounds. And of course, all this professional work puts HoboTech Ltd. on a sound financial footing, so the Hobo project will continue to be very active for the foreseeable future.

Good times!

Hobo Sightings

Posted over 7 years back at The Hobo Blog

Hi folks, sorry to be a bit quiet of late. Just thought I’d update you with a few bits and bobs from the Hobo world.

There’s been a few interesting sightings of Hobo out there. By now you’ve probably seen Dr Nic’s myconfplan, which uses Hobo. I’ve been meaning to ping some questions over to Dr Nic about the experience of using Hobo in that app, so hopefully that’ll be a blog post soon.

If you’ve paid attention to RailsConf, you may have noticed that a very tiny corner of Hobo – the compact create_table migration syntax – has found it’s way into core Rails. It seems DHH came across the “Sexy Migrations” post on err the blog. Nice!

The guys over at Bugzilla have taken a look at Hobo as one option (of many!) for a new implementation of Bugzilla.

Niko Dittmann will be doing a presentation on Hobo at the German language Rails Konferenz (German language link, here’s the hilarious automatic translation)

Meanwhile I’m hoping to get my proposal accepted for a talk on Hobo at RailsConf Europe.

Behind the scenes things are very busy at Hobo Central. We have a ton of client work on, all of which will be pushing the quality and feature-set of Hobo along in leaps and bounds. And of course, all this professional work puts HoboTech Ltd. on a sound financial footing, so the Hobo project will continue to be very active for the foreseeable future.

Good times!

Episode 39: Customize Field Error

Posted over 7 years back at Railscasts

When a validation error occurs, Rails helpfully wraps the field in a div tag so you can style it. But sometimes you don't want this behavior. In this episode you will see how to customize it.

Roundtable: Women in Development - Ruby on Rails Podcast

Posted over 7 years back at Ruby on Rails Podcast

Jen May Wu, Dr. Ana Nelson, Liz Summerfield, Sandy Metz, Carmelyne Thompson, Cynthia Kaiser, and Desi McAdam discuss the state of women in open source programming.
Relevant links:

Caught In The Act

Posted over 7 years back at zerosum dirt(nap) - Home

Wow, Google Street View is totally great. And, as expected, some funny shit gets frozen in time at street level. Google is watching! Be cautious where you go, what you do! Try to remain calm, don’t lose your head over it.

Good to Great (rules to live by)

Posted over 7 years back at work.rowanhick.com

What makes a great developer ? Outside of obligatory technical and problem solving skills which go without saying, the differentiator between good developers and great developers I think simply boils down to understanding, empathy and respect for your client. Having a cross functional developer that can write code and talk to a client in plain english is an amazingly huge (and seemingly rare) asset to any team or studio. As the world slowly moves away from waterfall development I think this is going to be increasingly important. I've worked with the uber algorithm generator russion rocket scientists, the fresh out of university bumbling junior guy, the know it all with an ego the size of africa, the one that wants to debate every minute detail until they forgot why they were debating it, the one that will fight to the death to not change the feature they just implemented. Every time the one developer that's stood out, and had clients want to work with them, were those that sat down and understood the business problem at hand and were empathetic to their clients needs. If you spend those hours/days up front and actually listen to your client. Put yourselves in their shoes, and understand how they do business and want to do it better. You are going to go a lot further than those who tell the customer how to do business. Here's my rules to live by: 1. Mr/Ms Pleasant. It doesn't matter what business you are dealing with, people unless they like being antagonised, will actively avoid dealing with an unpleasant person. I have a bike store by my house, it's got everything, it's convenient, but if I have to deal with the mechanic once more.... so I use the bike store close to work. Inconvenient, pain in the proverbial, the kids are way less experienced but I'd much rather deal with an 18yr old kid who's eager to please, than the 40 yr arrogant sod who has no time of day for you (I have no time of day giving him my hard earned cash). I'm sure we've all had those experiences no ? Now multiply that $50 purchase in the bike store a good 200-2000 times into a big scale web project. Who's the customer going to pick, Mr/Ms Pleasant or Mr/Ms Arrogant. 2. Mr/Ms Understanding. Understand the business problem at hand, and make an effort to understand the wider context of the business. Don't try and get the full story in the nth degree on the first meeting - you'll be there for days, however everytime you meet again, always try to get a bit more business knowledge in the wider context of the business. The more domain knowledge you have about the customer's business the easier it makes your job, the more valuable you become. 3. Mr/Ms Talker. Talk with your customer.... just because you and everyone around you uses email for everything, it's not necessarily a good thing. You get so much more out of talking and more importantly listening than you ever will on email - the hesitant pauses (.. maybe not a good idea to work on this functionality, they're unsure), the excited yes please (.. get it delivered straight away they want it!). I tend to talk or meet face to face, then follow up with an email restating the items to be actioned, priorities etc. Everytime I've relied solely on email it's been a disaster. And with any important business dealings (ie you get the contract, you've been paid, major milestone etc). Talk on the phone then follow up with an email - it shows respect. 4. Mr/Ms Restater. As part of number 3, to show your understanding of a problem, always restate it, multiple times if need be. It's like learning your ABC's. It a) shows you know and understand it, b) gives the customer a chance to rethink it through, see if it makes sense. Use role play "Okay, so I'm your business store owner, at the start of the day I go to my computer, fire up the browser, go to... I'm the region manager, at the end of the day I do..". You've got to have personal confidence of knowing the problem and your customer has to feel happy you can go away and put together a solution. Nothing's worse than giving a task to someone who has that semi nervous 'yeah.. sure, okay, i'll be back in touch'. I rarely need to refer to notes as I make an effort to understand the problem. 5. Mr/Ms Light. Don't go dark. No matter what.. don't go dark. It's the standing joke of feeding the pizza under the door and waiting for something to come out the other end (and waiting.. and waiting). The customer gets worried, you go off on a tangent it all turns to custard. Keep in touch. Even if it's just an email 'Just to touch base I'm working on aspect x. I expect to have it sorted in 3 days, I'll send you a screenshot then'. It also keeps you top of their mind, and them top of your mind. 6. Mr/Ms Nicely No. Say no carefully. If something's a bad idea, no with a smile and say why you're saying no. Remember Mr/Ms Pleasant ? ... The customer is paying the bills so be careful with this one. The customer is always right can be rephrased as: The customer is nearly always right in terms of what they want to acheive - but doesn't have experience in execution so often need to be guided. 7. Mr/Ms Goal Oriented Understand the stated goals and objectives. Extract these from the client before you run down the path of looking at the functional elements of your task. If you don't know what you're trying to acheive how can you write the steps to get there ? The customer often will express what they want by how they want to acheive it e.g. "add this button here, make it go to this page, then ask the user for this" vs "We want the user to give us their address information before entering the site" 8. Mr/Ms Humble Know when you're wrong, face up admit it and move forward. Unless you're facing a law suit then talk to your lawer don't listen to me! It seems obvious but it's the hardest thing to do, especially the later in the game it gets. Finally... Remember you're an expert in your field, they're an expert in theirs. Respect, understanding and an empathetic relationship will take you a lot further with your dealings, and will help to garner you more business and referrals. The cool toys like Flex, Rails, Ajax, etc all just help you along the way. Be the dude/dudette that either a client, or a project manager says "This person is fantastic, you should work with them"

Managing database.yml with Capistrano 2.0

Posted over 7 years back at Shane's Brain Extension

Jeremy Voorhis posted a really great Capistrano recipe for managing database.yml which dynamically creates a database.yml file in your shared directory on setup, and symlinks your app’s database.yml once it’s deployed. This is great if you don’t version control your database.yml file for security reasons or working with multiple developers.

changes the syntax for task callbacks and gets rid of the useful render method.  However, using ERb, Ruby's built-in templating system, isn't much more difficult than using the old render method.  Here is Jeremy's script updated for Capistrano 2.0 using ERb and the new namespaced callback syntax.
require 'erb'

before "deploy:setup", :db
after "deploy:update_code", "db:symlink" 

namespace :db do
  desc "Create database yaml in shared path" 
  task :default do
    db_config = ERB.new <<-eof base:><<:><<:><<:>

Until I get better syntax highlighting for this blog, check out the Pastie for the color version. For more info on whats new in Capistrano 2.0, check out Jamis’ preview and Geoff’s post. Also, props to Jamis for suggesting I use ERb directly.

Update: Updated code to use its own :db namespace instead of the default one. The database yaml file will be created by the default :db task, and the symlink will be created by the db:symlink task. Note how namespaces in Cap 2.0 allows us to have two symlink tasks, one in the deploy namespace and the other in db.

Managing database.yml with Capistrano 2.0

Posted over 7 years back at Shane's Brain Extension

Jeremy Voorhis posted a really great Capistrano recipe for managing database.yml which dynamically creates a database.yml file in your shared directory on setup, and symlinks your app’s database.yml once it’s deployed. This is great if you don’t version control your database.yml file for security reasons or working with multiple developers.

changes the syntax for task callbacks and gets rid of the useful render method.  However, using ERb, Ruby's built-in templating system, isn't much more difficult than using the old render method.  Here is Jeremy's script updated for Capistrano 2.0 using ERb and the new namespaced callback syntax.
require 'erb'

before "deploy:setup", :db
after "deploy:update_code", "db:symlink" 

namespace :db do
  desc "Create database yaml in shared path" 
  task :default do
    db_config = ERB.new <<-eof base:><<:><<:><<:>

Until I get better syntax highlighting for this blog, check out the Pastie for the color version. For more info on whats new in Capistrano 2.0, check out Jamis’ preview and Geoff’s post. Also, props to Jamis for suggesting I use ERb directly.

Update: Updated code to use its own :db namespace instead of the default one. The database yaml file will be created by the default :db task, and the symlink will be created by the db:symlink task. Note how namespaces in Cap 2.0 allows us to have two symlink tasks, one in the deploy namespace and the other in db.