feature_flags 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -18,8 +18,11 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- with feature_flags gem you can easily manage different features in your rails application.You can turn on/off features.
21
+ For more info:[Click Here](http://ror-tech.blogspot.in/2013/08/manage-different-features-in-our-ruby.html)
22
+
23
+ ###For changes in new version(0.1.0):[Click Here](http://ror-tech.blogspot.com/2014/01/ruby-gem-featureflags-new-features-010.html)
22
24
 
25
+ with feature_flags gem you can easily manage different features in your rails application.You can turn on/off features.
23
26
 
24
27
  rails generate feature_flags:install
25
28
 
@@ -35,6 +38,10 @@ then do
35
38
  ##############################################################################
36
39
  FeatureFlags.enabled?(:feature_name) To check whether particular feature is enabled or not
37
40
 
41
+ FeatureFlags.enabled?([:feature_name1, :feature_name2, :feature_name3]) To check for multiple features
42
+
43
+ FeatureFlags.enabled_any?([:feature_name1, :feature_name2, :feature_name3]) To check if any of given features are enabled or not
44
+
38
45
  FeatureFlags.enable_all To enable all features in your app.
39
46
 
40
47
  FeatureFlags.disable_all To disable all features in your app.
@@ -43,7 +50,7 @@ then do
43
50
 
44
51
  FeatureFlags.create_and_enable(:feature_name) To create and enable feature
45
52
 
46
- FeatureFlags.enable(feature_name) To enable feature
53
+ FeatureFlags.enable(:feature_name) To enable feature
47
54
 
48
55
  ##############################################################################
49
56
 
@@ -60,6 +67,8 @@ If you want to generate views use,
60
67
  rails generate feature_flags:views
61
68
 
62
69
 
70
+ For Demo:[Click Here](http://feature-flags.herokuapp.com/)
71
+
63
72
  Here are some screenshots,
64
73
  main index view
65
74
 
@@ -1,8 +1,8 @@
1
1
  class FeatureFlagsController < ApplicationController
2
2
  layout FeatureFlags.configuration.layout.downcase
3
+ before_filter :load_features, :only => [:index,:create,:update,:destroy]
3
4
 
4
5
  def index
5
- @features = Feature.all
6
6
  end
7
7
 
8
8
  def new
@@ -14,7 +14,6 @@ class FeatureFlagsController < ApplicationController
14
14
  end
15
15
 
16
16
  def create
17
- @features = Feature.all
18
17
  @feature = Feature.new(params[:feature])
19
18
  respond_to do |format|
20
19
  if @feature.save
@@ -31,12 +30,21 @@ class FeatureFlagsController < ApplicationController
31
30
  end
32
31
  end
33
32
 
33
+ def enable_all
34
+ FeatureFlags.enable_all
35
+ end
36
+
37
+ def disable_all
38
+ FeatureFlags.disable_all
39
+ end
40
+
34
41
  def update
35
- @features = Feature.all
36
42
  feature = Feature.find(params[:id])
43
+ enabled_all = params[:enable_all].present? ? enable_all : false
44
+ disabled_all = params[:disable_all].present? ? disable_all : false
37
45
 
38
46
  respond_to do |format|
39
- if feature.update_attributes(params[:feature])
47
+ if enabled_all || disabled_all || feature.update_attributes(params[:feature])
40
48
  flash[:notice] = "#{feature.name} feature successfully updated"
41
49
  format.html{
42
50
  redirect_to feature_flags_url
@@ -58,7 +66,6 @@ class FeatureFlagsController < ApplicationController
58
66
  end
59
67
 
60
68
  def destroy
61
- @features = Feature.all
62
69
  feature = Feature.find(params[:id])
63
70
 
64
71
  respond_to do |format|
@@ -82,4 +89,8 @@ class FeatureFlagsController < ApplicationController
82
89
  end
83
90
  end
84
91
  end
92
+
93
+ def load_features
94
+ @features = Feature.all
95
+ end
85
96
  end
@@ -0,0 +1,21 @@
1
+ <%= form_for feature, :url => path, :method => method, :html => {:class => "feature-flag-form"} do |f| %>
2
+ <div class ="field">
3
+ <label>Name : </label> <br/>
4
+ <%= f.text_field :name %>
5
+ <div class ="errors">
6
+ <% if feature.errors.any? %>
7
+ <% feature.errors.full_messages.each do |error| %>
8
+ <%= error %>
9
+ <% end %>
10
+ <% end %>
11
+ </div>
12
+
13
+ </div>
14
+ <div class ="field">
15
+ <label>Status : </label>&nbsp;&nbsp;
16
+ <%= f.check_box :status %><label>Enabled </label> <br/>
17
+ </div>
18
+ <div class ="field">
19
+ <%= f.submit "Submit" %>
20
+ </div>
21
+ <% end %>
@@ -0,0 +1,8 @@
1
+ <%= form_for feature, :url => feature_flag_url(feature), :method => :put, :html => {:class => "feature-flag-form",:style => "float:right;margin-right: 10px;display: inline-block"} do |f| %>
2
+ <%= hidden_field :enable_all,:value=> true %>
3
+ <%= f.submit "Enable All" %>
4
+ <% end %>
5
+ <%= form_for feature, :url => feature_flag_url(feature), :method => :put, :html => {:class => "feature-flag-form",:style => "float:right;margin-right: 10px;display: inline-block"} do |f| %>
6
+ <%= hidden_field :disable_all,:value=> false %>
7
+ <%= f.submit "Disable All" %>
8
+ <% end %>
@@ -7,26 +7,5 @@
7
7
 
8
8
  <div class="feature-div">
9
9
  <p style="font-weight:bold;font-size:23px">Update Feature</p>
10
- <%= form_for @feature, :url => feature_flag_path(@feature), :method => :put, :html => {:class => "feature-flag-form"} do |f| %>
11
- <div class ="field">
12
- <label>Name : </label> <br/>
13
- <%= f.text_field :name %>
14
- <div class ="errors">
15
- <% if @feature.errors.any? %>
16
- <% @feature.errors.full_messages.each do |error| %>
17
- <%= error %>
18
- <% end %>
19
- <% end %>
20
- </div>
21
-
22
- </div>
23
- <div class ="field">
24
- <label>Status : </label>&nbsp;&nbsp;
25
- <%= f.check_box :status %><label>Enabled </label> <br/>
26
- </div>
27
- <div class ="field">
28
- <%= f.submit "Submit" %>
29
- </div>
30
- <% end %>
31
-
10
+ <%= render :partial => "/feature_flags/form" , :locals => {:path => feature_flag_path(@feature),:method =>:put,:feature => @feature } %>
32
11
  </div>
@@ -14,7 +14,9 @@
14
14
 
15
15
  </div>
16
16
  <%= link_to "Add new Feature", new_feature_flag_path ,:style=>"float:right;margin-right: 50px;" %>
17
+ <%= render :partial => "/feature_flags/options", :locals => { :feature => @features.last } if @features.any?%>
17
18
 
19
+ <!--list of features start-->
18
20
  <div class="feature_flag">
19
21
  <center>
20
22
  <table id="features">
@@ -45,6 +47,10 @@
45
47
  </tr>
46
48
  <% end %>
47
49
  </tbody>
50
+ <%else%>
51
+ <tbody>
52
+ <tr><th colspan="10">Currently there are no features present!</th></tr>
53
+ </tbody>
48
54
  <% end %>
49
55
  </table>
50
56
  </center>
@@ -7,26 +7,5 @@
7
7
 
8
8
  <div class="feature-div">
9
9
  <p style="font-weight:bold;font-size:23px">Add new Feature</p>
10
- <%= form_for @feature, :url => feature_flags_path, :method => :post, :html => {:class => "feature-flag-form"} do |f| %>
11
- <div class ="field">
12
- <label>Name : </label> <br/>
13
- <%= f.text_field :name %>
14
- <div class ="errors">
15
- <% if @feature.errors.any? %>
16
- <% @feature.errors.full_messages.each do |error| %>
17
- <%= error %>
18
- <% end %>
19
- <% end %>
20
- </div>
21
-
22
- </div>
23
- <div class ="field">
24
- <label>Status : </label>&nbsp;&nbsp;
25
- <%= f.check_box :status %><label>Enabled </label> <br/>
26
- </div>
27
- <div class ="field">
28
- <%= f.submit "Submit" %>
29
- </div>
30
- <% end %>
31
-
10
+ <%= render :partial => "/feature_flags/form" , :locals => {:path => feature_flags_path,:method =>:post,:feature => @feature } %>
32
11
  </div>
@@ -4,7 +4,11 @@ require "feature_flags/configuration"
4
4
  require "feature_flags/manage_features"
5
5
  require "feature_flags/engine"
6
6
  require "active_support/dependencies"
7
+ require "feature_flags/feature_base"
8
+ require 'pstore'
9
+ require 'feature_flags/storage'
7
10
 
8
11
  module FeatureFlags
9
12
  # Your code goes here...\
13
+ FeatureFlags.update_pstore_value
10
14
  end
@@ -0,0 +1,53 @@
1
+ module FeatureFlags
2
+ module FeatureBase
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ after_save :update_hash
7
+ after_destroy :update_hash
8
+ end
9
+
10
+ @@features_hash = {}
11
+
12
+
13
+ #returns features hash
14
+ def self.features
15
+ ##checking value in pstore if false then update to true and update features_hash
16
+ pstore_value = get_pstore_value
17
+ @@features_hash = {} unless (pstore_value.present? && !defined? Rails::Console)
18
+
19
+ if(@@features_hash.present? && pstore_value.present?)
20
+ @@features_hash
21
+ else
22
+ set_hash
23
+ Feature.new.update_pstore_hash
24
+ end
25
+
26
+ @@features_hash
27
+ end
28
+
29
+ ###returns current value in pstore
30
+ def self.get_pstore_value
31
+ store = PStore.new('feature_flags')
32
+ store.transaction {store[:updated]}
33
+ end
34
+
35
+ #updates hash for features
36
+ def self.set_hash
37
+ @@features_hash = {}
38
+ Feature.all.map{|f| @@features_hash[f.name.to_s.intern] = f.status}
39
+ @@features_hash.freeze
40
+ end
41
+
42
+ def update_hash
43
+ FeatureFlags::FeatureBase.set_hash
44
+ update_pstore_hash
45
+ end
46
+
47
+ def update_pstore_hash
48
+ FeatureFlags.update_pstore_value(!defined? Rails::Console)
49
+ end
50
+
51
+
52
+ end
53
+ end
@@ -1,15 +1,15 @@
1
1
  module FeatureFlags
2
- def self.enabled?(feature_name)
3
- feature = Feature.where(:name => feature_name).last
2
+ def self.enabled?(feature)
3
+ feature.is_a?(Array) ? !check_features(feature) : get_feature(feature)
4
+ end
4
5
 
5
- if feature.present?
6
- feature.status? ? true : false
7
- else
8
- #Feature.create!(:name => feature_name, :status => true)
9
- #return true
10
- raise "#{feature_name} feature not found."
11
- end
12
-
6
+ def self.enabled_any?(features = [])
7
+ check_features(features, true)
8
+ end
9
+
10
+ ## checking dependant features
11
+ def self.check_features(features, check = false)
12
+ features.map{|feature| get_feature(feature)}.compact.include? check
13
13
  end
14
14
 
15
15
  def self.create_and_enable(feature_name)
@@ -19,38 +19,53 @@ module FeatureFlags
19
19
 
20
20
  def self.enable(feature_name)
21
21
  feature = Feature.where(:name => feature_name).last
22
- if feature.present?
23
-
24
- if feature.update_attributes(:status => true)
25
- return true
26
- else
27
- false
28
- end
22
+ throw_error(feature_name) unless feature.present?
23
+
24
+ if feature.update_attributes(:status => true)
25
+ return true
29
26
  else
30
- raise "#{feature_name} feature not found."
27
+ flash[:error] = "#{feature_name} could not be updated"
28
+ return false
31
29
  end
30
+
32
31
  end
33
32
 
34
33
  def self.set_disabled(feature_name)
35
34
  feature = Feature.where(:name => feature_name).last
36
- if feature.present?
35
+ throw_error(feature_name) unless feature.present?
37
36
 
38
- if feature.update_attributes(:status => false)
39
- return true
40
- else
41
- false
42
- end
37
+ if feature.update_attributes(:status => false)
38
+ return true
43
39
  else
44
- raise "#{feature_name} feature not found."
40
+ flash[:error] = "#{feature_name} could not be updated"
41
+ return false
45
42
  end
46
43
  end
47
44
 
45
+ #disables all features in application
48
46
  def self.disable_all
49
47
  Feature.update_all(:status => false)
48
+ Feature.last.update_attributes(:status => false)
50
49
  end
51
50
 
51
+ #enables all features in application
52
52
  def self.enable_all
53
53
  Feature.update_all(:status => true)
54
+ Feature.last.update_attributes(:status => true)
55
+ end
56
+
57
+ #fetch feature's status
58
+ def self.get_feature(feature_name)
59
+ all_features = FeatureFlags::FeatureBase.features
60
+ all_features.has_key?(feature_name) ? all_features[feature_name] : throw_error(feature_name)
61
+ end
62
+
63
+ def self.throw_error(feature_name)
64
+ raise "#{feature_name} feature not found."
65
+ end
66
+
67
+ def self.update_feature_hash
68
+ Feature.new.update_hash
54
69
  end
55
70
 
56
71
  end
@@ -0,0 +1,11 @@
1
+ module FeatureFlags
2
+
3
+ #storing toggle value inside pstore if in case someone updates from rails console
4
+ def self.update_pstore_value(updated = true)
5
+ store = PStore.new('feature_flags')
6
+ store.transaction do
7
+ store[:updated] = updated
8
+ end
9
+ end
10
+
11
+ end
@@ -1,3 +1,3 @@
1
1
  module FeatureFlags
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -31,6 +31,8 @@ module FeatureFlags
31
31
 
32
32
  def copy_feature_migration
33
33
  template "feature_flag_migrate.rb", "db/migrate/#{MigrationNumber.next_migration_number}_create_features.rb"
34
+
35
+ ##commented model file generation
34
36
  template "feature_flag_model.rb", "app/models/feature.rb"
35
37
  end
36
38
 
@@ -1,5 +1,4 @@
1
1
  class CreateFeatures < ActiveRecord::Migration
2
-
3
2
  def change
4
3
  #creating feature_flags table
5
4
  create_table(:features) do |t|
@@ -1,7 +1,13 @@
1
- class Feature< ActiveRecord::Base
1
+ class Feature < ActiveRecord::Base
2
2
 
3
+ #### IMPORTANT start ####
4
+ ### Dont remove this as this required for memoization of features...
5
+ include FeatureFlags::FeatureBase
6
+ #### IMPORTANT end ####
7
+
8
+
3
9
  validates :name, presence: true
4
10
 
5
11
  attr_accessible :name, :status
6
-
12
+
7
13
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: feature_flags
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-08-30 00:00:00.000000000 Z
12
+ date: 2014-01-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -56,6 +56,8 @@ files:
56
56
  - README.md
57
57
  - Rakefile
58
58
  - app/controllers/feature_flags_controller.rb
59
+ - app/views/feature_flags/_form.html.erb
60
+ - app/views/feature_flags/_options.html.erb
59
61
  - app/views/feature_flags/edit.html.erb
60
62
  - app/views/feature_flags/index.html.erb
61
63
  - app/views/feature_flags/new.html.erb
@@ -65,7 +67,9 @@ files:
65
67
  - lib/feature_flags.rb
66
68
  - lib/feature_flags/configuration.rb
67
69
  - lib/feature_flags/engine.rb
70
+ - lib/feature_flags/feature_base.rb
68
71
  - lib/feature_flags/manage_features.rb
72
+ - lib/feature_flags/storage.rb
69
73
  - lib/feature_flags/version.rb
70
74
  - lib/generators/feature_flags/install_generator.rb
71
75
  - lib/generators/feature_flags/templates/feature_flag.rb
@@ -94,9 +98,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
94
98
  version: '0'
95
99
  requirements: []
96
100
  rubyforge_project:
97
- rubygems_version: 1.8.18
101
+ rubygems_version: 1.8.23
98
102
  signing_key:
99
103
  specification_version: 3
100
104
  summary: Manage (turn on/off) different features in your rails app.
101
105
  test_files: []
102
- has_rdoc: