rails 3 start

I’m starting to play around with Rails 3… perhaps a bit premature, as the beta isn’t even scheduled to release until the end of the month and looking at the open tickets for documentation I’m curious how people are even beginning to plan for code migration.

So I decided yesterday to start looking at the code base. Of course this is really helpful:

http://yehudakatz.com/tags/rails-3/

But I think the most helpful thing really is going to be digging through the framework. Like with the last time I dug into the code, routing seems to be first… maybe because that’s where I expect the most problems to arise in the plugins I’ve developed? Maybe because it seems a logical place to start, being the first entry point at which a request gets processed?

The first problem that I foresee is that I follow a thoughtbot trick to apply Rails Engine routes in an order different from the default. In Rails 2.3, routes added from an engine take precedence over routes in an application. For plugins I want default behavior that can easily be overwritten from within a project (perfect for rapid prototyping where I want to be able to drop in base functionality and overwrite it only where necessary). So far… I’m not seeing an easy parallel.

relative_url_root in javascript

I just realized something that could make life much, much easier.

In my rails apps that utilize jQuery (pretty much all of them that have any complex interaction), I’m used to adding a line as follows to allow jQuery to include authenticity tokens in any ajax request:

<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>

And yet, when I write ajax requests with any sort of time crunch, in the interest of speed I throw in absolute URL strings. What happens when I want to change the root URL for a project when deploying to Passenger, though?

I just realized that I can use the AUTH_TOKEN technique to give JS access to my root url string.

<%= javascript_tag "var RAILS_ROOT = '#{ActionController::Base.relative_url_root}';" %>

This gives me a variable RAILS_ROOT that I can prepend to any of my urls. It’s not the complete joy of resourceful named routing, but it’s one step closer to it without the overhead of parsing all of my js files through a controller.

OCUnit, CoreData redux

Huh. Rereading my notes about incorporating CoreData with SenTest. Seems like that’s a perfect example of dependency injection. Wish I’d known about that earlier.

Github drinkups + something called ‘the bomb’

How much more information is necessary? I think that the total number of solid new connections I’ve made is a resounding zero. The faltering aquaintances can be counted on one hand.

The depth of joy and personal happiness? Boundless.

Plus I got to reconnect with @richardiux and @jpsilvashy, two gentileman of inestimable value.

I highly recommend github drinkups.

strings, string literals and memory

I’m doing something in Java at work. This is perhaps a greater surprise to me than to anyone else, as up until now I didn’t think I knew Java. It turns out to be much easier for me to understand now than last time I peeked at it, perhaps from what I’ve been doing in Objective-C.

In any case, I was asking a friend of mine whether Java can do multi-line string literals รก la Perl/Ruby/Bash/etc:

string = <<END
This is the first line.
This is the second line
END

The answer, apparently, is no. So, there I was about to go accept this syntax:

private static String string = "This is the first line.\n" +
"This is the second line.";

when my friend mentioned that StringBuilder is much more memory efficient than String. This was counter-intuitive to me, particularly as I would expect a non-mutable string to be more memory compact than a mutable string. Don’t know why, that’s just what I assume.

Then he pointed out that each “something” instantiates a new String class. So, my “thing” + “thing” turns out be something more like this at the compiler:

string = new String(new String("This is the first line.\n") + new String("This is the second line."));

That’s not exactly true, as after more investigation it turns out that the compiler would probably see those as string literals and inject them as constants into my class file. This is what I’d expect, really, coming from an Objective-C world. That’s still less memory efficient than I want, though.

My work project is tiny, so the impact of this is negligible. I really want to start out on the right foot, though, memory management-wise. I’ve been in the situation of inheriting projects that started simply, then became bloated and stupid as they passed from hand to hand. So, I want to start this the right way.

My bigger question is how Objective-C really handles strings at the compiler. Does this have implications for how NSStrings should be concatenated or built with formats? If that’s the case, then I should look at every for loop in my code.

SQL queries, counts and search

Well, I’m stuck at BART waiting 40 minutes for the next shuttle bus (barely missed the last one), huddling under a concrete overhang to hide from the rain. This is where my commute is awesome!

Anyways, I discovered some neat aspects of search the other day… Let’s say that you have a search query and you want to refine the results by tags or filters.

If you have multiple options for one type of tag, then those form an OR relationship. Different types of tags form an AND. So:

WHERE search LIKE "%x%" AND
(type_1 = xx OR type_2 = yy) AND
(category_1 = xy OR category_2 = xxyy)

Makes sense.

The problem starts when you try to generate counts for each tag, particularly if you want those counts to update on the fly. At that point, your relationships change. For each tag, you need a separate query that pulls its section out and compares it to the combination of the items in the other section. So:

WHERE search LIKE "%x%" AND type_1 = xx AND (category_1 = xy OR category_2 = xxyy)
...
WHERE search LIKE "%x%" AND type_2 = yy AND (category_1 = xy OR category_2 = xxyy)
...
WHERE search LIKE "%x%" AND category_1 = xx AND (type_1 = xx OR type_2 = yy)
...
WHERE search LIKE "%x%" AND category_2 = xxyy AND (type_1 = xx OR type_2 = yy)

This of course gets really expensive really fast, as you have to run a separate query for each tag. At this point you would have to optimize the hell out of everything you could possibly optimize, cache as much as you can cache, work on your indexes and beef up your server. Even then you’d probably want to performance test this as heavily as you can to see where the weak points are in your deployment. This is a scaling nightmare waiting to happen.

