Skip to content

Commit

Permalink
Add Redis strategy.
Browse files Browse the repository at this point in the history
  • Loading branch information
rolftimmermans committed Mar 21, 2016
1 parent 1f79ffd commit b7c85e6
Show file tree
Hide file tree
Showing 9 changed files with 148 additions and 4 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ group :test do
end

gem "sqlite3", ">= 1.3", platform: :ruby
gem "fakeredis"
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
gem "minitest", ">= 4.2"
gem "capybara", ">= 2.6"
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ The following strategies are provided:
* `:httponly` – Whether the cookies are accessible via scripting or only HTTP. Default is `false`.
* `:query_string` – Interpret query string parameters as features. This strategy is only used for resolving. It does not allow switching features on/off.
* `:prefix` – String prefix for all query string parameters. Defaults to no prefix.
* `:redis` – Save feature settings in Redis.
* `:client` – Use the specified Redis client instead of `Redis.new`.
* `:prefix` – String prefix for all Redis keys. Defaults to no prefix.
* `:session` – Save feature settings in the current user's application session.
* `:prefix` – String prefix for all session variables. Defaults to no prefix.
* `:default` – Not strictly needed, all feature defaults will be applied if no strategies match a feature. Include this strategy to determine the order of using the default value, and to make it appear in the dashboard.
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ namespace :assets do
end

task :clean do
FileUtils.rm(stylesheet_path)
FileUtils.rm(stylesheet_path) rescue nil
end
end
1 change: 1 addition & 0 deletions lib/flipflop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
require "flipflop/strategies/default_strategy"
require "flipflop/strategies/lambda_strategy"
require "flipflop/strategies/query_string_strategy"
require "flipflop/strategies/redis_strategy"
require "flipflop/strategies/session_strategy"
require "flipflop/strategies/test_strategy"

Expand Down
2 changes: 1 addition & 1 deletion lib/flipflop/strategies/active_record_strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def default_description
end

def initialize(**options)
@class = options.delete(:class) || "Flipflop::Feature"
@class = options.delete(:class) || ::Flipflop::Feature
if !@class.kind_of?(Class)
@class = ActiveSupport::Inflector.constantize(@class.to_s)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/flipflop/strategies/query_string_strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def initialize(**options)
def enabled?(feature)
return unless request?
return unless request.params.has_key?(param_key(feature))
request.params[param_key(feature)].to_s != "0"
request.params[param_key(feature)] != "0"
end

protected
Expand Down
41 changes: 41 additions & 0 deletions lib/flipflop/strategies/redis_strategy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
module Flipflop
module Strategies
class RedisStrategy < AbstractStrategy
class << self
def default_description
"Stores features in Redis. Applies to all users."
end
end

def initialize(**options)
@client = options.delete(:client) || ::Redis.new
@prefix = options.delete(:prefix).to_s.freeze
super(**options)
end

def switchable?
true
end

def enabled?(feature)
redis_value = @client.get(redis_key(feature))
return if redis_value.nil?
redis_value === "1"
end

def switch!(feature, enabled)
@client.set(redis_key(feature), enabled ? "1" : "0")
end

def clear!(feature)
@client.del(redis_key(feature))
end

protected

def redis_key(feature)
@prefix + feature.to_s
end
end
end
end
3 changes: 2 additions & 1 deletion lib/generators/flipflop/features/templates/features.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@

# Other strategies:
#
# strategy :session
# strategy :query_string
# strategy :redis
# strategy :session
#
# strategy :my_strategy do |feature|
# # ... your custom code here; return true/false/nil.
Expand Down
97 changes: 97 additions & 0 deletions test/unit/strategies/redis_strategy_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
require File.expand_path("../../../test_helper", __FILE__)

require "fakeredis"

describe Flipflop::Strategies::RedisStrategy do
before do
Redis.new.flushall
end

describe "with defaults" do
subject do
Flipflop::Strategies::RedisStrategy.new.freeze
end

it "should have default name" do
assert_equal "redis", subject.name
end

it "should have default description" do
assert_equal "Stores features in Redis. Applies to all users.",
subject.description
end

it "should be switchable" do
assert_equal true, subject.switchable?
end

it "should have unique key" do
assert_match /^\w+$/, subject.key
end

describe "with enabled feature" do
before do
Redis.new.set("one", 1)
end

it "should have feature enabled" do
assert_equal true, subject.enabled?(:one)
end

it "should be able to switch feature off" do
subject.switch!(:one, false)
assert_equal false, subject.enabled?(:one)
end

it "should be able to clear feature" do
subject.clear!(:one)
assert_nil subject.enabled?(:one)
end
end

describe "with disabled feature" do
before do
Redis.new.set("two", 0)
end

it "should not have feature enabled" do
assert_equal false, subject.enabled?(:two)
end

it "should be able to switch feature on" do
subject.switch!(:two, true)
assert_equal true, subject.enabled?(:two)
end

it "should be able to clear feature" do
subject.clear!(:two)
assert_nil subject.enabled?(:two)
end
end

describe "with unsaved feature" do
it "should not know feature" do
assert_nil subject.enabled?(:three)
end

it "should be able to switch feature on" do
subject.switch!(:three, true)
assert_equal true, subject.enabled?(:three)
end
end
end

describe "with options" do
subject do
Flipflop::Strategies::RedisStrategy.new(
client: Redis.new(db: 1),
prefix: "my_feature:",
).freeze
end

it "should use prefix and database to resolve parameters" do
Redis.new(db: 1).set("my_feature:one", 1)
assert_equal true, subject.enabled?(:one)
end
end
end

0 comments on commit b7c85e6

Please sign in to comment.