Adam BerlinAdam Berlin
Don't Sweep It Under the Rug
edit Posted by Adam Berlin on Monday January 31, 2011 at 06:33PM

Advice for Rails Performance Optimization

Upcoming Launch

Recently, our team releasing to a large set of users and needed to ensure that our application could meet the performance needs of the new users. Launch day was a month away. Months of steady Agile feature development needed to meet a healthy amount performance engineering.

We started with a few goals in mind. We wanted:

  • data-driven improvements
  • to prefer simple performant code to complex caching strategies
  • to use available tools to provide visualization for badly performing requests

Kevin FitzpatrickKevin Fitzpatrick
Standup 1/31/2011: Don't Fear The Upload
edit Posted by Kevin Fitzpatrick on Monday January 31, 2011 at 11:31AM

Ask for Help

"Does my Rails application on top of Passenger get blocked when I upload a file?"

Nope! Passenger uses plain old apache to buffer the file upload so your application instance is free to service other requests while the upload is finishing.

Lee ByrdLee Byrd
Mongoid Migrations using the Mongo Driver
edit Posted by Lee Byrd on Saturday January 29, 2011 at 06:35PM

In my last post, I modified a Mongoid::Document during a migration in order to access fields that where no longer defined in the class. This time I am using the mongo ruby driver directly to migrate data.

Since I am using Mongoid in this project, I will be using it to access the dependent mongo driver. This will prevent me from having to provide mongo with a connection string in my migration. I am also using mongoid_rails_migrations to roll out the change.

Initial Design

class User
  include Mongoid::Document
  field :first_name
  field :last_name
end

New Design

class User
  include Mongoid::Document
  field :name
end

Migration

class MergeUsersFirstAndLastName < Mongoid::Migration
  def self.up
    #get the mongo database instance from the Mongoid::Document
    mongo_db = User.db

    #query the collection for the fields needed for the migration
    user_hashes = mongo_db.collection("users").find({}, :fields => ["first_name", "last_name"])

    user_hashes.each do |user_hash|
      new_name = "#{user_hash['first_name']} #{user_hash['last_name']}"

      #update the new field
      mongo_db.collection("users").update({"_id" => user_hash["_id"]}, {"$set" => {"name" => new_name}})

      #remove old fields from collection
      mongo_db.collection("users").update({"_id" => user_hash["_id"]}, {"$unset" => { "last_name" => 1, "first_name" => 1}})
    end
  end
end

Resources

MongoDB Ruby Driver Tutorial

Querying with MongoDB Ruby Driver

Updating with MongoDB Ruby Driver

Dan PodsedlyDan Podsedly
Changes to Pivotal Tracker Pricing
edit Posted by Dan Podsedly on Friday January 28, 2011 at 02:21PM

Last week, we announced that we're introducing pricing for Pivotal Tracker. Since then, we've received a great deal of thoughtful and constructive feedback, and we're very grateful that the majority of you have shown support of Tracker’s move to be a paid product. We really appreciate all of your positive comments.

Continue reading below for details about changes to pricing that we're making based on your suggestions, and clarification of some aspects of pricing that may not have been stated clearly, including what remains free.

Gregg Van HoveGregg Van Hove
Standup 1/27/2011: Paperclip hangs?
edit Posted by Gregg Van Hove on Friday January 28, 2011 at 09:12AM

Ask for Help

Some pivots are trying to import a large number of images into paperclip, and it seemed to hang when shelling out to convert at different images.

Suggestions for troubleshooting included:

  • look at the memory usage over the course of the import
  • try running one file many time to see if it's just some bad images

Gregg Van HoveGregg Van Hove
Standup 1/27/2011: Rails server eats your batteries
edit Posted by Gregg Van Hove on Thursday January 27, 2011 at 09:17AM

Ask for Help

A pivot was looking for help with using mod_proxy on apache. It only seemed to want to proxy the root.

The only real suggestion available was to use HAProxy instead, but that wasn't an option for this project

Some pivots were looking for help using bundler together with capistrano, but without rvm.

No real suggestions on what the problem could be.

Some pivots were wondering how long of a time-box they should set aside to get jasmine running in CI.

Consensus was that it should only take about a half-hour.

Interesting Things

  • A pivot noticed that the battery life on his MacBook Air seemed to suddenly drop from about 8 hours down to only 4 hours. After some digging through top, it turned out that running rails server and rake jasmine:ci were causing the machine to never be able to fully enter sleep/hibernate to save battery life. So remember to turn those off when you put your laptop away.

We're pleased to be sponsoring the Open Source Women's Leadership Summit this Friday. We think the work that the RailsBridge community has done is critical to making the Ruby community more diverse and more welcoming to everyone. We know women are significantly under-repesented in the development community as a whole, and in the Ruby community specifically, and we choose not to accept this as inevitable. It was Grace Hopper, after all, who developed this whole idea of programming languages.

Pragmatically, we also see this as an opportunity. Women hold up half the sky, but until recently held down only 3% of the seats at conferences. In a market where everyone is searching for developers, we ignore this large segment of potential developers to our great detriment. Where else are we going to find the potential to double our Ruby community?

And, as our economy slogs its way out of the deepest downturn since the Great Depression, we also see this as an opportunity to even out what has been a very uneven recovery. We have at once deep unemployment and many many unfilled jobs. The jobs are there but they have moved. We are hiring as fast as we find good people and we are certainly not alone. We see RailsBridge as a way to help people develop the skills they need to move to these new jobs, and they're high-paying jobs, too! What better community to enter than one where employers fight to pay you above the median San Francisco income?

The work that RailsBridge started is very important, and is far from done. The work takes a great deal of effort. To that end, we want to celebrate the people who are making this happen. Pivotal Labs is honored to be a sponsor, and to continue to support these fantastic programs with space, time, money and our voice.

Those of you in the San Francisco area, we encourage you to attend and help us celebrate these inspiring leaders, and those of you elsewhere we encourage you to get involved: help get the word out about this exciting movement.

Event Details on EventBrite: OpenSource Women's Leadership Summit

RailsBridge Blog Post

Lee EdwardsLee Edwards
HTTP Basic Authentication and Devise
edit Posted by Lee Edwards on Wednesday January 26, 2011 at 09:48AM

Say you're using Heroku to host a staging version of your app that uses Devise for authentication. You want to keep unwanted visitors out of your staging app, but your app only uses authentication for certain features. You want to block outsiders from accessing the app entirely. Since Heroku doesn't allow you whitelist IP addresses in your webserver config, you might want to try HTTP basic access authentication to provide top-level authentication. Doing this in Rails is pretty straightforward. Let's assume your staging app runs in the "staging environment."

application_controller.rb:

before_filter :authenticate if Rails.env.staging?

protected

def authenticate
    authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
    end
end

See Ryan Bates' Railscast #82 HTTP Basic Authentication for more info.

This will work for most cases. However, since we have Devise installed, this won't work. Devise will enter an infinite loop of redirects unless we tell Warden to set the performed flag.

application_controller.rb:

def authenticate
    authenticate_or_request_with_http_basic do |username, password|
        username == "foo" && password == "bar"
    end
    warden.custom_failure! if performed?
end

But wait, we're still not done. Devise has the ability to use your HTTP Basic Authentication credentials and use it to log into its own authentication system - a cool feature if you want to be able to pass your login credentials over HTTP, perhaps as a simple way to authenticate an API consumer. However, in our case, we want to keep the HTTP Basic Authentication that we require for the entire site separate from the Devise login that we use internal to the app, so we need to disable Devise's ability to capture our HTTP Basic Authentication credentials. In some versions of Devise, this feature is on by default, and in others it is off by default. Check your devise.rb file and make sure you have uncommented the line that disables Devise's http_authenticatable configuration setting.

devise.rb:

config.http_authenticatable = false

Be warned that HTTP Basic Authentication transmits the username and password in clear text, so you should not use this method for applications where a higher level of security is required.

Gregg Van HoveGregg Van Hove
Standup 1/26/2011: Rails bridge is cool
edit Posted by Gregg Van Hove on Wednesday January 26, 2011 at 09:19AM

Ask for Help

Some pivots were looking for experts with google analytics.

A pivot or two has had experience. Splunk was also suggested as a way to get some potentially different analytics, but warnings were given that it can take a while to get everything set up for Splunk to work correctly.

Interesting Things

  • Typus allows easily adding the ability for admin users to edit structured content in your rails app.

  • OpenSource Women's Leadership summit is this Friday. See here for tickets. And check this out for more info

Gregg Van HoveGregg Van Hove
Standup: 1/25/2011:
edit Posted by Gregg Van Hove on Tuesday January 25, 2011 at 09:18AM

Ask for Help

How do you customize the body of the email message in ActionMailer 3.0? Some pivots want an admin user to be able to edit the default version of the email to be sent, but ActionMailer 3.0 no longer allows the body to be set directly.*

One suggestion was to create a new model that has a default body, and allow the admin user to edit and save, and use that to render the body of the email.

Can you require Bundler inside of the same script that is installing it?

No real solutions other that probably trying to look into the Gem API

Interesting Things

  • Amazon has released an email API for sending emails using their servers. Prices start at 10 cents per 1000 messages sent, with breaks for messages coming from within EC2

Other articles: