Pivotal Labs

Main menu

Skip to primary content
Skip to secondary content
  • About
  • Case Studies
  • Team
    • Executives
    • Locations
      • San Francisco (HQ)
      • Boston
      • Boulder
      • Denver
      • London
      • Los Angeles
      • New York
  • Community
    • Blogs
    • Tech Talks
    • Events
  • Careers
    • Lifestyle
    • Principles & Practices
    • Benefits
    • FAQ
    • Apply
  • Tools
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Onsi Fakhouri

[SF] Standup 4/25/2012: Haproxymations

Onsi Fakhouri
Wednesday, April 25, 2012

Ask for Help

What’s the best way to think about redirects for API calls? e.g. You post to create an object, what should you get in return?

The crowd: Some concensus emerged around: send back a 201 with a location header pointing to the url for the object and a body containing the object itself.

Mongoid’s atomic operations don’t trigger hooks (before_save, after_save, etc…)

The crowd: Crickets…

haproxy, like nginx, can pass http connection through with the header ‘X-Forwarded-For’ set so that it is possible for the app to know the original client IP. But haproxy doesn’t have support for serving as an SSL endpoint, so https:// connections are proxied in tcp mode instead of http mode. And no headers can be added because the request remains encrypted.

Some solutions:

  • Terminate the SSL connection in front of haproxy. PIvots suggested doing this via an additional nginx instance. Online resources show how to do this using stunnel. (http://www.completefusion.com/ssl-load-balancing-with-haproxy-and-stunnel-on-debian/)

  • Use nginx as the load balancer and discontinue using haproxy, or find a load balancer that fully supports SSL.

  • Build HAProxy with TPROXY support. http://blog.loadbalancer.org/configure-haproxy-with-tproxy-kernel-for-full-transparent-proxy/

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Cathy O'Connell

NYC Standup 04/24/2012: Loading OBJECTS through associations..

Cathy O'Connell
Tuesday, April 24, 2012

Interesting Things

  • When you load objects through associations, you should be aware of how the objects are being loaded. If a where statement is used the calls are being translated to SQL and always hitting the database.

example

it "should whatever" do
      foo.bars.where(something: true).each { |bar|        bar.modify_something }
      foo.bars.each { |bar| bar.expect_something_to_be_modified }
end
  • This will fail as the first call is not only limiting the association but also loading different objects to the second foo.bars collection.

  • Choosing first on a has_many association is dangerous. There are two ‘first’ functions a class and an array one. Depending on whether the association is loaded, a different method is called.

example

it "should do something with the first element" do
    foo.bars.first.modify_something
    foo.bars(:force_load).first
end
  • To ensure loading occurs and thus the object is the same on every call, you can provide any value that evaluates to true as part of the association call. Here :force_load symbol, evaluates to true and forces a database load for bars.

Events This Week

Tuesday:

  • 12:30- Brownbag
  • 6:30- NYC.rb Hackfest

Thursday:

  • 6:30- NYC Ruby Women Hackfest + Chat
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Aaron VonderHaar

Standup 04/24/2012: Make testing email (almost) pleasurable

Aaron VonderHaar
Tuesday, April 24, 2012

Ask for Help

URL helpers with Draper must be mocked under test. Any better solutions?

  • Add a default host environment in the test setup?
  • Try view tests?

ruby-debug w/ 1.9.3 and RubyMine 4.0.3 => dyld: symbol not found

  • Use debugger gem

Other helps?

… No.

Interesting Things

  • For testing – thin default logger (no one claimed this)
  • debugger gem – use it! (see Helps)
  • Use litmus to help debug how your emails look on multiple platforms (blog post forthcoming?)
  • Don’t start a new rails project today (well, maybe if you use non-SSL rubygems). http://railsapps.github.com/openssl-certificate-verify-failed.html
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Jeff Saracco

Standup 04/12/2012 -

Jeff Saracco
Thursday, April 12, 2012

Interestings

  • Chrome JsonViewer plugin – pretty prints JSON useful for debugging. Also some people use Awesome Print for similar functionality

  • ElementalJS

  • jquery_currency

  • Arel now has distinct, otherwise a work-around like
    #scope#.clone.tap { |arel| select_value = [ 'DISTINCT users.*'] }
    is used

  • Amazon released CloudSearch today – an Amazon hosted search service

Helps

  • How to use Twitter Bootstrap SASS semantically?
    • “span3″ sucks
    • “@extend span3″ breaks

Events

  • Anyone interested in hardware hacking (arduino, etc…) see Fader or Berger
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Jeff Saracco

Standup 04/10/2011: How to succeed in business like a ninja

Jeff Saracco
Tuesday, April 10, 2012

Interesting

  • Facebook bought Instagram for $1 billion

Events

Today:

Brownbag Enterprise-Fu or How to succeed in business (like a ninja)

NYC.rb – Lean startup

Wednesday:

Libs@Lunch: book club has been moved to lunch time so more people can come
This week they will be finishing smalltalk best practices and will be choosing the next book

Lean UX roundtable – JB will be speaking, see him for more info or if you would like to attend

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ken Mayer

TDD Action Caching in Rails 3

Ken Mayer
Wednesday, March 28, 2012

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.

We needed to confirm that a certain action was cached. This action is preview in the brands controller. Using the usual Rails url helpers, we construct some fixture data.

describe BrandsController do
  describe "caching" do
    let(:brand) { Factory.create(:brand) }
    let(:preview_cache_path) {'views/test.host' + preview_brand_path(brand)}
  end
end

Then we wrote our first test:

it "should action cache #preview" do
  Rails.cache.clear
  get :preview, :brand_id => brand.to_param
  ActionController::Base.cache_store.exist?(preview_cache_path).should be_true
end

This won’t work at all, however; because, in the test environment, caching is turned off.

$ cat config/environments/test.rb
Activator::Application.configure do
...
  config.action_controller.perform_caching = false

So, we need an around block to temporarily turn caching on:

around do |example|
  caching, ActionController::Base.perform_caching = ActionController::Base.perform_caching, true
  example.run
  ActionController::Base.perform_caching = caching
end

That’s great, but the default cache store is the :null store, which, as its name implies, does nothing.

around do |example|
  caching, ActionController::Base.perform_caching = ActionController::Base.perform_caching, true
  store, ActionController::Base.cache_store = ActionController::Base.cache_store, :memory_store
  example.run
  ActionController::Base.cache_store = store
  ActionController::Base.perform_caching = caching
end

Better. But our tests still won’t run because while ActionController uses the cache_store, Observers and Sweepers
use Rails.cache and that is only updated at boot time.

around do |example|
  caching, ActionController::Base.perform_caching = ActionController::Base.perform_caching, true
  store, ActionController::Base.cache_store = ActionController::Base.cache_store, :memory_store
  silence_warnings { Object.const_set "RAILS_CACHE", ActionController::Base.cache_store }

  example.run

  silence_warnings { Object.const_set "RAILS_CACHE", store }
  ActionController::Base.cache_store = store
  ActionController::Base.perform_caching = caching
end

Did I mention that Rails.cache is an accessor for the global, constant, RAILS_CACHE. Ugh.

So, now, we can implement our method

class BrandsController < ApplicationController
caches_action :preview
  def preview
  end
end

But that is still not enough. caches_action
has an interesting performance enhancement; it doesn’t actually set up the action caching unless caching is enabled at class load time. Since we’re not turning caching on until test time, the caches_action method call in the controller class does nothing. We need to re-add it in our test spec.

it "should action cache #preview" do
  Rails.cache.clear
  BrandsController.caches_action :preview # must be recapitulated to get around load time weirdfullness

  get :preview, :brand_id => brand.to_param

  ActionController::Base.cache_store.exist?(preview_cache_path).should be_true
end

This is ugly; it doesn’t test very much (except the underlying caching module, and why bother testing the framework). At least it proves to ourselves that the action is cached and the cache key is what we expect.

Now that we’ve got caching under control, let’s check cache expiration (using a Sweeper).

it "should clear the cache on #update" do
  ActionController::Base.cache_store.write(preview_cache_path, 'CACHED ACTION')

  put :update, id: brand.to_param, brand: {one: 'attribute', after: 'another'}

  ActionController::Base.cache_store.exist?(sign_up_cache_path).should be_false
end

First, I create a cached object, in this case, just the string ‘CACHED ACTION’ and then I invoke the action, and then, I hope, the cache will be expired.

It doesn’t really matter what happens in the #update method of the BrandsController as long as it updates a Brand object. A sweeper in Rails is a mix of Observer & controller filters, so all you need to do is “declare” it in the controller

class BrandsController < ApplicationController
caches_action :preview
cache_sweeper :brand_sweeper
def update
  ...
  @brand.save

Awesome sauce! Now our tests are red and I’m ready to implement the sweeper

class BrandSweeper < ActionController::Caching::Sweeper
  observe Brand # Observers will introspect on the class, but Sweepers don't

  def after_update(brand)
    expire_action :controller => "brand", :action => :preview, :brand_id => brand.to_param
  end
  ...

And voilĂ ! We have greenness.

So what have we learned from this? The Rails source is still your best friend when exploring a sticky problem. Caching is hard, and testing caching is even harder.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Brent Wheeldon

03/26/2012 NYC Standup

Brent Wheeldon
Monday, March 26, 2012

Ask for Help

“Has anyone used cucumber for code coverage? We’re trying to find dead code.”

SimpleCov worked great for rspec, but when used with cucumber introduced a lot of timeouts.

Interesting Things

  • In rspec you can use dot notation as the argument on its calls, for example:
        its(:"items.count") { should == 5 }
    
  • Scrollorama – The jQuery plugin for doing cool scrolly stuff.
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ken Mayer

Dry DevOps with heroku_san

Ken Mayer
Sunday, March 25, 2012

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?

Yeah, me too.

Enter heroku_san, the 85% solution, which allows me to do this:

$ rake staging deploy

And this is what happens: Maintenance mode is turned on; the latest green build is deployed to my staging server; all pending migrations are run, the app restarted, and then maintenance mode disabled. All while I go get a fresh cup of joe.

The value for us is that we don’t repeat ourselves, that our app will deploy, and we are confident that extending the toolkit is easy with a clear API and good test coverage. That’s a big win when you have dozens of apps deploying all day long.

Installation is pretty simple; add gem 'heroku_san' to your Gemfile (you are using Bundler, aren’t you?). This gem is only used locally, so you can add it to your group :development, :test block. Then create and edit a configuration file; config/heroku.yml[1]. The README file has more details and there’s a wiki on github with handy tips on how to extend the basic functionality in common ways.

So, why?

The gem has been around since 2010 and supported by a loyal core of maintainers. Version 2.1.1 brings changes large and small.

The biggest change since v1.3 is the creation of 2 new classes: Project and Stage, and a test suite to drive out the features. The task library is now almost entirely simple method calls, so there’s a lot of confidence that they will run correctly. Just to make sure, however, I’ve written an integration test, remote.feature which exercises the whole stack by creating an app on Heroku and run it through its paces. It’s worth a read.

There are some other new features worth highlighting:

  • Heroku stack support (aspen, bamboo and cedar)
  • Direct use of the Heroku::Client (instead of calls out to the shell)
  • tags — By adding an (optional) tag configuration value to your heroku.yml file, heroku_san will deploy only the most recent revision with that tag to your stage. This is great for creating a multi-stage environment, and when combined with auto_tagger and a continuous integration server (CI), you get a lot of bang for a little bit. See the wiki for more complete instructions.

tl;dr

Why write your own deploy scripts, again. Use heroku_san (or another gem like kumade)


Notes

[1]: I am working hard to remove the Rails dependencies.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Andrew Bruce

SF Standup – March 1st, 2012: so who’s deployed Carrierwave?

Andrew Bruce
Thursday, March 1, 2012

Requests for help

“How do I avoid compiling gems on production servers?”

Apparently there’s a project that Chef uses that packages dependencies into an installer.

Also, FPM is potentially a good solution.

Interesting

Survey: who’s actually deployed Carrierwave?

2 people said they had.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Andrew Bruce

SF Standup – February 28th, 2012: what does i18n stand for?

Andrew Bruce
Tuesday, February 28, 2012

Requests for help

“simple_form i18n labels for namespaced models i.e. Foo::Bar”

The requester wasn’t around, but we assumed the namespacing causes problems. No suggestions except “don’t namespace models”…

“On Ruby 1.8.7, Jasmine is timing out on startup after 60s. The project has a lot of fixtures and tests. Mongrel seems to block itself and then waits. Any ideas?”

A lot of blank faces.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (783)
  • rails (117)
  • testing (90)
  • ruby (86)
  • ruby on rails (71)
  • jobs (62)
  • javascript (59)
  • techtalk (44)
  • ironblogger (42)
  • rspec (39)
  • bloggerdome (34)
  • productivity (34)
  • activerecord (30)
  • rubymine (30)
  • git (29)
  • gogaruco (29)
  • nyc (27)
  • design (24)
  • mobile (23)
  • pivotal tracker (22)
  • process (21)
  • cucumber (21)
  • jasmine (19)
  • ios (18)
  • tracker ecosystem (17)
  • webos (17)
  • objective-c (17)
  • fun (16)
  • android (16)
  • palm (16)
  • ci (16)
  • "soft" ware (16)
  • bdd (15)
  • tdd (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • css (14)
  • gem (13)
  • mouse-free development (12)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • api (12)
  • keyboard (11)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
Subscribe to agile Feed
  1. ←
  2. 1
  3. ...
  4. 11
  5. 12
  6. 13
  7. 14
  8. 15
  9. 16
  10. 17
  11. ...
  12. 79
  13. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • Tools
  • Contact
  • Labs
  • Events

Contact Us

contact@pivotallabs.com
+1 415-77-PIVOT
TwitterLinkedInFacebook

Pivotal Tracker

Tracker is the award-winning agile project management tool that enables real-time collaboration around a shared, prioritized backlog.
Visit pivotaltracker.com >