From 2d77f64ae1a5084fec78139af305918f429012d3 Mon Sep 17 00:00:00 2001 From: Trevor Vallender Date: Thu, 25 Jan 2024 15:55:49 +0000 Subject: [PATCH] Initial commit --- MIT-LICENSE | 20 ++++++ README.md | 68 +++++++++++++++++++ flaggle_rock.gemspec | 11 +++ lib/flaggle_rock.rb | 49 +++++++++++++ .../flaggle_rock/install/install_generator.rb | 21 ++++++ .../install/templates/create_feature_flags.rb | 10 +++ 6 files changed, 179 insertions(+) create mode 100644 MIT-LICENSE create mode 100644 README.md create mode 100644 flaggle_rock.gemspec create mode 100644 lib/flaggle_rock.rb create mode 100644 lib/generators/flaggle_rock/install/install_generator.rb create mode 100644 lib/generators/flaggle_rock/install/templates/create_feature_flags.rb diff --git a/MIT-LICENSE b/MIT-LICENSE new file mode 100644 index 0000000..a306f55 --- /dev/null +++ b/MIT-LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2023 David Heinemeier Hansson + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..d666db6 --- /dev/null +++ b/README.md @@ -0,0 +1,68 @@ +# Flaggle Rock + +[View on RubyGems](https://rubygems.org/gems/flaggle_rock) + +Flaggle Rock is a simple feature flagging gem for use with Ruby on Rails applications. + +It is designed for easily hiding features from end users to help enable a fast-moving +CI workflow. It currently does not aim to support more advanced features such as A/B +testing. + +## Installation + +Add Flaggle Rock to your Gemfile: + +```ruby +gem "flaggle_rock" +``` + +And install + +```sh +bundle install +``` + +Generate the migrations, and run them to add feature flags to your database: +```sh +bundle exec rails generate fflag:install +bundle exec rails db:migrate +``` + +## Usage + +All flags are _off by default_. There is no need to explicitly create a new flag—turning +it on will do this. + +To enable/disable a flag: +```ruby +Rock.on(:flag_name) +Rock.off(:flag_name) +``` +To check whether a flag is on: +```ruby +Rock.on?(:flag_name) +Rock.off?(:flag_name) +``` + +To remove a flag which is no longer used: +```ruby +Rock.delete(:flag_name) +``` + +To remove all disabled flags: +```ruby +Rock.delete_all_disabled +``` + +## Future + +Goals with Flaggle Rock include the creation of a web UI for easily administering flags. + +## Compatibility + +Flaggle Rock has been tested with Rails 7 and PostgreSQL 11, but should work with older versions of +Rails and other database engines. + +## License + +Flaggle Rock is released under the [MIT License](MIT-LICENSE.md). diff --git a/flaggle_rock.gemspec b/flaggle_rock.gemspec new file mode 100644 index 0000000..559f354 --- /dev/null +++ b/flaggle_rock.gemspec @@ -0,0 +1,11 @@ +Gem::Specification.new do |s| + s.name = "flaggle_rock" + s.version = "0.1.0" + s.summary = "A simple feature flag gem" + s.authors = ["T S Vallender"] + s.email = "t@tsvallender.co.uk" + s.homepage = "https://git.tsvallender.co.uk/tsv/flaggle_rock" + s.files = Dir["lib/**/*", "MIT-LICENSE", "README.md"] + s.license = "MIT" +end + diff --git a/lib/flaggle_rock.rb b/lib/flaggle_rock.rb new file mode 100644 index 0000000..03cb314 --- /dev/null +++ b/lib/flaggle_rock.rb @@ -0,0 +1,49 @@ +class Rock + def self.turn_on(flag_name) + enable(flag_name, true) + end + + def self.turn_off(flag_name) + enable(flag_name, false) + end + + def self.on?(flag_name) + result = sql <<-SQL + SELECT enabled FROM feature_flags + WHERE name = '#{flag_name}'; + SQL + result&.first&.dig("enabled") || false + end + + def self.off?(flag_name) + !on?(flag_name) + end + + def self.delete(flag_name) + sql <<-SQL + DELETE FROM feature_flags + WHERE name = '#{flag_name}'; + SQL + end + + def self.delete_all_disabled + sql <<-SQL + DELETE FROM feature_flags + WHERE enabled = false; + SQL + end + + private + + def self.enable(flag_name, enabled) + sql <<-SQL + INSERT INTO feature_flags (name, enabled, created_at, updated_at) + VALUES ('#{flag_name}', #{enabled}, now(), now()) + ON CONFLICT (name) DO UPDATE SET enabled = #{enabled}; + SQL + end + + def self.sql(query_string) + ActiveRecord::Base.connection.execute(query_string) + end +end diff --git a/lib/generators/flaggle_rock/install/install_generator.rb b/lib/generators/flaggle_rock/install/install_generator.rb new file mode 100644 index 0000000..d776bb5 --- /dev/null +++ b/lib/generators/flaggle_rock/install/install_generator.rb @@ -0,0 +1,21 @@ +require "rails/generators" +require "rails/generators/migration" + +module FlaggleRock + module Generators + class InstallGenerator < Rails::Generators::Base + include Rails::Generators::Migration + source_root File.expand_path("templates", __dir__) + desc "Generates a migration to create the feature flags table" + + def self.next_migration_number(path) + next_migration_number = current_migration_number(path) + 1 + ActiveRecord::Migration.next_migration_number(next_migration_number) + end + + def copy_migrations + migration_template "create_feature_flags.rb", "db/migrate/create_feature_flags.rb" + end + end + end +end diff --git a/lib/generators/flaggle_rock/install/templates/create_feature_flags.rb b/lib/generators/flaggle_rock/install/templates/create_feature_flags.rb new file mode 100644 index 0000000..8407880 --- /dev/null +++ b/lib/generators/flaggle_rock/install/templates/create_feature_flags.rb @@ -0,0 +1,10 @@ +class CreateFeatureFlags < ActiveRecord::Migration[7.0] + def change + create_table :feature_flags do |t| + t.string :name, null: false, index: { unique: true } + t.boolean :enabled, null: false, default: false + + t.timestamps + end + end +end