detour 0.0.7 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8ca146964bc97965e5f1b493fb87c8c4fcd2b149
4
- data.tar.gz: da57f56e5998a03bc6559958a9dcc54f2bf62629
3
+ metadata.gz: 8684efda0b28c3dbd1dd637adced4476063e1b69
4
+ data.tar.gz: 7b8de882f70365420e74d75734583ac336f58762
5
5
  SHA512:
6
- metadata.gz: 4cdaf7bcfec46bdadbbc147f6baaddabf373fe610172afb531805f82250c3b292581281ba5a11aeeaac98dd87fd77ceb4e980d4165a7e0ca0a07fa2c1a8245e8
7
- data.tar.gz: d2535f168cadb5ff31bcd23055d96cac22971d8521a97903407563de976b741faada4ade8cb1ed826edb71ef8e94cac4439c38161787bec14de9be9ef13541b2
6
+ metadata.gz: 070f25d30517f8f1dbd062087e90db55f15b1a51a7eb456211a57123f71314ec33d93417d06ac5921ec2815fb784c8f666b2765a7c8eb290e8163188ce135849
7
+ data.tar.gz: 0080ba77c52c9de244cdc68676519ff81148ee4e190e60f5c9d9c54e903cfd343c1e5f6bd0861d239c66073e085977e658d57bc2fd01dc54525f2edec78b2391
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Detour
2
2
 
