Sapling Gem

Sapling lets you seed your new features to just a few users at a time. You can change which and how many users are seeded for a feature dynamically by updating the database via the Sapling API. Core features are the ability to seed a feature for specific users and/or a percentage of users.

Heritage

This is a port of the rollout gem for use with ActiveRecord instead of Redis. We dropped the groups functionality, but otherwise we mirrored the API.

Setup

Add a route to your routes file. Feel free to change the 'sapling/stylesheet.css' to whatever you want.

map.sapling_script 'sapling/script.js', :controller => 'sapling', :action => 'script'

After including your javascript library, add this:

<%= javascript_include_tag sapling_script_path, :id => 'sapling_script' %>

Run the db/create.sql file to create the sapling_settings table on your DB

Ensure you have a current_user method to your application controller, which returns a user object, or nil if no active user.

class ApplicationController < ActionController::Base
  ...
  def current_user
    # Return your current user
    # This is already done for you in Devise, RestfulAuthentication, and other authentication lib
  end
  ...
end

For a given feature space_chat,

Server-side Usage

To check if a feature is enabled for a user in rails controllers or views: use

sapling.active?(:space_chat [, :user => the current user])

Note: sapling will automatically populate the user argument by calling current_user

To get the css classes the javascript adds to the HTML element for a feature:

sapling.css_class(:space_chat)
sapling.css_toggle_class(:space_chat)

To enable a feature for a specific user, in the rails console:

Sapling::ActiveRecord.new.activate_user(:space_chat, space_admin)

To disable a feature for a specific user, in the rails console:

Sapling::ActiveRecord.new.deactivate_user(:space_chat, space_admin)

To enable a feature for 50% of the users, in the rails console:

Sapling::ActiveRecord.new.activate_percentage(:space_chat, 50)`

To disable a feature activated for anyone but individually-activated users, in the rails console:

Sapling::ActiveRecord.new.deactivate_percentage(:space_chat)

Note: Individually-activated users are always activated, regardless of the percentage setting. A deactivated user may still have access to a feature if they fall within an active percentage.

Custom Feature-Active Tests

You can optionally inject your own code for testing if a feature is active. In rails, just added methods of the following form to your ApplicationController:

# Example: override feature-active? for feature :new_homepage
#
# options:
#   :feature => object of type Sapling::Feature
#       (current settings for the feature from the database)
#   :active => true if the feature would be active without the override
#
# remaining options are those passed to 'sapling.active?'
#   :user => user to test for feature-active
#   :context_id => Integer
#
# return true if the feature is active.
def new_homepage_active?(options={})
  # your test here
end

Note If you are using Sapling manually, when you create a Sapling instance, you can pass in an any object which responds to "current_user" and implements zero or more of your feature-active overrides.

Client-side Usage

Sapling include a javascript helper which adds and removes classes on the HTML element for a given user, based upon the features available to that user.

Given the feature space_chat, if it is enabled for the given user, the html root will get the class sapling_feature_space_chat_on. If disabled for the given user, the class will be sapling_feature_space_chat_off.

To retrieve the class name for a given feature, you can use sapling.css_class(feature) and sapling.css_toggle_class(feature, on? (boolean) ) in your ERB files.

Using the client-side tools, you can define CSS classes which will be visible/invisible when a feature is enabled/disabled. For example:

CSS:

/* Chat Defaults to being hidden for everyone */
.sapling_feature_chat.enabled {
  display: none;
}
.sapling_feature_chat.disabled {
  display: block;
}

/* When chat is enabled, we hide the disabled container, and show the enabled container */
html.sapling_feature_chat_on .sapling_feature_chat.enabled {
  display: block;
}
html.sapling_feature_chat_on .sapling_feature_chat.disabled {
  display: none;
}

ERB:

<div class="<%= sapling.css_class(:chat) %> enabled">
  REJOICE - SPIFF CHAT ENABLED FOR YOU
</div>

<div class="<%= sapling.css_class(:chat) %> disabled">
  DESPAIR - SPIFF CHAT NOT ENABLED FOR YOU
</div>

Note Currently, the javascript generated depends on MooTools being loaded first.

TODO

  • Rails 3 compatibility
  • Remove mootools dependency
  • Database migration generator