Ask for Help
"Our delayed job consumes 2G of memory creating ~20k ActiveRecords in a loop!"
It doesn't answer why your job is using so much memory, but check out activerecord-import.
The Ugly Truth
On a recent project, we had an ActiveRecord model that declared some relationships and callbacks like so:
belongs_to :credit_card
before_create :build_credit_card
The intent was that build_credit_card would build the associated CreditCard instance, and ActiveRecord's default :autosave feature on the belongs_to would save it.
What we discovered was that no CreditCard object was being persisted. We confirmed that :autosave is on by default for belongs_to relationships, so we couldn't immediately understand why the new CreditCard wasn't being created.
Googling proved futile, so we dove right in to the ActiveRecord source- and boy did we have a good laugh about 10 minutes later.
What we found was that the :autosave option works by simply declaring a before_save callback- that makes perfect sense.
In our case, however, we were building the object to be autosaved in a before_create callback, which ActiveRecords runs after the before_save callbacks (cf. the callback ordering docs).
So our first problem was that we needed to move the call to build_credit_card from a before_create callback to a before_save :on => :create callback.
Did you catch that? There is a difference between before_create and before_save :on => :create. A big difference.
While I understand the how and why of this, the semantics don't make it obvious. So beware!
Now with our declarations changed to
belongs_to :credit_card
before_save :build_credit_card, :on => :create
We ran our tests again, and, still, no love. Ahhh, we've still got an ordering problem. In addition to the ordering semantics detailed in the docs, ActiveRecord also runs callbacks within a single group in the order in which they are declared. So, even though we changed the call to build_credit_card to occur in a before_save, it was still occurring after the :autosave before_save callback, because of the declaration order.
Finally, we changed our declarations to
before_save :build_credit_card, :on => :create
belongs_to :credit_card
and our tests were happy.
Takeaways
When using
autosavewith any ActiveRecord association, be very careful of callback ordering if you are building or modifying the inverse objects using ActiveRecord callbacks.before_createisn't ever the same thing asbefore_save :on => :create, even if it sounds like it should be.
Interesting Things
has_manyandbelongs_toassociations can now automatically create back references each other, thanks to a Backport of :inverse_of from Rails 3 to rails 2.3.6. This allows us to keep our object graphs more correct and avoid situations where we have 2 copies of the same object because the object graph is walked in reverse. Here's how to use it:
class Parent < ActiveRecord::Base has_one :child, :inverse_of => :parent accepts_nested_attributes_for :child end class Child < ActiveRecord::Base belongs_to :parent validates_presence_of :parent end
My company launched our app, Cohuman, a few weeks ago. The rush of finishing features, fixing bugs, and responding to user feedback has subsided a bit, and it's time to go back and give the little baby a tune-up. I find that a good development process will ebb and flow, and as long as you don't let something slide for too long, it's perfectly acceptable to let bugs, or performance issues, or development chores pile up for a bit and then attack them concertedly for an entire day or two. A bug-fest or chore-fest or tuning-fest can actually increase efficiency as you get in a rhythm... and it feels really good at the end of the day when you see all the bugs you slayed or all the milliseconds you shaved.
In this article I'd like to describe some of my techniques. I make no claim of originality or great expertise; I just want to share what I know, and hear (in comments) what other people have learned. I'm using Sinatra and ActiveRecord, but not Rails; hopefully this discussion will help people no matter what framework they're using.
Ask for Help
"We keep getting webrat thread exceptions running our integration specs with the rails integration runner: Thread tried to join itself. The error message varies with different versions of ruby 1.8.6 vs 1.8.7."
Anyone had this problem or know why?
"How do I skin an iphone mobile site to be the correct width so it's not 980px wide?"
<meta name="viewport" content="width = device width" />
*"We're trying to deploy some nginx configuration changes to EngineYard Cloud, what's the right way to do that?"
We've tried building custom chef recipes to solve this problem, but they run after nginx has already restarted, so are a poor solution to this problem. The better solution might be to check in configuration files into the application and symlink them into the nginx configuration directory using a before_symlink.rb hook in the /deploy directory.
*"We've got a
has_manyassociation where some of the child records are originally saved in an invalid state. When we later load the parent and ask it if it's valid, it returns true even withvalidates_associated. How can we get the desired validation behavior?"
Turns out that unloaded associations are not validated. Solution: load the association before calling .valid? on the parent. In general, you should also not create invalid objects, instead using a state variable to put them into a "draft" or "incomplete" state where they are still valid but not complete. Then remove that state and you'll see the errors required to finish that object.
Interesting Things
- When RubyMine 2.0.1 won't run your focused specs, try attaching rspec 1.2.9 to it rather than 1.3.x. It fixed this issue for one of our teams.
- Rubymine 2.0.2 came out today: can finally run focused contexts?! Also including bundler support! What's new
- We tried our Unicorn on EngineYard cloud: so far so good. It's still "experimental" but seems to work.
Ask for Help
"mp4s do not play during download in chrome"
Talks at Pivotal are recorded and published in various formats. Our talks page has an embedded viewer so that people can watch the video without downloading. We also offer a downloadable version in mp4. Most browsers will play the video as it is downloading. Google Chrome does not. Are we doing something wrong?

Interesting Things
Beware: has_many associated objects are saved before has_one associated objects.
update_attribute of foreign_key value on belongs_to association does not save...when object was created by factory girl?
This is pretty specific, but perhaps not enough to be useful. The team tried to do an update_attribute on an object generated by factory girl, changing the belongs_to column value. However, no database update would occur. They later resolved this by doing a reload on the object before the update_attribute.
"Update_attribute is almost never the right thing to do" --anon
Now that I'm starting to use DelayedJob to perform jobs in the future in my Heroku Sinatra app, its important that they happen at the scheduled time. But unless you pay attention, you'll find that times get mysteriously changed -- in my case, since I'm in San Francisco in the wintertime, by +/-8 hours -- which means that some conversion to or from UTC is being attempted, but it's only working halfway.
Trying to keep a handle on which libraries are attempting, and which are failing, to convert times is a losing battle, so I'm trying to do the right thing and save all my times in the database in UTC, and convert them to and from the user's local time as close to the UI as possible. Unfortunately, a variety of gotchas in Ruby and ActiveRecord and PostgreSQL makes this trickier than it should be. Here's a little catalog of my workarounds.
Help
Why is upgrading to Ruby 1.8.7 so painful?
More specifically, a Pivot was wondering why there seem to be so many ways to install Ruby and Rubygems on a Mac. There are a lot of different places where gems end up being installed depending on which version of Ruby you have installed, and the specifics of how you installed it. The conversation turned into one about RVM and Yehuda Katz' Bundler, two technologies that appear destined to make it much easier to easily combine a version of Ruby with a set of gems under a particular project.
What is that technology that allows for more complex condition hashes in ActiveRecord?
This must be ActiveRecord::Extensions, which allows for an expanded syntax in the conditions hash of AR finders. A debate was had as to whether hashes and arrays could possibly comprise a reasonable DSL for complex query logic, but surprisingly, the final word on the subject was not reached during standup.
We are using
curlto talk to a Mongrel/Rack server that is running some specs. That server is emitting dots (just as any Rspec process would), but we cannot get those dots to show up in real-time on the client. The only way we've been able to force a flush is with a newline character, but that gives us an ugly vertical column of dots. Any suggested hacks for this?
The Bay Area Chef Meetup Group is meeting on 10/14 in Mountain View. If you're into Chef (and here at Pivotal we use it extensively), you might want to check it out.
Nested attribute assignment is one of the recent additions to Rails that made a great deal of sense, and made a lot of people happy. Chances are you've either used nested attribute assignment by now, or you worked on an older project that really could have used it. If you haven't yet, check it out and see what you think.
Unfortunately, not all is well in Railstown. Nested attribute assignment is slick, and the related implementation of #fields_for makes it even slicker, but #fields_for can cause you some headaches if you're not careful. Possibly if you are careful as well.
One of my favorite computer games when I was growing up was Robot Odyssey; I imagine it will come as a surprise to no one that I was a nerdy kid. This article is a little bit of a tribute to that game, and the coolness of solving complex problems with a handful of simple concepts combined in clever ways.
Imagine you want to write a web-based game that involves robots. The robots in your game are a bit like the robots in Robot Odyssey: you program them with a list of simple instructions and when you turn them on they follow those instructions faithfully. Let's say, for the sake of argument, that your robots can Walk Forward, Turn Left, Turn Right, Jump, and Beep.
