Skip to content

Commit

Permalink
Merge pull request #49 from flippercloud/more-examples
Browse files Browse the repository at this point in the history
Cleans Up Demo & Examples
  • Loading branch information
garrettdimon authored Feb 2, 2024
2 parents 119d621 + 1f607c1 commit c81ac94
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 48 deletions.
8 changes: 7 additions & 1 deletion app/models/example.rb
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def slug
end

def exists?
File.exist?(to_partial_path)
File.exist?(example_file)
end

def partial
Expand All @@ -59,4 +59,10 @@ def partial
def to_partial_path
"example/#{partial}"
end

private

def example_file
Rails.root.join("app/views/example/_#{partial}.html.erb")
end
end
6 changes: 4 additions & 2 deletions app/views/demo/actor.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
<% end %>

<% if !Flipper.enabled?(:demo_actor, current_user) %>
<h1>User-based Feature Flipping</h1>
<h1>Actor-based Feature Flipping</h1>
<p>You can also toggle a feature on or off for <strong>a specific user</strong>. You can enable access for users several ways, but for this example, we'll focus on enabling a feature for a specific user rather than a group that includes that user.</p>

<p>Previously, we enabled the demo for all users. While that's the simplest case and very handy when a feature is completely ready, you'll occasionally want to enable a feature for a single individual like yourself or a teammate. So let's see how that works.</p>
Expand All @@ -21,7 +21,7 @@
<h1>That's It for Actors</h1>
<p>That's all for enabling features for individual actors. Next we'll look at how you can enable features for groups of actors by registering groups and specifying the conditions that indicate an actor is in that group.</p>

<%= next_button "Learn How to Toggle Features for Groups", demo_group_path %>
<%= next_button "Toggle Features for Groups", demo_group_path %>
<% end %>

<% content_for :aside do %>
Expand All @@ -44,6 +44,8 @@
<p class="m-0">The <code>demo_actor</code> feature is <del>disabled</del> for anyone that doesn't have special authorization.</p>
<% end %>

<hr>

<% if Flipper.enabled?(:demo_actor) %>
<p class="m-0">The <code>demo_actor</code> feature is <em>implicitly</em> <ins>enabled</ins> for you since it's enabled for everyone.</p>
<% elsif Flipper.enabled?(:demo_actor, current_user) %>
Expand Down
64 changes: 49 additions & 15 deletions app/views/demo/group.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,65 @@
<% end %>


<% if Flipper.enabled?(:demo_group, @coffee_drinker) && !Flipper.enabled?(:demo_group, current_user) %>
<h1>One More Step</h1>
<p>The <code>demo_group</code> feature is <del>disabled</del> for you since you don't prefer coffee. Let's update your beverage preference so you'll be included in the coffee drinkers group and get access&hellip;</p>
<% if Flipper.enabled?(:demo_group, @coffee_drinker) %>

<% if Flipper.enabled?(:demo_group, current_user) %>
<h1>Welcome to the club!</h1>
<p>The <code>demo_group</code> feature is <ins>enabled</ins> for you since you prefer coffee. Nice work! Next we'll look at how you can enable features for a percentage of users.</p>
<%= next_button "Learn How Percentage Flags Work", demo_percentage_path %>
<% else %>
<h1>Your Beverage Preference</h1>
<p>The <code>demo_group</code> feature is <del>disabled</del> for you since you don't prefer coffee. Let's update your beverage preference so you'll be included in the coffee drinkers group and get access.</p>
<% end %>

<hr class="my-5">

<p><strong><mark>Important:</mark></strong> Even if coffee's not your thing, the rest of the demo is only for coffee drinkers, and there's no penalty for lying.</p>

