At work we have to go through a proxy to get to the outside world. So every time I take my laptop home I need to switch the proxy setting on my browser. Lame. Surely there is some sort of Firefox plugin to help me with this tedious task.
And there is. But Foxyproxy isn't it.
It's crazy heavyweight and unpredictable. The heavyweight part is that you can define different proxy settings and each of those settings can have white and black lists (with wildcard or regex matching) that decide whether or not to use a proxy. Or you can mix and match proxies for different sites. All that I could live with, but I just spent a few hours tracking down a bug that didn't exist because of Foxyproxy's weirdness.
The feature I was working on involved calling out to an outside system. But the browser just spun and spun when I tried it. After a LOT of time spent talking to people about the right configuration for this 3rd party system I guessed that just possibly this was a proxy issue and uninstalled Froxyproxy (and used Firefox's built in proxy system). And it worked like a charm.
I went back and looked at my settings for Foxyproxy and I couldn't for the life of me see how it wasn't using the proxy to connect to the third party system. And yet it was ignoring the proxy for this one call and one call only. Very hard to debug, as it's one of the last things you'd expect to stop working.
My coworkers are saying good things about SwitchProxy, but I'm a little bit skittish after getting burned on this.
At work we have to go through a proxy to get to the outside world. So every time I take my laptop home I need to switch the proxy setting on my browser. Lame. Surely there is some sort of Firefox plugin to help me with this tedious task.
My latest story card is all about getting our app to send email so I’ve had to delve into ActionMailer. It’s a cool way to send emails without tons of code but there are some things that are a little bit wacky. Let us say that you’ve got a cookie website and you want people to be able to send emails of their favorite recipes to each other. “My that’s a handsome cookie” they might say and “Oh look, an email button that lets me send this recipe to a friend. This site has met my needs exactly.” In order to get such a thing to happen you would create a RecipeMailer model that extended ActionMailer kinda like this:
class RecipeMailer < ActionMailer::Base
@from = email_params[:from]
@recipients = email_params[:recipients]
@subject = email_params[:subject]
@sent_on = email_params[:sent_on]
@body[:recipe] = email_params[:recipe]
In your controller you’d call:
And some good old method_missing magic would match deliver_recipe_email with your recipe_email method which would then render a view.
Er, a view?
That’s right, the email templates are rhtml views. You write them as you would a view, but ActionMailer turns them into emails. So one might look like this:
Here’s a recipe you might like:
<%= @recipe.text %>
And Rails would of course evaluate the <%= stuff like it would in a view. But, although it’s a view, it doesn’t have access to any helper methods you have defined, even if you put them in ApplicationHelper (which are supposed to be available to all views). You’ll have to declare this in your RecipeMailer model if you want the view to see them.
Another thing to watch out for is any links you include in your email must have the full path to your app. When using link_to you can pass in these options:
:only_path => false, :host => @host
Where host is the host you get off of request.host but you won’t have access to request in your view or your mailer, so you’ll have to pass it in from your controller (again, the email template is only sort of a view). But if you’ve added some fancy custom tags (like a hypothetical recipe_image_tag that takes in a recipe object and does all sorts of neato stuff) you might find that the combination of needing a full path and being rendered by an email client (ie not your rails app) will force you to, sigh, hack up your own links like so:
<img src="http://<%= @host -%>/images/logos/<%=@cookie_name-%>.png"
Not the prettiest code I’ve ever written but sometimes time is a factor.
We’re using an open source java app to help with searching on my current project and when I start it up (through cygwin – must… stop… developing… in… windows…) it throws up a bunch of stack traces. The first time I saw this I thought “holy crap, I must have configured it wrong.” And I was right. But then I configured it correctly and I was still getting a few stack traces on startup. I spent an hour or so trying to fix the problem before I remembered that lots of times a Java app will thow some errors at ya just for fun and I started up the rails app, navigated to the search, and it worked fine. Nice. So I just learned to ignore those stack traces.
Can you see where this is going?
Yep, later the search stopped working in a spectacular way that took down the whole app. Except I wasn’t sure it was the search breaking it. And I lost a bunch of time because I was ignoring the errors that were telling me something was wrong. They were different errors than the usual ones, but I was so used to hitting enter and watching a big stream of stuff fly by that I didn’t look at it.
Errors that are not critical errors need to be stuffed in a log file. Otherwise you’re training your users to ignore your output. Take a look at how Mongrel starts up:
A few lines and no random crap. Want to know the details? There’s a log file for that.
** Starting Mongrel listening at 0.0.0.0:3000
** Starting Rails with development environment...
** Rails loaded.
** Loading any Rails specific GemPlugins
** Signals ready. INT => stop (no restart).
** Mongrel available at 0.0.0.0:3000
** Use CTRL-C to stop.
Neal Ford has been having similar problems with garrulous software.
At my current gig I develop on Windows while the rest of the team is working on Linux (but not for long, I just got PartitionMagic and I’m going to dual-boot). This has caused several problems and one of the most vexing is that the Linux dudes can check in fixtures that blow up on my Windows box. Every time it happens I take a look at the offending fixture and it isn’t putting something into a column that has been declared ‘not null.’ So I fix it by adding in some data, but why the hell isn’t it blowing up on their machines (or cruise control, which is on a Linux box)? My colleague Ricky Lui figured it out today. Allow me to quote from his email:
On our Linux machines, MySQL is installed with no default sql_mode. That means
if there's a certain column that's supposedly NOT NULL, your unit tests can
still pass even without setting that column (e.g. through test fixtures).
For MySQL installation on Windows, the default sql_mode is set, so that same
unit test that passes on a linux machine will fail on Windows.
I think it's a good idea to let MySQL catch more errors for you. You can
view and set your sql_mode:
mysql> SELECT @@global.sql_mode;
mysql> SET @@global.sql_mode = traditional;
As per http://dev.mysql.com/doc/refman/5.0/en/server-sql-mode.html, the
'traditional' mode is ' "give an error instead of a warning" when inserting
an incorrect value into a column.'
Nice job Ricky.
I’ve got some bad new for ya. I know you’ve been reading this blog picturing me as some handsome muscled young stud -- but I am not. I’m fat and 35 and all muscle has left since I stopped working out about 5 years ago. What happened? Who cares – what I wanna talk about today is how every waiter is trying to kill me.
As a traveling consultant I tend to eat out 3 meals a day while I’m on the road. And in order to lose some weight I thought I’d just stop getting side dishes. Hamburger – no fries. Pasta – no garlic bread. Whatever it comes with -- I don’t want it. This is very hard for waitstaff. Here’s a conversation I’ve had about a thousand times:
Me - “I’ll have the French dip, but I don’t want any sides”
Waiter - (confused pause)
Waiter – “You don’t want… Would you like to substitute something else for the fries?”
Me – “Nope. Just the French dip is fine.”
Waiter – (weirded-out pause) “Um… Okay.”
15 minutes later
Waiter – “Here ya go.”
Me – “I thought I ordered no sides, but there are fries covering half the plate.”
Waiter – “I guess the cook just put them on anyway. You don’t have to eat ‘um”
Oh sure everybody says you should throw out the prototype after you make it, but look at all that yummy code just waiting to be used. Sure you wrote it fast and without tests – but it took a lot of work and it would be silly not to just use it as the base of your real project. Brush it off, clean it up a little, and it’ll be fine.
Don’t do it.
First of all it’s not fine. Code written without the threat of production tends not to be good. But let’s pretend you did write some nice code (you didn’t but this is pretend time). Now you’ve got huge chunks of untested code floating around that looks like it does stuff but actually is just left over from the prototype. Joe dev comes along and tries to write some functionality and he comes across a bunch of prototype code. It’s really confusing. It’s doing all this stuff. Stuff that doesn’t seem to work like he thought the app was supposed to work… Huh. “Oh well, I guess that’s how they want it done so I better follow along.” he thinks. Or maybe there’s a bug and he’s looking through code to see what’s going on. It’s not a lot of fun to realize you’ve spent a few hours rummaging around dead code. Or the case of the new functionality that seems to already be done. Just a little bit of hacking and it IS done. “Except for those extra methods that I couldn’t figure out… Better just leave it ‘cause they must be important.”
It may seem silly to keep the prototype separate from the real project, especially if you’re going to be referring to it all the time. I don’t care if you do end up copying and pasting much of the prototype into the real code as you add functionality. At least this way every line you add is a conscious decision. There’s less chance of your code becoming a way confusing combination of used and unused, polished and unpolished, tested and legacy.
Awhile back I was bored of the suburbs and being a teacher (high school physics for 7 years – no foolin’) so I decided to become an actor. I didn’t quit my job, but I did use my summer vacation to take 3 acting classes at once. It was a crazy good time and I completely recommend it to anyone looking for a change of pace and/or the opportunity to meet lots of pretty girls. Anyway, one of my classes was Improvisation which should really be called game playing for adults. Remember cops and robbers? Well yeah, it was like that. Teacher would get some volunteers and come up with some wacky situation and the 2 or more actors would just play out the scene. You’re a salesman on his way to a big sales call who sits next to a weird guy on the bus. And you, you’re a crazy person who thinks this bus is a submarine. Go.
Somewhat scary, but lots of fun. But like cops and robbers the game could stall if people didn’t play fair. “I shot you. No you didn’t” and so on. The number one rule for all improv is that you always say yes. If the butcher sez that its 5pm and closing time, you aren’t allowed to say “No, its 3 o’clock.” Everything just stops, the trust is lost, and the bit just becomes a boring argument. There’s something magic about saying yes. Which is why there’s a rule in XP that when someone asks for help, you always have to say yes. Even if you don’t want to. Even if you don’t know how to help. It just hurts the team too much when everyone is free to say no.
Now, of course, this rule is flexible. There are plenty of cases you can think up where it would be perfectly reasonable to say “No.” But it’s a good guideline. I’ve seen teams that are great and teams that suck and the ones where you can always get someone to help you fall into the first camp. Saying yes maybe scary (like improve) because you might look like a fool (also like improve) if you don’t know what you’re doing. But when everyone starts doing it the fear disappears and the team really gels.
So the project I’m working on has multiple databases – which is, in Rails opinion, kinda weird. Lately we’ve been having some issues where one developer will check in a migration that creates a new database and updates the database.example file. Everyone else does an update, tries to run their migrations, and gets an error saying that you can’t overwrite Object::InstanceMethods. What they need to do is add a few more lines to their database.yml file from the example file, but how would they know that unless they saw the database.example file amongst the stream of files that came down when they updated from source control. We need to get better about telling everyone (an email or a shout out to the room) when these get checked in. Because invariably some dev spends a few minutes scratching their head with this perplexing error.
What’s worse is that when I get this error on windows – It’s all over. I update my database file: same error. I drop and re-create all my databases manually: same error. The only thing I’ve found that works is if I kill my whole damn development folder and check out fresh. I realize that this makes no sense at all, but it works. Is windows hiding or caching some file somewhere? No idea. Luckily I’ve been mostly been developing on Linux for the last few days.
This error is another example of something I’ve been struggling with since I started writing Ruby: The errors tend to be unhelpful. Java and other strongly typed languages fail fast. If you give some method the wrong class, it blows up right away. In dynamic langs like Ruby the method doesn’t care what it gets so long as it can respond to the methods it called on it (the famous “duck typing”). Maybe the method just passes it along, or maybe it gets something off that the bad object and tries to do some stuff with it. So you can get pretty far down the stack from where you actually made your error before the interpreter blows up -- Which makes debugging a challenge. Now I know this added flexibility is what makes Ruby so cool. But it’s not without its costs.
So I ran into this weird problem with RSpec (the unit test (spec) framework for Ruby) and Rcov (a code coverage tool also for Ruby). At some point, usually as your list of specs gets longer, if you run your specs with Rcov they blow up with a seg fault. I’ve seen this happen on OSX, Windows, and now Linux. On my last project we just had to give up running Rcov (which sucked). This time Ricky Lui and Peter Ryan managed to figure out that if they comment out the tests that have an Active Record object mocked out for new, then Rcov is fine. Say you have an object called User and your controller gets a new instance and does a bunch of stuff to it. Well, you want to test (specify) what happens to that object so you do this:
specify “something important should happen to User” do
mock_user = mock(“mock_user”)
But Rcov no like this. So to get around this bug I had to open up my object in the spec and overwrite new, like so:
def self.set_mock mock
@@mock = mock
So now I can make a call to User.set_mock and give it the mock I want new to return. Not quite as elegant as the mocking framework (and it doesn’t check to make sure new is called), but it works. But here’s the weird part: I can do some mocking of new in the spec, just not too much. In the spec that was making rcov bomb, I had 7 places where it read User.should_receive(:new). If I commented out 2, the spec ran fine with rcov. If I left all 7 in, it blew up. Weird, huh?
I need to get a small version of this consistently failing so I can give it to David Chelimsky, my friend and an a RSpec admin. I want to submit the bug to Rcov, but I can’t seem to find where to submit it. I guess I’ll just email whoever’s maintaining it.
So I wrote this website for my dad over the weekend. Mostly to replace this site I wrote about 8-9 years ago when I first learned HTML. Dad’s a sculptor and I thought it would be cool for him to have a web presence. Of course to update the site he has to edit these html templates I gave him, create thumbnails and non-huge regular images of the pictures he’s taken, and then ftp the files to his server. Not so fun for a guy born during the year of
Now, armed with acts_as_attachment and a whole bunch more RoR experience, I knocked it out in a weekend. But the weirdest thing was that I didn’t write much code. Using the scaffold_resource generator I quickly threw up some pages to manage my 3 objects (FrontPage, Piece, and Gallery). Then I added some lines to Piece’s model to configure the attachments associated with it. I had to add a few more lines to make Piece’s views and controller deal with the attachments. And the rest of the time I’ve been screwing around with CSS trying to make it look nice.
The new site can not only upload images, but it automatically re-sizes them and creates thumbnails. Pretty bad-ass for a weekend. ‘Course I still have to deploy it.
You join a new project (and if you’re a consultant like me then this happens a lot) and you start asking a bunch of questions. Where’s the svn repository? What version of Rails are we using? How do I install this other thing upon which our thing depends? And the answers come. But then it’s a few days later and the more sensitive questions come: Why aren’t we pairing much? Why is this meeting scheduled to take most of the day (when it should 45 minutes at most)? How come the dev boxes are so slow? And if the answers you get to those questions are variations on “Um… We can’t do that – talk to me about it later.” then something is busted.
You don't know what it is, but you can feel it in the atmosphere. It’s tense. Some things are unspoken and mysterious forces are making sure it stays that way. Every iteration seems like it has too much in it. Its common knowledge that we have way more scheduled for release 1.0 then we can do in the time allowed.
If this is how XP feels then you’re doing it wrong. The point of an iteration isn’t to make every week a death march, it’s to increase visibility. If you didn’t get your 20 points of work done this week, the solution is not to mandate overtime or give speeches about how we “really need to get more done this week” and you certainly don’t want to just sign up for another 20 points for next week (only to fail again). If 2/5s of you team was out last week or lightning struck the servers then you can call it a bad week and move on. What bugs me is when people get pulled out for normal things (meetings, other projects they are assigned to, or normal fire dousing) and then the “bad iteration” gets blamed on “circumstance beyond our control” and we sign up for the same amount of work. There will, believe it or not, be more meetings in the future. So just call it overhead and adjust the amount of work we can accomplish in a week. And if that means we won’t hit our release date, then its good we know now. Right? If its not good we know now, then we’ve got a whole other set of problems.
As part of the hiring process at ThoughtWorks we do a code review. After a candidate gets through a few gates (a resume’ screen and some phone interviews) the prospect is giving a choice of three code problems to work on. They have 3 days to complete the assignment and turn it in. Then we have 2 developers look over the code (separately) and assign it a score. A lot of these submissions are pretty bad. Java arrays used where an object would provide clarity, cryptic variable names, missing files needed to run the project, and (amazingly) code that just plain don’t work.
But last night I graded a submission that was a joy to read. He submitted in Ruby (a good sign, but not a sure thing by any means) and clearly understood the elegance of the language. He did some fun things with aliasing and Ruby’s built in collections methods that made me smile. And they weren’t just showing off either. Sometimes we get solutions that are crazy over designed. Pages and pages of code where 100 or so lines will do. But this was short and sweet.
I hope we hire him.
First of all I was sick for 4 days last week so, yes, I missed the first 4 days of my new project. Nice. Now this is an ongoing project (for about a monthish now), so it wasn’t a total tragedy. But I did feel like a mope calling in every day to say that I was indeed still sick. I’m still sick, but it’s at a point where I can manage it with OTC medications. Drugged up and billable I am. W00t. And did I mention it was -9 degrees outside with a wind chill of -20 F this morning? Good lord -- that is a whole lot of cold (Especially as my new commute involves a brisk 30 minute walk across downtown
But what I meant to talk about was RMagick – which is a pain. It’s an image manipulation gem for Ruby that is pretty powerful but totally took down 2 systems I tried to install it on in the last 2 weeks. Back on First Street Live, Clint and I tried to install it on a Mac mini but Mac Ports and Fink started to fight over who was the package management of record and ended up not even being able to find our gems. Why does every package management system assume it’s the only one you’ll ever need? They refuse to play nice with each other. We hosed that Mac mini up so bad we just gave up and wiped it. Damn we suck.
Then, because I refuse to be beaten by something (and I’m a glutton for punishment), I decided to put acts_as_attachment on a little side project website I’m building. Acts_as_attachment is a cool plugin for Rails which lets you link an image to an ActiveRecord class. It makes it real easy to upload images to your website and delete ‘em and resize ‘em and gussy ‘em up real nice. But it requires RMagick, which requires ImageMagick and, yes, there was another point where nothing worked on my machine. But, even though Windows takes a lot crap about being dev-hostile, I was able to recover and install. They key is following the straight and narrow as described at rmagick.rubyforge.org/install-faq.html. You could install ImagickMagick and Rmagick your self but that will never work (even though some of the documentation seems to imply that it would). Follow the advice of the page listed above and install the package ‘cause it will make your life easier.
If you’re looking to live on the edge you might want to check out attachment_fu which is a reworking of acts_as_attachment but with plans to make it more modular so you can replace the dreaded ImageMagick with image_science and file/database storage with Amazon S3 storage. It’s pretty beta right now, but there is some buzz about it.
- ► 2014 ( 6 )
- ► 2010 ( 17 )
- ► 2009 ( 91 )
- ► 2008 ( 48 )
- FoxyProxy is bad news
- ActionMailer tips
- The stack trace that doesn’t mean anything
- Rails fixtures on Linux and Windows
- You want fries with that?
- The perils of keeping your prototype
- Theater and Programming
- Object::InstanceMethods is a confusing error
- RSpec and Rcov are not playing nice
- Where’s the code?
- What must not be spoken of
- Code Review
- RMagick is a crazy pain
- ▼ February 2007 ( 13 )
- Code ( 61 )
- Apprenticeship ( 57 )
- Rails ( 53 )
- commentary ( 48 )
- Ruby ( 31 )
- RSpec ( 20 )
- Metrics ( 17 )
- metric_fu ( 13 )
- Flog ( 9 )
- complexity ( 9 )
- testing ( 9 )
- RailsConf2009 ( 8 )
- git ( 8 )
- RubyConf2008 ( 7 )
- test_coverage ( 7 )
- Bugs ( 6 )
- Mocking ( 6 )
- craftsman_swap ( 6 )
- not_code ( 6 )
- Agile2009 ( 5 )
- Amazon ( 5 )
- refactoring ( 5 )
- ActiveRecord ( 4 )
- JRuby ( 4 )
- Linux ( 4 )
- LoneStarRubyConf2008 ( 4 )
- RailsConf2010 ( 4 )
- Saikuro ( 4 )
- XP ( 4 )
- churn ( 4 )
- design ( 4 )
- Fixtures ( 3 )
- LoneStarRubyConf2009 ( 3 )
- Math ( 3 )
- Obtiva ( 3 )
- RailsConf2007 ( 3 )
- Rake ( 3 )
- Rcov ( 3 )
- RubyKaigi2010 ( 3 )
- RubyMidwest2010 ( 3 )
- Svn ( 3 )
- legacy_code ( 3 )
- Flay ( 2 )
- GLSEC ( 2 )
- Mingle ( 2 )
- SQuiD ( 2 )
- TextMate ( 2 )
- Windows ( 2 )
- WindyCityRails ( 2 )
- lean ( 2 )
- Backstop ( 1 )
- Bundler ( 1 )
- DUST ( 1 )
- EVDO ( 1 )
- GC ( 1 )
- IO ( 1 )
- MacRuby ( 1 )
- MongoDB ( 1 )
- OSS ( 1 )
- OSX ( 1 )
- Routes ( 1 )
- RubyWorks ( 1 )
- Tomcat ( 1 )
- attachment_fu ( 1 )
- cache-fu ( 1 )
- citcon ( 1 )
- consulting ( 1 )
- craftsmanship ( 1 )
- css ( 1 )
- db ( 1 )
- iPhone ( 1 )
- interview ( 1 )
- mac ( 1 )
- memcached ( 1 )
- memprof ( 1 )
- oracle ( 1 )
- ord_sessions ( 1 )
- ostatus ( 1 )
- pairing ( 1 )
- redis ( 1 )
- restful_authentication ( 1 )
- singleton_class ( 1 )