Deploy Strategies
If you look at the network graphs of heroku_san on github, you'll see a number of branches where the only change is the deletion of the following line from the deploy task:
- stage.migrate
If more than a few people are willing to take the effort to fork a gem just so they can delete 1 line, something smells. The reason is that these forkers were using something other than Rails+ActiveRecord+SQL in their project. Some were using Sinatra, others were using Rails, but with CouchDB.
The raison d'ĂȘtre for the heroku_san gem is to make Heroku deploys dirt simple. So, if people are making whole forks to customize the deploy task, we should make it less painful.
One of the many pleasures of working at Pivotal Labs is that we are encouraged to release some of our work as open source. Often during the course of our engagements, we write code that might have wide-spread use. Due to the nature of our contracts, we can not unilaterally release such code. Those rights belong to the client. And rightly so. So, it is an even greater pleasure when one of our clients believes in "giving back" to the community, as well.
One such example is this modest gem, attribute_access_controllable which allows you to set read-only access at the attribute level, on a per-instance basis. For example, let's say that you have a model Person with an attribute birthday, which, for security purposes, cannot be changed once this attribute is set (except, perhaps, by an administrator with extraordinary privileges). Any future attempts to change this attribute will result in a validation error.
e.g.
> alice = Person.new(:birthday => '12/12/12')
=> #<Person id: nil, attr1: nil, created_at: nil, updated_at: nil, read_only_attributes: nil, birthday: "0012-12-12">
> alice.attr_read_only(:birthday)
=> #<Set: {"birthday"}>
> alice.save!
=> true
> alice.birthday = "2012-12-12"
=> "2012-12-12"
> alice.save!
ActiveRecord::RecordInvalid: Validation failed: Birthday is invalid, Birthday is read_only
> alice.save!(:skip_read_only => true)
=> true
Setting this up is trivial, thanks to a Rails generator which does most of the heavy lifting for you.
rails generate attribute_access Person
After that, you need only know about one new method added to your class:
#attr_read_only(*attributes) # Marks attributes as read-only
There are a few others, but this one, plus the new functionality added to #save and #save! will get you quite far.
And if that's all that you were looking for when you stumbled across this article, then there's no need to read any further. Go install the gem and have fun (and may your tests be green when you expect them to be).
When generating sprites with Compass (which is extremely easy), we found that the default output directory for your sprites is the same as the root images directory. This is annoying because we would have to add a line line app/assets/images/icons-*.png to our .gitignore, repeated for each sprite file.
We wanted to put all our sprites in a single folder to be put in .gitignore -- this was easy to find, by adding config.compass.generated_images_dir = 'public/sprites' to our config/application.rb. The next problem was that while the sprite file was correctly being saved to e.g. public/sprites/icons-xxx.png, the client-facing path to the sprite file was still /assets/icons-xxx.png which was always 404ing.
The final answer came from an open pull request on compass-rails which clearly explains that you need to add the output path to the assets path, e.g. config.assets.paths << Rails.root.join('public', 'sprites'). Finally, we can easily add public/sprites to our .gitignore.
The other gotcha we encountered today is that compass-rails only regenerates the sprite file when the sprites CSS file changes, not when you add or remove files from the globbed path.
If you ever spot room for improvement or an error in the Rails documentation -- and that includes the Rails Guides and the API docs -- they've made the process extremely easy. If you've been waiting for "the right moment" to start contributing to open-source software, this might be it.
In Rails 3.1 and newer, when you write a migration by hand, you can (usually) just define a change method instead of an up and a down method.
On my current project, we needed to prove that an action cache was working as expected. Alas, the blogosphere had either out-of-date or unhelpful information. So, after many experiments, we came up with an RSpec test that does what we want. It seems ugly to me, and I hope there's a better way. The names have been changed to protect the guilty. Any resemblances to actual classes and methods are purely coincidental.
Quiz time!
- How many times (each day) have you typed this at your console?
git push heroku masterand then forgotten to runheroku run rake db:migrate --app yellow-snow-3141orheroku ps:restart - Does your script support a multi-stage environments?
- Do you remember how to get to the application's console process?
- Is your application's configuration consistent across all stages?
- Are you deploy scripts tested?
TL;DR
We moved a Rails app into an unbuilt engine of a new blank slate container app to allow new parts of our app to live next to it as engines as well. It has been working great for us!
I have a sample app rails_container_and_engines of the result's structure on github.
Skip to the pitfalls and discoveries section to read about some of the speed bumps we during our transition. Interested in the why and how? Read on!
help
- anybody seen old content showing up on heroku at various points in time (especially at night)?
- crickets ...
interesting
- rake execute takes a hash, rake invoke takes an ordered list
- http://join.me is a cool tool for interactive screen sharing
- don't use anonymous iframes for ajax file upload, use a class or id,
- we saw weird issues with a chat provider who uses an anonymous iframe which was getting all our file upload info
Interesting Things
- There's a new release of Backbone - 0.9.0. It's billed as a release candidate for 1.0, and seems to be a bit buggy, as RCs can be. However, it's exciting to see that Backbone is getting close to that milestone.
- You should default boolean fields to true or false, at the database layer. Otherwise your queries have to deal with three-valued logic.
- Rails 3.2 has some unexpected behavior. First, the generated form ids have changed ... what used to be
id=user_newis nowid=new_user. Second, if your routes file is missing an entry, you will no longer get errors in controller tests. If you liked that behavior, try out request specs.
Ask for Help
- "Anyone seen problems with the latest REE and iconv?"
Everything works on the Linux machines, but on Macs, there's an error about an unrecognized target encoding. Iconv works on the command line, so it's something about REE.
