I’ve been using the Pivotal Tracker gem by Justin Smestad on a project to do various things but I ran into a problem using it with multiple API keys. The gem would create a single connection object and continue to mimic the user the first connection was made with, even when you’d updated the token to different user’s token. The Tracker API relies on you passing your API key for access to the projects and stories your account has access to, so I had the problem that the first user to use my app would determin access for everyone using the app. Not good!
After checking out the project the change was pretty simple but it highlighted an issue that I’ve seen in plenty of code where caching is done too broadly. In this case the cacheing (or memoization) was performed without taking into account the variable that was sent to establish the connection in the first place. The offending method looked like this :
This was set on the class and as such @connection would never be created after the first call, whether the token was reset or not. I just changed it so that the connection is cached for each @token the system uses. For us it’s a small number or users, but in a larger context of course you’d need to implement some invalidation protocols to stop the following code from (slowly) swallowing the world :
NoToken is just a class inheriting from StandardError that I chucked in there, the only thing that makes the gem now work properly come afterwards. I setup a hash and then store a new connection for each new incoming token, the connection is keyed by the token in the @connections hash. All pretty simple.
I’ve created a pull request that will hopefully be accepted soon, I think it fixes an unexpected problem with the gem.
CarrierWave is a great gem for adding image uploading and basic processing abilities to your Rails applications. By default there is no way to set the quality of the resized images, which could be a very useful feature.
One of the applications that we’re currently building has a requirement to resize and compress images to produce smaller file sizes, as well as stripping out any personal information that may be stored in the uploaded images.
Out of the box CarrierWave provides a consistent interface to process images using RMagick, MiniMagick or ImageScience. Resizing and cropping is supported for all three image processing engines but setting the quality or removing personal data is not supported. Thankfully, CarrierWave provides an easy way to extend the default functionality so we can do more.
For the examples I’ll be adding extra functionality to RMagick processing. If you’re using MiniMagick or ImageScience the methods will need to be altered to work correctly. We’ll start by adding a new initializer into our application.
You may be wondering about the fix_exif_rotation method. Well, some modern cameras always take photos upright, in portrait. When you take a photo in landscape mode the photo is actually saved as a portrait, but the photo will contain some extra orientation metadata. When we remove the embedded data in the photo this value gets removed, so as a result we need to manually rotate the photo, which is what this method does.
The application server will need to be restarted before the new initializer can be used. Once restarted the new filters can be used in an uploader like so:
It seems that access to the ActiveRecord callback chain has changed recently, however the documentation still contains the following :
To list the methods and procs registered with a particular callback, append _callback_chain to the callback name that you wish to list and send that to your class from the Rails console.
This used to work in Rails 2.3.x and I’d used it a few times before, however trying to use it in Rails 3 gave me problems :
HourEntry.before_save_callback_chain
NoMethodError: undefined method `before_save_callback_chain' for #
After some digging around ActiveRecord then ActiveModel and ActiveSupport I figured I could just access the _#{type}_callbacks method and then reject and select these arrays to get what was required. This is what I came up with to get the before_save callbacks that I was interested in.
This returns me the array of callback objects that are chained before I call save on the HourEntry model. If I want to check for a particular proc being in that chain then I can do :
It’s not optimal chaining a number of enumerable methods but I think it seems pretty readable.
I am hoping that the callback_chain methods return at some point (though I only used them sparingly) but more than that I’m hoping someone might be able to set me straight on how I’m going about getting around the callback chains on ActiveRecord and ActiveModel.
Today I had some knowledge delivered straight to the top of my dome, by Darcy. The issue was I had two models that I wanted to join and then apply scopes to. I wanted to retrieve Story objects that were joined to HourEntry objects, that were from this week. However when I tried to use the Time scope on the query it was attempting to call those methods on Story.
ree-1.8.7-2011.02 :132 > Story.joins(:hour_entries).this_week
NoMethodError: undefined method `this_week' for #
The problem was that the .this_week call was being sent to Story rather than to HourEntry. Here’s where Darcy chimed in with the scoped.merge call. It went a little something like this :
Story.scoped.merge HourEntry.this_week
This successfully merged the scope defined by Story with the scope defined by the HourEntry.this_week call and I get all the stories that have HourEntry objects that are returned by the .this_week scope.
This then returns all the stories you’ve worked on this week. Add a bit of grouping/distinct and it’s done and done. The additional nice part about this is composing these scopes will allow me to do a lot more in the future, very quickly.