<%= form_with model: current_user, method: :patch, url: profile_path do |f| %>
<%= f.text_field :beverage, value: 'coffee', hidden: true %>
<%= f.submit "I Prefer Coffee!", class: 'btn btn-lg btn-primary w-100 rounded rounded-pill' %>
<div class="list-group rounded-4 mb-2">
<% %w[water tea coffee].each do |bev| %>
<label class="list-group-item d-flex align-items-top align-content-center justify-content-between gap-2 p-3">
<%= f.radio_button("beverage", bev, class: 'form-check-input flex-shrink-0', checked: current_user.beverage.to_s == bev) %>
<div class="d-block w-100">
<strong><%= bev.capitalize %></strong>
<small class="d-block text-body-secondary">
<%=
if bev == 'coffee'
"You'll be included in the beta testing for coffee-related features!"
else
"A great drink, but you won't be in the Coffee group and won't get early access to our new coffee-related features."
end
%>
</small>
</div>
<div class="ms-4">
<% if bev == 'water' %>
<%= icon 'cup-straw', 'bi-large text-primary' %>
<% elsif bev == 'tea' %>
<%= icon 'cup', 'bi-large text-warning-emphasis' %>
<% else %>
<%= icon 'cup-hot', 'bi-large text-body-emphasis' %>
<% end %>
</div>
</label>
<% end %>
</div>
<%= f.submit "Save my Drink Preference", class: 'btn btn-primary w-100 rounded rounded-pill' %>
<% end %>
<% elsif Flipper.enabled?(:demo_group, current_user) %>
<h1>Welcome to the coffee drinker group!</h1>
<p>The <code>demo_group</code> feature is <ins>enabled</ins> for you since you prefer coffee. Nice work! Next we'll look at how you can enable features for a percentage of users.</p>
<%= next_button "Learn How to Toggle Features for a Percentage of Users", demo_percentage_path %>
<% else %>
<h1>Group-based Feature Flipping</h1>
<p>Let's see how to <a href="https://www.flippercloud.io/docs/features#enablement-group">enable access for a group of users</a>. For that, we need to register the group and specify the conditions that determine whether a given actor is included in the group. Since our new feature would only be relevant for coffee drinkers, we'll only enable it for them.</p>

<p>We've named this feature flag <code>demo_group</code>. We still pass <code>current_user</code> as the actor, but instead of having enabled the user directly, we'll enable the group and the current user would be enabled implicitly if they're a member of the coffee group.</p>

<p>Behind the scenes, we've registered and defined the coffee drinker group in <code>config/initializers/flipper.rb</code>:
<hr class="my-5">

<p><strong><mark>Important:</mark></strong> Behind the scenes, we've already registered and defined the coffee drinker group in <code>config/initializers/flipper.rb</code>:</p>

<pre class="border rounded rounded-3"><code>
Flipper.register(:coffee_drinkers) do |actor, context|
actor.respond_to?(:coffee?) && actor.coffee?
end
</code></pre>
<pre class="border rounded rounded-4 p-3 bg-body-tertiary"><code><strong class="text-success">Flipper.register(:coffee_drinkers)</strong> do |actor, context|
actor.respond_to?(:coffee?) && actor.coffee?
end</code></pre>
<% end %>


Expand Down
2 changes: 1 addition & 1 deletion app/views/demo/start.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<h1>Nice flag toggling!</h1>
<p>The <code>:demo</code> flag is enabled, and you're ready to take Flipper for a spin and enable features on a more specific basis now! Our first example focuses on enabling features for a specific user—you!</p>

<%= next_button 'Learn How to Toggle Features for Individual Actors', demo_actor_path %>
<%= next_button 'Toggle Features for Individual Actors', demo_actor_path %>
<% end %>


Expand Down
31 changes: 18 additions & 13 deletions app/views/example/_managing_external_tools.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,16 @@
["chat-heart-fill", "<strong>Suppress customer-centric widgets</strong> for internal team members that don't need them so everything runs faster."],
]) %>

<hr class="my-4">

<p>Let's considerer a tool like <a href="https://github.com/MiniProfiler/rack-mini-profiler"><code>rack-mini-profiler</code></a>. Would you ever want it on in production all of the time for each and every user? Probably not. You might however want to enable it in production for individual team members to troubleshoot a performance issue hasn't been reproducible in development.</p>

<p>Alternatively, would you want it on for everyone by default in development? That may be less of an issue, but for some teammates, the widget may get in the way of doing design or other front-end work.</p>

<p>Much of this can be handled with checks like <code>Rails.env.production?</code> or <code>Rails.env.local?</code>, but that can only easily consider the environment. And changing that logic would require re-deploying and the waiting that goes along with it.</p>
<p>Much of this could be handled with checks like <code>Rails.env.production?</code> or <code>Rails.env.local?</code>, but that can only easily consider the environment. And changing that logic would require re-deploying and the waiting that goes along with it.</p>

<p>With Feature Flags, everyone on the team can have more granualar control over which tools and widgets they want to see in which environment, and they can turn them on or off any time they want without any changes to the code itself—let alone waiting to deploy new code.</p>

<pre class="d-block border rounded-3 p-4"><code class="">class ApplicationController < ActionController::Base
before_action :setup_rack_mini_profiler