BUT it works. And it’s kind of cool.

It’s also cool that I can blog from my phone in the rain at a BART station. Cool. Yeah, that’s the word for it.

dependency injection, yo!

I have not been testing my controllers. It’s terrible. Part of this has been because I only managed to get OCUnit to work in my project about a month and a half ago, and in the intervening span of time I was fighting to get it to work with a CoreData dependency. The other part of it is that I really haven’t known how to test my controllers.

[This is where I really should have started TDD four months ago and not done any coding without it.]

So my problem is that I have a main controller that does a lot. I mean a LOT. It’s in charge of knowing when location services are enabled. It downloads records from my server and inserts them into my database. It keeps track of which records are in memory (being an NSFetchedResultsController delegate). And I don’t have any tests written against it. It’s really starting to get scary, as I look at the features I still need to implement.

The issue I’ve been facing has been that the code that I want to start writing tests around is dependent upon NSURLConnection: when it gets word from its location manager that locations are enabled, it fires off a GET to my server. It all works in theory, but already I’m realizing that I would have found problems earlier and isolated my bugs when coding them if I’d been writing tests to prove the desired behavior. It’s completely dependent upon a foreign class in order to function, however.

This is where dependency injection comes in. I was searching for a way to hijack the NSURLConnection framework with OCMock, but kept coming back to the fact that I was creating my connection deep in the middle of code that had other external dependencies. So I was getting really confused. Thankfully I stumbled upon this Wikipedia link.

If I rewrote my code so that I could pass in the connection object only when it was required, I could then test the subsequent code with a mock object and not have to worry about testing my external dependencies.

So this:

- (void)locationManager:(CLLocationManager *)manager 
      didUpdateToLocation:(CLLocation *)newLocation
      fromLocation:(CLLocation *)oldLocation {
  // do stuff
  [self downloadCoordinate:newLocation];
}
- (void)downloadCoordinate:(CLLocation *)location {
  // context context init and observation to process records
  NSURLRequest *request = // setup request
  NSURLConnection *connection = [[NSURLConnection alloc]
     initWithRequest:request delegate:self];
  if (connection) {
    // set up NSMutableData for received data
  }
}

Becomes this:

- (void)locationManager:(CLLocationManager *)manager 
      didUpdateToLocation:(CLLocation *)newLocation
      fromLocation:(CLLocation *)oldLocation {
  // do stuff
  NSURLRequest *request = // setup request
  NSURLConnection *connection = [[NSURLConnection alloc]
     initWithRequest:request delegate:self startImmediately:NO];
  [self downloadCoordinate:newLocation];
}
- (void)downloadCoordinate:(CLLocation *)location 
      connection:(NSURLConnection *)connection {
  // context context init and observation to process records
  if (connection) {
    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] 
        forMode:NSDefaultRunLoopMode];
    [connection start];
    // set up NSMutableData for received data
  }
}

Now I can write a test that calls the download method directly, and I can pass in a mocked object to fake the request. That’s dependency injection: you write your code so that you can inject foreign dependencies from outside, so that your code doesn’t become internally dependent upon an external resource.

Note that I had to add the connection to the run loop schedule. This was because it was throwing an exception if I just called start without it. I’m not exactly sure what’s going on behind the scenes, but apparently if you initialize the connection with startImmediately:NO it doesn’t add it to the current run loop?

Now I just need to figure out how to mock up an NSURLConnection so that I can run the tests. Sigh.

NSFetchedResultsControllerDelegate methods, main thread

I was running into some issues getting updates to my NSFetchedResultsController to update my UITableViewController. Yeah, I know, who hasn’t? Sheesh, where have I been these past few years. Talking to girls or something?

Anyways, I discovered something that was not entirely intuitive until I tried a few experiments.

The problem that I’m trying to solve is that I have data on my server exposed as JSON. When my iPhone application is running and ready, it opens an NSURLConnection to download the data, then (using the CoreDataBooks sample as an example) creates a new NSManagedObjectContext (addingContext) to process the inserts and updates. My controller registers an observer on this context, so that when it finishes and saves, the changes can be merged back into the main context. This fires off the NSFetchedResultsControllerDelegate method (whew) -(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath;

Say that two hundred times fast.

Anyways, what I was finding was that new records were triggering the delegate method, but updates were not.

So… Long story short is that I was creating the addingContext and registering the observers from within the NSURLConnection delegate method -(void)connectionDidFinishLoading. The problem [I think] is that this is in a secondary thread. NSURLConnection implicitly creates a new thread in initWithRequest, so that it does not stop the main thread from processing user interactions. Somewhere in the documentation I noticed something about making sure that fetched results controller updates are done in the main thread [can't find it now].

When I move the code to create the addingContext and add the observer up before I create the NSURLConnection, everything works correctly.

The only complication is that I have to add a few more lines here and there to clean up memory in case of different connection states.

Sleep would be nice

It is extremely difficult to get a detailed understanding of NSError after two weeks of 6 hour sleep increments.

Just sayin.

fixing autospec

Right. Was running into issues getting autospec to run on both a clean install of rails 2.3.4 as well as a machine that used to run it fine.

After some fiddling and reinstalling gems, it now works.

gem install rspec # currently 1.2.8
gem install rspec-rails # currently 1.2.7.1
gem install autotest-rails # currently 4.1.0
gem install ZenTest # currently 4.1.4

I think I was missing autotest-rails. I had to reinstall ZenTest after that became available to my system, to make sure it installed correctly. There were no install error messages before, I think something was just missing in the background.