ar_rollout 0.0.17 → 0.0.18

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -118,6 +118,9 @@ List known features with:
118
118
  - Merge ArRollout and Rollout class methods
119
119
  - Autodetection of new features from code, before rollout begins
120
120
 
121
+ ## Version 0.0.18 - 04 Dec 2012
122
+ - Add Group, Membership, OptOut
123
+
121
124
  ## Version 0.0.17 - 29 Nov 2012
122
125
  - ArRollout caches groups
123
126
 
@@ -0,0 +1,20 @@
1
+ class Group < ActiveRecord::Base
2
+ after_destroy :destroy_rollouts
3
+
4
+ has_many :memberships, dependent: :destroy
5
+ validates :name, presence: true, uniqueness: true
6
+ validate :validate_not_defined
7
+ attr_accessible :name
8
+
9
+ private
10
+
11
+ def destroy_rollouts
12
+ Rollout.where(group: name).each(&:destroy)
13
+ end
14
+
15
+ def validate_not_defined
16
+ if ArRollout.defined_groups.include?(name.intern)
17
+ errors.add(:name, "can't be a defined group name")
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,10 @@
1
+ class Membership < ActiveRecord::Base
2
+ self.table_name = :groups_users
3
+
4
+ attr_accessible :group_id, :user_id
5
+
6
+ belongs_to :group
7
+ belongs_to :user
8
+
9
+ validates :user_id, :group_id, presence: true
10
+ end
@@ -0,0 +1,5 @@
1
+ class OptOut < ActiveRecord::Base
2
+ validates_uniqueness_of :user_id, scope: :feature
3
+ validates :user_id, :feature, presence: true
4
+ attr_accessible :user_id, :feature
5
+ end
@@ -13,6 +13,8 @@ class Rollout < ActiveRecord::Base
13
13
  def match_group?(user)
14
14
  if Rollout.method_defined? "match_#{group}?"
15
15
  send "match_#{group}?", user
16
+ elsif group = Group.find_by_name(group) && group.memberships.where('user_id = ?', user.id).any?
17
+ true
16
18
  else
17
19
  false
18
20
  end
@@ -1,3 +1,3 @@
1
1
  module ArRollout
2
- VERSION = "0.0.17"
2
+ VERSION = "0.0.18"
3
3
  end
data/lib/ar_rollout.rb CHANGED
@@ -1,18 +1,25 @@
1
1
  require 'ar_rollout/rollout.rb'
2
+ require 'ar_rollout/group.rb'
3
+ require 'ar_rollout/membership.rb'
4
+ require 'ar_rollout/opt_out.rb'
2
5
  require 'ar_rollout/helper.rb'
3
6
  module ArRollout
4
- @@groups = []
7
+ @@defined_groups = []
5
8
 
6
9
  def self.configure
7
10
  yield self
8
11
  end
9
12
 
13
+ def self.defined_groups
14
+ @@defined_groups
15
+ end
16
+
10
17
  def self.groups
11
- @@groups
18
+ (@@defined_groups + Group.select(:name).collect(&:name).collect(&:intern)).uniq.sort
12
19
  end
13
20
 
14
21
  def self.define_group(name, &block)
15
- @@groups << name
22
+ @@defined_groups << name
16
23
 
17
24
  Rollout.send :define_method, "match_#{name}?" do |b|
18
25
  block.call(b)
@@ -30,8 +37,16 @@ module ArRollout
30
37
  Rollout.find_all_by_name_and_user_id(feature, res_id).map(&:destroy)
31
38
  end
32
39
 
40
+ def self.exclude_user(feature, user)
41
+ res_id = [Fixnum, String].include?(user.class) ? user : user.id
42
+ OptOut.create(feature: feature, user_id: res_id)
43
+ end
44
+
33
45
  def self.activate_group(feature, group)
34
46
  return false if feature.nil? || group.nil?
47
+ unless defined_groups.include? group
48
+ get_group(group)
49
+ end
35
50
  Rollout.find_or_create_by_name_and_group(feature, group)
36
51
  end
37
52
 
@@ -44,6 +59,15 @@ module ArRollout
44
59
  Rollout.create(name: feature, percentage: percentage)
45
60
  end
46
61
 
62
+ def self.get_group(group)
63
+ Group.find_or_create_by_name(group)
64
+ end
65
+
66
+ def self.activate_user_in_group(group, user)
67
+ res_id = [Fixnum, String].include?(user.class) ? user : user.id
68
+ Membership.find_or_create_by_group_id_and_user_id(get_group(group).id, res_id)
69
+ end
70
+
47
71
  def self.deactivate_all(feature)
48
72
  Rollout.find_all_by_name(feature).map(&:destroy)