private

def setup_rack_mini_profiler
if Flipper.enabled?(:profiler, current_user)
Rack::MiniProfiler.authorize_request
end
end
end</code></pre>

<% content_for :aside do %>
<div class="card border-5 border-dark rounded-4">
<div class="card-header p-3 pb-2 border-bottom">
Expand Down Expand Up @@ -70,4 +60,19 @@ end</code></pre>
</div>
<% end %>
</div>

<p class="mt-5">To power this, we could add some code to our <code>ApplicationController</code>:</p>

<pre class="border rounded rounded-4 p-3 bg-body-tertiary"><code>class ApplicationController < ActionController::Base
before_action :setup_rack_mini_profiler

private

def setup_rack_mini_profiler
if <strong class="text-success">Flipper.enabled?(:profiler, current_user)</strong>
Rack::MiniProfiler.authorize_request
end
end
end</code></pre>

<% end %>
8 changes: 3 additions & 5 deletions app/views/layouts/application.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
<div class="container">
<div class="row">
<div class="col-12 mx-auto">
<%= flash %>

<header class="bg-primary bg-opacity-10 rounded-3 p-3 mt-3 mb-4 rounded-4">
<nav>
<ul class="nav m-0 p-0 d-flex align-items-center align-content-center justify-content-between">
Expand All @@ -40,11 +42,7 @@


<div class="row mb-3">
<div class="col col-12 mx-auto">
<%= flash %>
</div>

<main class="col col-12 col-xl-6 ps-xl-4 mx-auto">
<main class="col col-12 col-xl-6 ps-xl-4 pe-xl-5 mx-auto">
<%= yield %>
</main>

Expand Down
21 changes: 15 additions & 6 deletions app/views/shared/_page_footer.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
<footer class="d-flex justify-content-center border-top gap-3 my-5 py-4">
<span class="fw-bold">View Source</span>
<a target="_blank" rel="noreferrer" class="link-offset-2 link-underline link-underline-opacity-25 icon-link" href="https://github.com/flippercloud/flipper-rails-demo/tree/main/app/views<%= locals[:file].gsub(Rails.root.to_s, '') %>">
<%= icon 'github' %>
<code><%= locals[:file].gsub(Rails.root.to_s, '') %></code>
</a>
<footer class="d-flex justify-content-between border-top gap-3 my-5 py-4">
<div class="d-flex justify-content-center gap-2">
<span class="fw-bold"></span>
<a target="_blank" rel="noreferrer" class="link-offset-2 link-underline link-underline-opacity-25 icon-link" href="/flipper">
<%= icon 'toggles' %>
Flipper UI
</a>
</div>
<div class="d-flex justify-content-center gap-2">
<span class="fw-bold">View Source</span>
<a target="_blank" rel="noreferrer" class="link-offset-2 link-underline link-underline-opacity-25 icon-link" href="https://github.com/flippercloud/flipper-rails-demo/tree/main/app/views<%= locals[:file].gsub(Rails.root.to_s, '') %>">
<%= icon 'github' %>
<code><%= locals[:file].gsub(Rails.root.to_s, '') %></code>
</a>
</div>
</footer>
12 changes: 10 additions & 2 deletions test/controllers/example_controller_test.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
require "test_helper"

class ExampleControllerTest < ActionDispatch::IntegrationTest
test "should get index" do
test "gets index" do
get examples_url
assert_response :success
end

test "should get show" do
test "gets show" do
get example_url(slug: 'circuit-breakers')
assert_response :success
end

test "loads all examples" do
Example.list.each do |ex|
get example_url(slug: ex.slug)
assert_response :success
end
end

end
31 changes: 28 additions & 3 deletions test/models/example_test.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,32 @@
require "test_helper"

class ExampleTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
setup do
@example = Example.new(
title: "Example Title",
desc: "Example Description",
icon: "check",
tags: [[:permanent, :success], [:internal, :secondary]]
)
end

test "auto-generates a flag symbol without a custom_flag" do
assert_equal :example_title, @example.flag
end

test "prefers custom_flag symbol when provided" do
@example.custom_flag = :example
assert_equal :example, @example.flag
end

test "creates slug from title" do
assert_equal 'example-title', @example.slug
end

test "knows if the corresponding partial exists" do
assert_not @example.exists?

@example.title = "Circuit Breakers"
assert @example.exists?
end
end

0 comments on commit c81ac94

Please sign in to comment.