Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 21, 2021 03:38 pm GMT

Use Pundit as a Rails Feature Flag System

In this tutorial, I'll show you how to create a feature flag system in Rails using pundit and a features column on the users table.

Resources

Step 1: Initial Setup

This tutorial assumes you are using devise and have a User model. However, you should still be able to follow along and implement this pattern even if that's not the case.

  1. Create a Post scaffold.
rails g scaffold Post title:string user:references meta_description:text
  1. Add a features column to the users table by running the following command.
rails g migration add_features_to_users features:jsonb 
  1. Set a default value on the features column.
class AddFeaturesToUsers < ActiveRecord::Migration[6.1]  def change    add_column :users, :features, :jsonb, default: {}  endend

What's Going On Here?

  • We add a JSONB Column to our users table. This will allow us to store multiple features in one column, compared to making a column for each feature.
  • We add default: {} simply to add a formatted default value to this column.
  1. Run the migrations.
rails db:migrate
  1. Set features on User model.
class User < ApplicationRecord  ...    FEATURES = %i[enable_post_meta_description].freeze  store :features, accessors: User::FEATURESend

What's Going On Here?

  • We create a FEATURES constant that will store the names of our features as symbols by calling %i on the array. We call .freeze to ensure this constant cannot be updated anywhere else.
  • We use ActiveRecord::Store to interface with the features column. This will allow us to call @user.enable_post_meta_description instead of user.features.enable_post_meta_description. By passing User::FEATURES into the accessors parameter we can continue to add new features in the FEATURES constant.

Setting a features column on the users table will allow us to enable/disable features on a per-user basis.

  1. Enable the enable_post_meta_description for a user. That way you have something to test.
User.last.update(enable_post_meta_description: true)

Step 2: Install Pundit and Build a Policy

Next, we'll need to install and configure pundit.

  1. Install pundit.
bundle add pundit
  1. Generate the base pundit files.
rails g pundit:install
  1. Include pundit in the ApplicationController
class ApplicationController < ActionController::Base  include Punditend

Step 3: Build a Feature Flag Policy

  1. Generate a namespaced pundit policy.
rails g pundit:policy feature/enable_post_meta_description
  1. Build the policy
class Feature::EnablePostMetaDescriptionPolicy < ApplicationPolicy  def ceate?    user.present? && (user.enable_post_meta_description == true)  end  def permitted_attributes    if user.enable_post_meta_description == true      [:title, :user_id, :meta_description]    else      [:title, :user_id]    end  end  ...end

What's Going On Here?

  • We generate a policy under the feature namespace. This is not required, but it helps keep things organized and will allow us to add new policies for new features later. We also name this policy to match the name of the feature in the User model.
  • We build a ceate? method that returns true or false based on whether or not that user has the enable_post_meta_description feature set to true. We could have called the method index?, new?, update?, edit? or destroy? but create? makes the most sense in this context. We're building a policy that enables a user to create a meta description on a post.
  • We used pundit's permitted_attributes method to return an array of paramters to be used in the PostsController. This will allow us to conditionally permit the meta_description parameter.

Step 4: Implement the Feature Flag

  1. Update the post_params to hook into the permitted_attributes method.
class PostsController < ApplicationController  before_action :authenticate_user!, except: %i[ show index ]   before_action :set_post, only: %i[ show edit update destroy ]  private    ...    def post_params      params.require(:post).permit(        Feature::EnablePostMetaDescriptionPolicy.new(current_user, Post).permitted_attributes      )    endend

What's Going On Here?

  • We instantiate a new instance of the Feature::EnablePostMetaDescriptionPolicy policy class and pass in the current_user and Post per pundit's API. Then we call permitted_attributes to load the correct parameters based on whether the user has access to the meta_description.
  • Note that we call authenticate_user! before all actions except show and index since the Feature::EnablePostMetaDescriptionPolicy relies on a user.
  1. Conditionally show the meta_description in the post form partial.
# app/views/posts/_form.html.erb<%= form_with(model: post) do |form| %>  ...  <% if Feature::EnablePostMetaDescriptionPolicy.new(current_user, post).create? %>    <div class="field">      <%= form.label :meta_description %>      <%= form.text_area :meta_description %>    </div>   <% end %>  ...<% end %>

What's Going On Here?

  • We wrap the meta_description field in a new instance of the Feature::EnablePostMetaDescriptionPolicy policy class. We call create? which returns true or false based on whether the user has access to the meta_description.

Did you like this post? Follow me on Twitter to get even more tips.


Original Link: https://dev.to/stevepolitodesign/use-pundit-as-a-rails-feature-flag-system-3152

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To