49
73
  end
@@ -52,10 +76,16 @@ module ArRollout
52
76
  Rollout.select("distinct(name)").order(:name).map(&:name)
53
77
  end
54
78
 
79
+ def self.active_groups
80
+ Rollout.where("'group' is NOT NULL").map(&:group).uniq
81
+ end
82
+
55
83
  def self.active?(name, user)
56
84
  return false unless user
57
- Rollout.where(name: name).where("user_id = ? or user_id is NULL", user.id.to_i).any? do |rollout|
58
- rollout.match?(user)
85
+ unless OptOut.where(feature: name, user_id: user.id).any?
86
+ Rollout.where(name: name).where("user_id = ? or user_id is NULL", user.id.to_i).any? do |rollout|
87
+ rollout.match?(user)
88
+ end
59
89
  end
60
90
  end
61
91
 
@@ -79,22 +109,22 @@ module ArRollout
79
109
 
80
110
  def self.info(feature)
81
111
  {
82
- :percentage => (active_percentage(feature) || 0).to_i,
83
- :groups => active_groups(feature).map { |g| g.to_sym },
84
- :users => active_user_ids(feature)
112
+ :percentage => (_active_percentage(feature) || 0).to_i,
113
+ :groups => _active_groups(feature).map { |g| g.to_sym },
114
+ :users => _active_user_ids(feature)
85
115
  }
86
116
  end
87
117
 
88
118
  private
89
- def self.active_groups(feature)
119
+ def self._active_groups(feature)
90
120
  Rollout.where('"name" = ? and "group" is not null', feature).map(&:group)
91
121
  end
92
122
 
93
- def self.active_user_ids(feature)
123
+ def self._active_user_ids(feature)
94
124
  Rollout.where('"name" = ? and "user_id" is not null', feature).map(&:user_id)
95
125
  end
96
126
 
97
- def self.active_percentage(feature)
127
+ def self._active_percentage(feature)
98
128
  Rollout.select("percentage").where('"name" = ? and "percentage" is not null', feature).first
99
129
  end
100
130
 
@@ -11,8 +11,9 @@ class ArRolloutGenerator < Rails::Generators::Base
11
11
  def copy_initializer_file
12
12
  copy_file "ar_rollout.rb", "config/initializers/ar_rollout.rb"
13
13
  migration_template "migration.rb", "db/migrate/create_rollout"
14
+ migration_template "groups_migration.rb", "db/migrate/create_groups_and_groups_users"
15
+ migration_template "opt_outs_migration.rb", "db/migrate/create_opt_outs"
14
16
  end
15
-
16
17
  end
17
18
 
18
19
 
@@ -0,0 +1,19 @@
1
+ class CreateGroupsAndGroupsUsers < ActiveRecord::Migration
2
+ def up
3
+ create_table :groups do |t|
4
+ t.string :name
5
+ end
6
+
7
+ create_table :groups_users do |t|
8
+ t.references :group
9
+ t.references :user
10
+ end
11
+
12
+ add_index :groups_users, [:group_id, :user_id], unique: true
13
+ end
14
+
15
+ def down
16
+ drop_table :groups
17
+ drop_table :groups_users
18
+ end
19
+ end
@@ -0,0 +1,15 @@
1
+ class CreateOptOuts < ActiveRecord::Migration
2
+ def up
3
+ create_table :opt_outs do |t|
4
+ t.integer :user_id
5
+ t.string :feature
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :opt_outs, [:user_id, :feature], unique: true
10
+ end
11
+
12
+ def down
13
+ drop_table :opt_outs
14
+ end
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ar_rollout
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.17
4
+ version: 0.0.18
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2012-11-30 00:00:00.000000000 Z
16
+ date: 2012-12-04 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: rails
@@ -86,13 +86,18 @@ executables: []
86
86
  extensions: []
87
87
  extra_rdoc_files: []
88
88
  files:
89
+ - lib/ar_rollout/group.rb
89
90
  - lib/ar_rollout/helper.rb
91
+ - lib/ar_rollout/membership.rb
92
+ - lib/ar_rollout/opt_out.rb
90
93
  - lib/ar_rollout/rollout.rb
91
94
  - lib/ar_rollout/version.rb
92
95
  - lib/ar_rollout.rb
93
96
  - lib/generators/ar_rollout_generator.rb
94
97
  - lib/generators/templates/ar_rollout.rb
98
+ - lib/generators/templates/groups_migration.rb
95
99
  - lib/generators/templates/migration.rb
100
+ - lib/generators/templates/opt_outs_migration.rb
96
101
  - lib/tasks/ar_rollout_tasks.rake
97
102
  - MIT-LICENSE
98
103
  - Rakefile