Two things happened recently that have each, in their own way, de-railed me to some extent. The details of each instance should be interesting to iOS developers and Rails developers alike.
As I thought about what to write about this week, I realized I had had two recent experiences that were actually related (i.e. same project) and with which I could make a play on words (something I enjoy doing at every opportunity. 🙂 ) “De-railed” here refers not only to Ruby on Rails (in which the de-railment was only temporary) but also to an ongoing iOS development effort which has been, and remains, temporarily de-railed.
De-railed: Paperclip gem for storing attachments with dynamic watermarks
The At-Hand Apps project, which I have written about in the past, consists of several iOS apps which all rely on a Ruby on Rails backend. The backend provides 3 things: our customer-facing marketing web pages, our content management system, and our API.
Of interest here is the content management system. Using this system, our content contributors and editors manage our database of activities, which includes pictures. To store pictures with activities, we use in our model the Paperclip gem. The gem is really cool because it allows us to define an “attachment” attribute in the Photo model, and the gem takes care of storing the image (on Amazon S3 in our case) and performing any other post-processing we might need (e.g. thumbnail creation).
Many of our photos come from third-party photographers who have graciously allowed us to use their photos in our app so long as we give them proper attribution. No problem; the Photo model allows for content editors to include, on a per-photo basis, an attribution, and Paperclip includes the ability for us to run a “watermarking” post-processor. Awesome!
Now, watermarking often means, in most applications, applying something like a fixed image on top of another image. In our case, however, a photo may have a custom attribution: text identifying the photographer. So our version of the watermark processor wants to take that attribution (a property of the Photo model) and apply it as a graphic to the image.
The problem we encountered was that when the watermark processor ran, the model’s attribution property was nil until after a new Photo was saved. So initially, photos would have the wrong attribution: our default At-Hand Guides attribution. This made some photographers understandably very unhappy.
It turns out that the way in which we were instantiating new Photo objects in our controller was wrong. In fact, we were not creating objects explicitly at all! And that was the problem. What was apparently happening was that Rails was generating a new object for us using mass assignment. And here’s the rub: Paperclip does it’s thing (runs its processors) on assignment, and not after the model object is complete.
The solution was to explicitly create the object, using mass assignment, but only after removing from the Rails parameters the picture. Also, we made all but the picture property attr_accessible (meaning, the picture attribute could no longer be assigned via mass assignment). After creating the new object explicitly, which guaranteed that the attribution property would be set, we then assigned the picture property to the value removed earlier from the Rails parameters.
Problem solved! You can read about this (again), but with some code examples, on StackOverflow where I wrote about this in response to a question that suggested that the model data was not available at all in Paperclip processors. In fact, the model data is available, if you create your objects and assign your properties deliberately.
De-railed: App rejections
If you are iOS developer and have not had an app rejected, you might consider yourself lucky. On the other hand, it is something worth experiencing, at least once, simply to understand what it means and what it’s like to deal with. There are a lot of App Store Guidelines, and I am certain we all have not memorized them. None of us intend to violate these rules with our apps. But sometimes, it happens, despite our best efforts.
I’ve experienced two app rejections so far. The first was minor, really, and if you ask me, silly ridiculous. We had submitted our original app, and about 7 prior updates with a certain name, which was by no means confusing to users. The app’s Springboard display name was one of the words in the longer iTunes name. It was on our 8th submission (7th update) that Apple decided the (longer) name might be confusing to users. What?!
In this case, we acquiesced and changed the iTunes name, literally by swapping the order of the first 3 words in the long title. It wasn’t worth arguing about it, and the business utility of using the original name, which only differed in the order of the words, had passed. No biggie. (Annoying, but not a big deal…)
My second app rejection came more recently, with a new app At Hand Apps had submitted. The app was rejected for violating App Store Guideline 2.20. The reviewer pointed out that this new app was really just the same as our other apps, except with different content. To be fair, the initial content available in the app was different from content in our other apps, and this app, like several of the others, offers in-app purchase to add more content. The app was to be free on the App Store.
Obviously, it was never our intent to violate any guidelines! In fact, our strategy had always been to provide a high-quality app in ways that gave users different ways to enter our platform. The idea behind this new, free app was to on-board a lot of new users in a frictionless way, and then if they wanted more content, they could buy it.
Needless to say, we were upset and confused. Upset because we had worked hard to get the app done and submitted ahead of July 4th (a moment in time when our app and its free content would have been particularly relevant), and confused because we already had 7 apps in the App Store which, if you wanted to pick nits, also violated Guideline 2.20. What to do, what to do…
When you have an app rejected, Apple does provide a means of engaging in a dialog about the rejection. We carefully considered what our response would be. After some time had passed, we responded with a careful explanation of what it was we were trying to accomplish, and that of course, it was never our intent to spam the app store with many similar apps (although there are certainly many examples of developers who have done this.)
This resulted in my having an excellent phone conversation with someone from iOS Developer Relations. While getting the app rejection sucked, actually talking with someone who could offer real suggestions on how to be successful was awesome. He explained that one of the App Store goals is to keep things simpler for users. He suggested that many similar apps from the same developer that only differed in content had the potential to be confusing. He suggested a couple alternative strategies that he said would be “Ok”, meaning, they would pass muster with app reviewers. Ultimately, he was very candid with me about the lay of the land and how things really worked behind the App Review curtain (to the extent that any Apple employee is willing to open their kimono, so-to-speak.) All in all, a very enlightening exchange.
So for the moment, development on this project is still a bit de-railed unfortunately. But we have a lot of new information, straight from the horse’s mouth, on how to proceed and be successful.
Have you been de-railed lately? How did you resolve it? Have you had an app rejected? How did pivot (or not) to overcome it? Leave a comment.