At Firmhouse we love small pull requests, they help with getting your code reviewed quicker but also with feeling less anxiety when you deploy your code.
Having small pull requests is easy for when you're doing a bug fix, but when working on a feature it get's a bit more tricky. In this post, I want to take you along with how we deal with that!
We find that the best way to keep moving forward with significant features is by using something called Feature Flags. With Feature Flags, you can have functionality running on production and still have it hidden for other people.
The thing with a new feature is that you want to be able to test it on staging, or any other environment other than production. In those cases using a simple
if false; ... end is not going to cut it.
There are a couple of ways to do Feature Flags, the most basic way that we implement at Firmhouse is using Environment Variables.
Let's see how you can set that up for yourself, for this we will be using this "Feature" that we want to hide:
# app/controllers/super_feature_controller.rb class SuperFeatureController < ApplicationController def index #... Some great code that we want to hide end end # app/views/layouts/application.html.erb <html> ...Code omited <nav> <%= link_to "Home", root_path %> <%= link_to "New feature", super_feature_path %> </nav> ..Code omited <html>
If you take a close look at the above code you see that there are two things that we want to "Hide" behind the feature flag, one is the link in the main navigation, and the other part is to prevent people guessing the URL and still be able to use the feature.
Let's first start by actually hiding the URL. We can easily hide the URL by only showing it if the Environment key
SUPER_FEATURE_ENABLED is set.
# app/views/layouts/application.html.erb <html> ...Code omited <nav> <%= link_to "Home", root_path %> <%= link_to("New feature", super_feature_path) if ENV["SUPER_FEATURE_ENABLED"] %> </nav> ..Code omited <html>
Now that the feature is not "visible" to the visitor anymore, we still want to make sure that people that somehow guess the URL not end up at this new feature. We can do this with a
before_action on the controller:
# app/controllers/super_feature_controller.rb class SuperFeatureController < ApplicationController before_action :check_super_feature_enabled def index #... Some awesome code end private def check_super_feature_enabled return if ENV["SUPER_FEATURE_ENABLED"] redirect_to root_path end end
You are now ready to merge this into master and deploy it to production, right away. If you want to test this on, for example, a staging environment you can easily enable the feature by setting the
SUPER_FEATURE_ENABLED environment variable.
Once you feel the feature is ready for a production deploy, just enable the environment variable on production, and you're ready to go! Added benefit of first enabling the feature via the feature flag, is that you can disable it if you notice weird behavior that you did not expect. After a week of running it on production successfully, you can (and probably should) remove the code that we just implemented.
The method I showed you above is the most basic version, for more advanced features we use the library Flipper. With Flipper, we can enable features for just a percentage of users, or a particular user group (for example beta users).