A while back, I was working with an application that used custom headers. Applications use custom HTTP header to transfer domain specific information, either in request or response. Earlier the trend was to prepend “X-“ to the custom header, but since June 2012, this approach has been deprecated.
I used rack-test to write some tests and to my surprise it appends HTTP_ in front of custom headers. I think it may do that in front of other headers too, and I did read this somewhere, but I can’t seem to find that link anymore. So, the first lesson of this post is to make others aware that HTTP_ is appended to custom headers with rack.
All this worked smoothly in local environment, and the moment I pushed it to Nginx+Passenger, it just blew up. Debugging revealed that it was actually just the way custom headers are treated in Nginx. The custom header had underscores in it, and Nginx is known to ignore custom headers with underscores, and therefore, this custom header never made it to the actual application. For example: X_API_KEY will be ignored by Nginx, where as X-API-KEY will be translated into X_API_KEY. I had to change the custom header to X-API-KEY and remove the underscores.
To summarise, these are the stages a custom header goes through:
1. Starts it’s life as X-API-KEY in the client request
2. Reaches Nginx, and is changed from X-API-KEY to X_API_KEY
3. Reaches Rack, and is changed from X_API_KEY to HTTP_X_API_KEY
4. Should be interpreted as HTTP_X_API_KEY in the actual application code.
The first think we learn as programmers is DRY i.e. Don’t Repeat yourself yet we programmers break that principle all the time, sometimes unknowingly, and sometimes on purpose. Writing a gem is easy, but why write one from scratch when one can extend and improve an existing gem. Anyways, just my opinion.
I never understood the reason for rbenv. I love rvm far too much to move to rbenv. My work colleague suggested that rbenv is much faster than rvm. I just ignored him then, but later on decided to investigate it further. I decided to write a small Dtrace script.
It’s a very trivial DTrace script. It collects and displays the process count called in the background. So, if it just lists the process (or scripts) with the count when I execute bash. In my bash script, I had the following line which loads rvm and allows for selecting gemsets and rubies.
if [[ -s ~/.rvm/scripts/rvm ]] ; then source ~/.rvm/scripts/rvm ; fi
Here are the results:
In short, rvm script makes quite a few extra calls and that makes it different from rbenv. But, it’s not a significant difference for me to switch or write another library that does exactly the same.
If you think about it, RVM is trying to solve two problems:
Store gems based on projects, so one can easily separate a Rails 2.3 application’s gems from Rails 3’s gems.
Easily switch between different rubies.
Does it need to do that? In my opinion, Bundler is quite good at managing gems. Therefore, my solution to this issue is to not create gemsets. That’s exactly what rbenv does. In the meantime, I have created a simple bash function to load rvm shell on demand.
For non-programmers, Spring symbolises sunshine, warm breeze and holiday season. However, the story is a little bit different for Programmers. Yes, Spring brings timezone issues for Programmes. In other words, the moment of truth is upon us now and it’s time to check your timezone code. I spotted two obvious issues, and both are somewhat related to github. My pull request on rails are showing an hour behind the actual time, and the resque web admin retries the failed jobs an hour before the actual time.
Testing has always been part of the Rails framework, right from the beginning. The whole TDD concept became hugely popular after Rails was adopted in the mainstream. It has been around but Web applications were tested in a different manner 10 years ago. On my first day as a Java Developer, I was told by a Senior Developer that you can’t really test a Java web app by writing unit tests. I took his advice and frankly speaking, I didn’t know better.
Anyways, I am not here to talk about my career. I have been doing Rails for quite a while now and on one project, test suite took about 30 minutes to run. I know, 30 minutes. Because, we didn’t fake the calls to external APIs. How silly was that? So, recently I started working on the project and every time I ran the test suite, it took 2 minutes for them to run. That kind of put me off the whole testing thing. I mean what’s the point. I can just write the code and use the good old presentation driven development, where if it works it works. If it doesn’t, then we’ll fix it. This strategy kind of works, but becomes a nightmare when one bug fix results in another regression bug.
I ventured out looking for solutions and I found that instead of fixing the issues around testing, community has moved to the whole client/server architecture towards testing. I started on Spork. It’s a very nice idea but I don’t want to muck about with my configs and do the setting up. The downside is that now I have to get the entire team to use Spork and set it up and all. I know it works and a lot of developers use it but I don’t want to do it. Then, accidentally, I found spin. Spin is the same client/server idea but instead of a drb server, like Spork, it uses UNIX sockets for communication. There is absolutely no setup required. I have been using it on two different projects and it has worked nicely.
Some other solutions are to load your database in memory, easy to do with sqlite but with postgres you have to create a ram disk and load the database from there. Stop abusing machinist, factory_girl and the like as they make db calls. Instead, use mocks and stubs.
But, I still think these are just workarounds for the existing problem with Rails load times and testing. Is there a better solution to this problem? How can I make my application testable, follow TDD and yet never have to worry about loading rails? I guess I need to objectify my application. I will probably talk about it in my next post.