Ken Mayer's blog



Ken MayerKen Mayer
Deploy strategies for HerokuSan
edit Posted by Ken Mayer on Monday May 14, 2012 at 09:42AM

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.

Ken MayerKen Mayer
From customer requirements to releasable gem
edit Posted by Ken Mayer on Sunday May 13, 2012 at 11:42AM

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).

Ken MayerKen Mayer
TDD Action Caching in Rails 3
edit Posted by Ken Mayer on Wednesday March 28, 2012 at 08:10PM

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.

Ken MayerKen Mayer
Dry DevOps with heroku_san
edit Posted by Ken Mayer on Sunday March 25, 2012 at 02:23PM

Quiz time!

  1. How many times (each day) have you typed this at your console? git push heroku master and then forgotten to run heroku run rake db:migrate --app yellow-snow-3141 or heroku ps:restart
  2. Does your script support a multi-stage environments?
  3. Do you remember how to get to the application's console process?
  4. Is your application's configuration consistent across all stages?
  5. Are you deploy scripts tested?

Ken MayerKen Mayer
SF Standup - Feb 13, 2012 - The Sound of One Hand
edit Posted by Ken Mayer on Monday February 13, 2012 at 09:00AM

Cries for help

Capybara is reporting "stale elements" for no good reason.

Any experience, war stories upgrading from jQuery 1.6 to 1.7, especially with the whole event delegation API change? [crickets] See interestings...

Interestings

Have a really big spec file that takes a long time to run? http://rubygems.org/gems/parallel_split_test, from our own Michael Grosser, will run a big spec file in smaller chunks.

url helpers cache results for better performance, but they seem to be losing custom options (in this case a locales setting).

In jQuery 1.6, triggering an event in an unattached DOM node would propagate the event up into the document, even though it was never attached to it. jQuery 1.7 (maybe 1.7.1) fixes this behavior.

Ken MayerKen Mayer
Social Chorus is looking for a Ruby on Rails Engineer
edit Posted by Ken Mayer on Wednesday January 18, 2012 at 11:24AM

At Pivotal Labs, one of the services we provide our clients is helping them interview and hire. Pivotal Labs and our clients place a strong emphasis on Agile development and its many aspects: Pair Programming, Test-Driven Development, rapid iterations, and frequent refactoring.

Halogen Media Group merged with YouCast Corp. to collaborate in forming a powerhouse of technology, Social Chorus (http://socialchorus.com), that measures social reach through paid and earned media through influencer distribution.

Here's the job posting:

Ken MayerKen Mayer
SF Standup 8/12/2011: Helpers All The Way Down
edit Posted by Ken Mayer on Friday August 12, 2011 at 11:37AM

Ask for Help

"clear_helpers and ActionController::Base"

A [recent?] change to Rails 3 moved helper :all from the default ApplicationController to ActionController::Base -- which would be fine, except that there's little documentation on how to override this (for example, when you don't want all helpers included in your controller class)

There is a lesser known method from AbstractController::Helpers

# Clears up all existing helpers in this class, only keeping the helper
# with the same name as this class.
def clear_helpers

You would think that since helper :all is being called from the base class, there would be no way to override it. Except for this little bit of code at the bottom of ActionController::Base:

def self.inherited(klass)
  super
  klass.helper :all if klass.superclass == ActionController::Base
end

So, clear_helpers will "work" for all subclasses of ApplicationController -- which is everything you should care about. And the default, all helpers included, remains.

Ken MayerKen Mayer
[SF Standup 8/9/2011]: Answering our own questions
edit Posted by Ken Mayer on Tuesday August 09, 2011 at 10:00AM

Ask for Help

"Does the selenium driver send mouse events?"

Yes... but, for drag and drop testing, it is often impossible to get right. The best alternative is to use the jQuery simulate plugin as mentioned in the jQuery forum

"Why does AREL make some associations read-only (and then raise ActiveRecord::ReadOnly exceptions)?"

This happens around associations that create compound objects (such as by the popular paperclip gem), where AR can't know what is writable and what isn't. The solution (as blogged about many times), is to include a :select => 'foo.*' in your query to pull out only the writable attributes.

"Be wary of using RR to stub class methods in ActionMailer"

It has something to do with both ActionMailer and RR using method_missing and, of course, not playing nicely together. The other solution mentioned was to stub on .any_instance instead of the class methods. Other references Pivotal Blabs-NY Standup and Technical.Pickles.

Ken MayerKen Mayer
Skype's automatic gain control driving you INSANE?
edit Posted by Ken Mayer on Friday July 15, 2011 at 08:46AM

If you're working in an environment with a noisy background, Skype's über-friendly automatic gain control can drive you crazy (open up sound preferences and watch your input levels change like magic)

Here's a fix (that still works in Skype 5):

http://jon.smajda.com/2011/04/19/disable-automatic-gain-control-in-skype

Ken MayerKen Mayer
[Standup][sf] 5/20/2011 DVORAK? I hardly knew her!
edit Posted by Ken Mayer on Friday May 20, 2011 at 11:55AM

Helps

"Can I use after_initialize to set up nested associations for use with Controller#new actions?"

Not recommended. It is better to write a custom #new_for_form method in your model that pre-populates your instance variables with the 1 or more nested objects. That way you can test drive it, too.

"DelayedJob YAML parser in Ruby 1.9 is having issues."

The compiled-in psych library has issues, use the tenderlove/psych gem instead. You have to use Bundler, however. Invoking require "psych" will use the compiled-in version.

"RubyMine is not honoring a DVORAK keyboard layout properly (it is mapping keyboard shortcuts to the QWERTY layout)"

Use a hardware dongle.

"Jenkins is trying to kill off Postgres?"

Does anyone have Jenkins CI working with Postgres? It seems that after a build is complete, some java deep down inside Hudson is trying to parse the process table, and it is choking on the Postgres entries. (Postgres re-writes ARGV[0] to display status info, you can't rely on it be the original command line.) It remains a mystery why Jenkins would even need this information.

"Is anyone using Chrome in CI? The windows are transparent"

Sounds pretty. Odd, but pretty.

Interesting

"brew info ... is your friend"

Can't remember how to start or stop a daemon under OS X? If you installed it via Homebrew you are in luck:

brew info <foo>

Will print out the original install instructions, including exact lines to pass to launchctl(1), etc.

"More 'special' keywords to avoid in your models: target and source"

ActiveRecord Polymorphic Associations use a method called target internally. If you have an attribute in your model / database, also called target, then strange things will happen.

"Paperclip's <model>.attachment.exists? is slow; it goes out to S3 (or whatever the store is)"

And it happens in strange places. Be warned. Or mock out your network calls.

Other articles: