Joined July 2012

James Brooks

Good Dog Design
Good Dog Design
Adelaide, Australia


It is as #merge combines AR::Relations into a new AR::Relation. When this is ran only a single query is ran opposed to multiple queries (as well as multiple AR instance instantiations being performed that aren't required).

The first approach (using #map) runs 1+O(n) queries (which can be reduced to 2 by using includes(:computer) before the #map call).

The second approach (using #merge) only runs 1 query, as well as having the advantage as returning a AR::Relation (good for chaining on additional scopes if required, as well as lazy evaluation).

I benchmarked the results of the three different calls (including using #include also), my results were (1000 iterations each):

                     user     system      total        real
#map             1.460000   0.060000   1.520000 (  1.813301)
#map + #include  1.110000   0.040000   1.150000 (  1.381373)
#merge           0.190000   0.000000   0.190000 (  0.188655)

Seems to be ~10x speedup over #map, ~7x speedup over #map + #include.

footnote: In this example the query generated (looking at #to_sql) using #merge is:

SELECT `computers`.* FROM `computers` INNER JOIN `accounts` ON `computers`.`id` = `accounts`.`computer_id` WHERE `accounts`.`person_id` = 1 AND `accounts`.`role` = 'administrator'
Posted to Rails - Internal Requests over 1 year ago

The use-case here is a game containing many actions (as mostly POROs). Actions can be invoked depending on a number of things through a common controller that handles execution of actions. As part of a action execution the action can possibly dictate that a user should be redirected to another page (which after handled by a JS layer is just an ajax call with div replacement).

Originally this worked with having the result of the action request possibly return a key/value pair indicating that this redirection should occur, the client would then perform the request and perform the div replace with the entire returned request.

The internal request here was meant to be able to perform this second request in pair with the first request, returning the payload for the body of the page that we know that the client would then be requesting after this current request is complete, while still having everything operate as it did perviously (filters hit, controller action(s) ran, views rendered, return).

While this isn't something I haven't been overly happy to have had implement it isn't something I've had to do as of yet in my professional Rails career, and hopefully not often again, and serves as a reference for how this can be accomplished (a few hours of googling prior didn't reveal much).

Any suggestions for how to implement that without an internal request which doesn't introduce a whole lot of bloat I'll be happy to hear :)

599 Karma
61,932 Total ProTip Views