3
- Rollouts for `ActiveRecord` models. It is a spiritual fork of [ArRollout](https://github.com/markpundsack/ar_rollout).
3
+ Rollouts for `ActiveRecord` models. It is a spiritual fork of
4
+ [ArRollout](https://github.com/markpundsack/ar_rollout).
4
5
 
5
6
  | development status | master status | Code Climate |
6
7
  | ------------------ | ------------- | ------------ |
@@ -17,6 +18,7 @@ Rollouts for `ActiveRecord` models. It is a spiritual fork of [ArRollout](https:
17
18
  - [Installation](#installation)
18
19
  - [Usage](#usage)
19
20
  - [Configuration](#configuration)
21
+ - [Restricting the admin interface](#restricting-the-admin-interface)
20
22
  - [Marking a model as flaggable](#marking-a-model-as-flaggable)
21
23
  - [Determining if a record is flagged into a feature](#determining-if-a-record-is-flagged-into-a-feature)
22
24
  - [Defining programmatic groups](#defining-programmatic-groups)
@@ -44,7 +46,8 @@ Run the Detour migrations:
44
46
 
45
47
  `Detour` works by determining whether or not a specific record
46
48
  should have features accessible to it based on individual flags, flags for a
47
- percentage of records, or flags for a programmable group of records.
49
+ percentage of records, flags for a database-backed group of records, or flags
50
+ for a code-defined group of records.
48
51
 
49
52
  ### Configuration
50
53
 
@@ -61,11 +64,6 @@ Detour.configure do |config|
61
64
  # checking for flags in your code. Provide it an
62
65
  # array of glob strings:
63
66
  config.feature_search_dirs = %w[app/**/*.{rb,erb}]
64
-
65
- # Provide a default class to manage rollouts for, if
66
- # desired. This means you can omit the class name from
67
- # rake tasks:
68
- config.default_flaggable_class_name = "User"
69
67
  end
70
68
  ```
71
69
 
@@ -77,6 +75,37 @@ Rails.application.routes.draw do
77
75
  end
78
76
  ```
79
77
 
78
+ ### Restricting the admin interface
79
+
80
+ If you'd like your Detour admin interface only accessible to admins, for example,
81
+ you can add a `before_filter` to `Detour::ApplicationController` in the Detour
82
+ initializer:
83
+
84
+ ```ruby
85
+ # config/initializers/detour.rb
86
+
87
+ Detour::ApplicationController.class_eval do
88
+ include CurrentUser
89
+
90
+ before_filter :admin_required!
91
+
92
+ private
93
+
94
+ def admin_required!
95
+ if current_user && current_user.admin?
96
+ true
97
+ else
98
+ # redirect somewhere for non-admins
99
+ end
100
+ end
101
+ end
102
+ ```
103
+
104
+ Since `Detour::ApplicationController` isn't a subclass of my `ApplicationController`,
105
+ I've included a `CurrentUser` module that I built in this app that adds a
106
+ `current_user` method to any controller that it's included in. Now, only admins
107
+ will have access to the Detour admin interface.
108
+
80
109
  ### Marking a model as flaggable
81
110
 
82
111
  In addition to listing classes that are flaggable in your initializer, add
@@ -4,9 +4,10 @@ class Detour::FlaggableFlagsController < Detour::ApplicationController
4
4
  include Detour::FlaggableFlagsHelper
5
5
 
6
6
  before_filter :ensure_flaggable_type_exists
7
+ before_filter :ensure_flag_type_exists
7
8
 
8
9
  def index
9
- @feature = Detour::Feature.find_by_name!(params[:feature_name])
10
+ @feature = Detour::Feature.where(name: params[:feature_name]).first_or_create!
10
11
  end
11
12
 
12
13
  def update
@@ -14,9 +15,17 @@ class Detour::FlaggableFlagsController < Detour::ApplicationController
14
15
 
15
16
  if @feature.update_attributes(params[:feature])
16
17
  flash[:notice] = "Your #{flag_noun.pluralize} have been updated"
17
- redirect_to send("#{flag_type}_flags_path", feature_name: params[:feature_name], flaggable_type: params[:flaggable_type])
18
+ redirect_to flaggable_flags_path flag_type: params[:flag_type], feature_name: params[:feature_name], flaggable_type: params[:flaggable_type]
18
19
  else
19
20
  render :index
20
21
  end
21
22
  end
23
+
24
+ private
25
+
26
+ def ensure_flag_type_exists
27
+ unless %w[flag-ins opt-outs].include? params[:flag_type]
28
+ raise ActionController::RoutingError.new("Not Found")
29
+ end
30
+ end
22
31
  end
@@ -12,7 +12,7 @@ module Detour::FlaggableFlagsHelper
12
12
  end
13
13
 
14
14
  def flag_type
15
- request.path.split("/")[2].underscore.singularize
15
+ params[:flag_type].underscore
16
16
  end
17
17
 
18
18
  def flag_verb
@@ -8,12 +8,12 @@ class Detour::Feature < ActiveRecord::Base
8
8
  serialize :flag_in_counts, JSON
9
9
  serialize :opt_out_counts, JSON
10
10
 
11
- has_many :flag_in_flags
12
- has_many :defined_group_flags
13
- has_many :database_group_flags
14
- has_many :percentage_flags
15
- has_many :opt_out_flags
16
- has_many :flags, dependent: :destroy
11
+ has_many :flag_in_flags, dependent: :destroy
12
+ has_many :defined_group_flags, dependent: :destroy
13
+ has_many :database_group_flags, dependent: :destroy
14
+ has_many :percentage_flags, dependent: :destroy
15
+ has_many :opt_out_flags, dependent: :destroy
16
+ has_many :flags, dependent: :destroy
17
17
 
18
18
  validates_presence_of :name
19
19
  validates_uniqueness_of :name
@@ -33,13 +33,13 @@
33
33
  <% end %>
34
34
 
35
35
  <td class="flag-in-count">
36
- <%= link_to flag_in_flags_path(feature.name, params[:flaggable_type]) do %>
36
+ <%= link_to flaggable_flags_path(flag_type: "flag-ins", feature_name: feature.name, flaggable_type: params[:flaggable_type]) do %>
37
37
  <%= feature.flag_in_count_for(params[:flaggable_type]) %>
38
38
  <% end %>
39
39
  </td>
40
40
 
41
41
  <td class="opt-out-count">
42
- <%= link_to opt_out_flags_path(feature.name, params[:flaggable_type]) do %>
42
+ <%= link_to flaggable_flags_path(flag_type: "opt-outs", feature_name: feature.name, flaggable_type: params[:flaggable_type]) do %>
43
43
  <%= feature.opt_out_count_for(params[:flaggable_type]) %>
44
44
  <% end %>
45
45
  </td>
data/config/routes.rb CHANGED
@@ -5,12 +5,10 @@ Detour::Engine.routes.draw do
5
5
  resources :features, only: [:create, :destroy]
6
6
  resources :groups, only: [:index, :show, :create, :update, :destroy]
7
7
 
8
- %w[flag-ins opt-outs].each do |flag_type|
9
- scope "/#{flag_type}/:feature_name" do
10
- get ":flaggable_type" => "flaggable_flags#index", as: "#{flag_type.underscore.singularize}_flags"
11
- put ":flaggable_type" => "flaggable_flags#update"
12
- delete ":flaggable_type/:id" => "flaggable_flags#destroy", as: "#{flag_type.underscore.singularize}_flag"
13
- end
8
+ scope "/:flag_type/:feature_name" do
9
+ get ":flaggable_type" => "flaggable_flags#index", as: "flaggable_flags"
10
+ put ":flaggable_type" => "flaggable_flags#update"
11
+ delete ":flaggable_type/:id" => "flaggable_flags#destroy", as: "flaggable_flag"
14
12
  end
15
13
 
16
14
  root to: "application#index"
@@ -1,7 +1,6 @@
1
1
  class Detour::Configuration
2
2
  attr_reader :defined_groups
3
3
  attr_reader :feature_search_regex
4
- attr_accessor :default_flaggable_class_name
5
4
  attr_accessor :flaggable_types
6
5
  attr_accessor :feature_search_dirs
7
6
 
@@ -1,3 +1,3 @@
1
1
  module Detour
2
- VERSION = "0.0.7"
2
+ VERSION = "0.0.9"
3
3
  end
@@ -6,57 +6,96 @@ describe Detour::FlaggableFlagsController do
6
6
  describe "GET #index" do
7
7
  let(:flag) { create :flag_in_flag }
8
8
 
9
- before do
10
- get :index, feature_name: flag.feature.name, flaggable_type: "users"
9
+ context "when the flag type is invalid" do
10
+ def do_get
11
+ get :index, flag_type: "foo", feature_name: flag.feature.name, flaggable_type: "users"
12
+ end
13
+
14
+ it "returns a 404" do
15
+ expect { do_get }.to raise_error ActionController::RoutingError
16
+ end
11
17
  end
12
18
 
13
- it "assigns the feature" do
14
- assigns(:feature).should eq flag.feature
19
+ context "when the feature does not exist" do
20
+ before do
21
+ get :index, flag_type: "flag-ins", feature_name: "foo", flaggable_type: "users"
22
+ end
23
+
24
+ it "persists the feature" do
25
+ Detour::Feature.where(name: "foo").should_not be_nil
26
+ end
27
+
28
+ it "is a 200" do
29
+ response.status.should eq 200
30
+ end
15
31
  end
16
32
 
17
- it "renders the index template" do
18
- response.should render_template :index
33
+ context "when the flag type is valid" do
34
+ before do
35
+ get :index, flag_type: "flag-ins", feature_name: flag.feature.name, flaggable_type: "users"
36
+ end
37
+
38
+ it "assigns the feature" do
39
+ assigns(:feature).should eq flag.feature
40
+ end
41
+
42
+ it "renders the index template" do
43
+ response.should render_template :index
44
+ end
19
45
  end
20
46
  end
21
47
 
22
48
  describe "PUT #update" do
23
49
  let(:flag) { create :flag_in_flag }
24
50
 
25
- before do
26
- put :update, feature_name: flag.feature.name, flaggable_type: "users", feature: flag_params
51
+ context "when the flag type is invalid" do
52
+ def do_put
53
+ put :update, flag_type: "foo", feature_name: flag.feature.name, flaggable_type: "users", feature: {}
54
+ end
55
+
56
+ it "returns a 404" do
57
+ expect { do_put }.to raise_error ActionController::RoutingError
58
+ end
27
59
  end
28
60
 
29
- context "when successful" do
30
- let(:user) { create :user }
31
61
 
32
- let(:flag_params) do
33
- {
34
- users_flag_ins_attributes: {
35
- "1" => { flaggable_type: "User", flaggable_key: user.id, _destroy: 0 }
36
- }
37
- }
62
+ context "when the flag type is valid" do
63
+ before do
64
+ put :update, flag_type: "flag-ins", feature_name: flag.feature.name, flaggable_type: "users", feature: flag_params
38
65
  end
39
66
 
40
- it "sets a flash message" do
41
- flash[:notice].should eq "Your flag-ins have been updated"
42
- end
67
+ context "when successful" do
68
+ let(:user) { create :user }
43
69
 
44
- it "redirect to the group" do
45
- response.should redirect_to flag_in_flags_path(feature_name: flag.feature.name, flaggable_type: "users")
70
+ let(:flag_params) do
71
+ {
72
+ users_flag_ins_attributes: {
73
+ "1" => { flaggable_type: "User", flaggable_key: user.id, _destroy: 0 }
74
+ }
75
+ }
76
+ end
77
+
78
+ it "sets a flash message" do
79
+ flash[:notice].should eq "Your flag-ins have been updated"
80
+ end
81
+
82
+ it "redirect to the group" do
83
+ response.should redirect_to flaggable_flags_path(flag_type: "flag-ins", feature_name: flag.feature.name, flaggable_type: "users")
84
+ end
46
85
  end
47
- end
48
86
 
49
- context "when unsuccessful" do
50
- let(:flag_params) do
51
- {
52
- users_flag_ins_attributes: {
53
- "1" => { flaggable_type: "User", flaggable_key: nil, _destroy: 0 }
87
+ context "when unsuccessful" do
88
+ let(:flag_params) do
89
+ {
90
+ users_flag_ins_attributes: {
91
+ "1" => { flaggable_type: "User", flaggable_key: nil, _destroy: 0 }
92
+ }
54
93
  }
55
- }
56
- end
94
+ end
57
95
 
58
- it "renders the show template" do
59
- response.should render_template :index
96
+ it "renders the show template" do
97
+ response.should render_template :index
98
+ end
60
99
  end
61
100
  end
62
101
  end
@@ -2,11 +2,11 @@ require "spec_helper"
2
2
  require "fakefs/spec_helpers"
3
3
 
4
4
  describe Detour::Feature do
5
- it { should have_many(:flag_in_flags) }
6
- it { should have_many(:database_group_flags) }
7
- it { should have_many(:defined_group_flags) }
8
- it { should have_many(:percentage_flags) }
9
- it { should have_many(:opt_out_flags) }
5
+ it { should have_many(:flag_in_flags).dependent(:destroy) }
6
+ it { should have_many(:database_group_flags).dependent(:destroy) }
7
+ it { should have_many(:defined_group_flags).dependent(:destroy) }
8
+ it { should have_many(:percentage_flags).dependent(:destroy) }
9
+ it { should have_many(:opt_out_flags).dependent(:destroy) }
10
10
  it { should have_many(:flags).dependent(:destroy) }
11
11
  it { should validate_presence_of :name }
12
12
  it { should validate_uniqueness_of :name }
@@ -16,6 +16,7 @@ describe Detour::Feature do
16
16
  it { should allow_value("foo_bar").for(:name) }
17
17
  it { should allow_value("foo-bar").for(:name) }
18
18
  it { should_not allow_value("foo-bar.").for(:name) }
19
+ it { should_not allow_value("foo bar").for(:name) }
19
20
 
20
21
  describe "name format validation" do
21
22
  let(:feature) { build :feature, name: "foo bar." }
data/spec/spec_helper.rb CHANGED
@@ -57,7 +57,6 @@ RSpec.configure do |config|
57
57
  end
58
58
 
59
59
  config.after :each do
60
- Detour.config.default_flaggable_class_name = nil
61
60
  Detour.config.feature_search_dirs = []
62
61
  Detour.config.instance_variable_set "@defined_groups", {}
63
62
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: detour
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonathan Clem
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-08 00:00:00.000000000 Z
11
+ date: 2014-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails