Code Monkey home page Code Monkey logo

flip's Introduction

Flip — flip your features

Build Status

Flip provides a declarative, layered way of enabling and disabling application functionality at run-time.

This gem optimizes for:

  • developer ease-of-use,
  • visibility and control for other stakeholders (like marketing); and
  • run-time performance

There are three layers of strategies per feature:

  • default
  • database, to flip features site-wide for all users
  • cookie, to flip features just for you (or someone else)

There is also a configurable system-wide default - !Rails.env.production?` works nicely.

Flip has a dashboard UI that's easy to understand and use.

Feature Flipper Dashboard

Install

Rails >= 4.0

# Gemfile
gem "flip"

# Generate the model and migration
> rails g flip:install

# Run the migration
> rake db:migrate

# Include the Feature model, e.g. config/initializers/feature.rb:
require 'feature'

Declaring Features

# This is the model class generated by rails g flip:install
class Feature < ActiveRecord::Base
  extend Flip::Declarable

  # The recommended Flip strategy stack.
  strategy Flip::CookieStrategy
  strategy Flip::DatabaseStrategy
  strategy Flip::DefaultStrategy
  default false

  # A basic feature declaration.
  feature :shiny_things

  # Override the system-wide default.
  feature :world_domination, default: true

  # Enabled half the time..? Sure, we can do that.
  feature :flakey,
    default: proc { rand(2).zero? }

  # Provide a description, normally derived from the feature name.
  feature :something,
    default: true,
    description: "Ability to purchase enrollments in courses"

end

Checking Features

Flip.on? or the dynamic predicate methods are used to check feature state:

Flip.on? :world_domination   # true
Flip.world_domination?       # true

Flip.on? :shiny_things       # false
Flip.shiny_things?           # false

Views and controllers use the feature?(key) method:

<div>
  <% if feature? :world_domination %>
    <%= link_to "Dominate World", world_dominations_path %>
  <% end %>
</div>

Feature Flipping Controllers

The Flip::ControllerFilters module is mixed into the base ApplicationController class. The following controller will respond with 404 Page Not Found to all but the index action unless the :something feature is enabled:

class SampleController < ApplicationController

  require_feature :something, :except => :index

  def show
  end

  def index
  end

end

Dashboard

The dashboard provides visibility and control over the features.

The gem includes some basic styles:

= content_for :stylesheets_head do
  = stylesheet_link_tag "flip"

You probably don't want the dashboard to be public. Here's one way of implementing access control.

app/controllers/admin/features_controller.rb:

class Admin::FeaturesController < Flip::FeaturesController
  before_action :assert_authenticated_as_admin
end

app/controllers/admin/strategies_controller.rb:

class Admin::StrategiesController < Flip::StrategiesController
  before_action :assert_authenticated_as_admin
end

routes.rb:

namespace :admin do
  resources :features, only: [ :index ] do
    resources :strategies, only: [ :update, :destroy ]
  end
end

mount Flip::Engine => "/admin/features"

Cacheable

You can optimize your feature to ensure that it doesn't make a ton of feature calls by adding Cacheable to your model.

extend Flip::Cacheable

This will ensure that your features are eager loaded with one call to the database instead of every call to Flip#on? generating a call to the database. This is helpful if you have a larger Rails application and more than a few features defined.

To start or reset the cache, just call #start_feature_cache.


Created by Paul Annesley Copyright © 2011-2013 Learnable Pty Ltd, MIT Licence.

flip's People

Contributors

acoravos avatar bak avatar bsharpe avatar carloslopes avatar jasonblalock avatar jcoyne avatar joefiorini avatar kache avatar kcm avatar kwent avatar lenidot avatar mwitek avatar olleolleolle avatar pda avatar pewniak747 avatar piotrze avatar ryanhouston avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

flip's Issues

Clearing out old feature flags

Hi, thanks for building Flip! It works perfectly for what we need.

I was wondering what is the recommended process for clearing out old feature flags. Presumably you remove any Flip conditional statements in the code and remove the corresponding feature definition from Feature. But this still leaves around old feature flags in the database and in cookies. Would it make sense to clean those up as well, or do you just leave them around?

Rails 3.2 support dropped? undefined method `before_action'

Did the new version, 1.1.0 drop Rails 3.2 support?
I'm getting this error

NoMethodError: undefined method `before_action' for ActionController::Base:Class

    Did you mean? before_filter

            Loader at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/flip-1.1.0/lib/flip/cookie_strategy.rb:55
       module_eval at org/jruby/RubyModule.java:2356
   append_features at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/activesupport-3.2.22.4/lib/active_support/concern.rb:121
           include at org/jruby/RubyModule.java:2137
            Engine at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/flip-1.1.0/lib/flip/engine.rb:5
     instance_exec at org/jruby/RubyBasicObject.java:1623
               run at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/initializable.rb:30
  run_initializers at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/initializable.rb:55
              each at org/jruby/RubyArray.java:1613
  run_initializers at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/initializable.rb:54
       initialize! at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/application.rb:136
    method_missing at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/railtie/configurable.rb:30
            (root) at /Users/andrei/projects/cloudstats/config/environment.rb:5
           require at org/jruby/RubyKernel.java:1040
            (root) at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/activesupport-3.2.22.4/lib/active_support/dependencies.rb:1
           require at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/activesupport-3.2.22.4/lib/active_support/dependencies.rb:251
   load_dependency at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/activesupport-3.2.22.4/lib/active_support/dependencies.rb:236
           require at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/activesupport-3.2.22.4/lib/active_support/dependencies.rb:251
     instance_eval at org/jruby/RubyBasicObject.java:1594
        parse_file at /Users/andrei/projects/cloudstats/config.ru:3
        initialize at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/rack-1.4.7/lib/rack/builder.rb:51
              eval at org/jruby/RubyKernel.java:1079
        parse_file at /Users/andrei/projects/cloudstats/config.ru:0
        parse_file at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/rack-1.4.7/lib/rack/builder.rb:40
               app at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/rack-1.4.7/lib/rack/server.rb:200
               app at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/commands/server.rb:46
       wrapped_app at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/rack-1.4.7/lib/rack/server.rb:304
             start at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/rack-1.4.7/lib/rack/server.rb:254
             start at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/commands/server.rb:70
               tap at org/jruby/RubyKernel.java:1858
            (root) at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/commands.rb:55
           require at org/jruby/RubyKernel.java:1040
            (root) at /Users/andrei/.rvm/gems/jruby-1.7.23/gems/railties-3.2.22.4/lib/rails/commands.rb:50

Gem release?

Any chance of getting a gem release soon with the Rails 4 support? Thanks!

Feature model should be namespaced

In case of an application has a real model called feauture.rb, which is not rare, we are not able to use this gem. Have you even thought about that? Any idea to change this soon?

Requiring Feature Model Required?

Is it actually a requirement to require the feature model in an initializer as stated in the README? I can't seem to find a reason why it would be.

Dashboard doesn't work for me

I'm on Rails 4.2.2. The dashboard is just a blank page.
And I don't really understand how features get added to the database.

ActiveSupport conflict causes Bundler to fail on Rails 5.0

Flip requires activesupport-4.2.6, and rails-5.0.0 requires activesupport-5.0.0, so Bundler chokes on the dependency requirements.

Is there a known issue with activesupport-5.0.0 that Flip can't work out of the box with that version?

Differentiate between "on" and "on for current user"

I built a new strategy that basically lets me toggle whether or not a feature is on for a known set of users (like all employees). This all works fine, but if I'm logged in as a non-employee looking at the feature settings it would show the toggle as "off" because it conflates a flag being on with a flag applying to me. Ideally these would be separate so that I could see the status of a flag as it applies globally and switch it. I realize that this is backwards from how the cookie strategy has to work, since it has local scope, but the api should probably handle the broader case.

is this gem maintained anymore

@pda are you accepting any new features for this gem? I've noticed PR's going stale and I have something I'd like to contribute but I'm not gonna waste my time if this gem is no longer getting any attention from you.

Features aren't declared until Feature model has been required.

Only tested in development, but until the Feature model has been loaded, any call to a Flip.on? :blarg will raise No feature declared with key :blarg.

If you simply place require 'feature' before a call, then the problem will go away (even for subsequent requests AFTER removing the require 'feature' line).

Is it easy enough to include a load method in Flip, which checks for initialization and requires 'feature' if it's not available?

Flip → Flipflop?

Flip has not been actively maintained. @rolftimmermans created a backwards-incompatible fork called Flipflop which looks in far better shape. Should Flipflop completely replace Flip? I can see a few ways forward:

  1. Merge Flipflop into Flip, tag it as v2.0.0, release the v2 gem, give @rolftimmermans / @voormedia full access to flip on GitHub and RubyGems. That doesn't rule out maintaining a v1 branch for backwards-compatible fixes. It would make sense in this option to shut down https://github.com/voormedia/flipflop pointing people to flip.
  2. Officially halt development on Flip, close all issues and PRs, modify the README to endorse migration to Flipflop.
  3. Bring some collaborators in to continue development on Flip, keep it separate from Flipflop. I think this only makes sense if it's to keep flip reasonably backwards-compatible compared to the breaking changes and trickier migration to Flipflop (assuming that's true?).
  4. ¯_(ツ)_/¯

In all cases, existing commits, tags and gem releases of flip would continue to work.

/cc @rolftimmermans @kwent @jcoyne @olleolleolle @jippeholwerda as recent contributors (sorry if I responded late or never to your PRs!)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.