ar_rollout 0.0.17 → 0.0.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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