Class: ActiveRecord::Rollout::Feature

Inherits:
Base
  • Object
show all
Defined in:
lib/active_record/rollout/feature.rb

Overview

Represents an individual feature that may be rolled out to a set of records via individual flags, percentages, or defined groups.

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.add_group_to_feature(flaggable_type, group_name, feature_name) ⇒ ActiveRecord::Rollout::Flag

Add a group to the given feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised.

Examples:

ActiveRecord::Rollout::Feature.add_group_to_feature "User", "admin", :delete_records

Parameters:

  • flaggable_type (String)

    The class (as a string) that the group should be associated with.

  • group_name (String)

    The name of the group to have the feature added to it.

  • feature_name (String, Symbol)

    The feature to be added to the group.

Returns:



178
179
180
181
# File 'lib/active_record/rollout/feature.rb', line 178

def add_group_to_feature(flaggable_type, group_name, feature_name)
  feature = find_by_name!(feature_name)
  feature.group_flags.create!(flaggable_type: flaggable_type, group_name: group_name)
end

.add_percentage_to_feature(flaggable_type, percentage, feature_name) ⇒ ActiveRecord::Rollout::Flag

Add a percentage of records to the given feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised.

Examples:

ActiveRecord::Rollout::Feature.add_percentage_to_feature "User", 75, :delete_records

Parameters:

  • flaggable_type (String)

    The class (as a string) that the percetnage should be associated with.

  • percentage (Integer)

    The percentage of ‘flaggable_type` records that the feature will be available for.

  • feature_name (String, Symbol)

    The feature to be added to the percentage of records.

Returns:



215
216
217
218
219
220
# File 'lib/active_record/rollout/feature.rb', line 215

def add_percentage_to_feature(flaggable_type, percentage, feature_name)
  feature = find_by_name!(feature_name)

  flag = feature.percentage_flags.where(flaggable_type: flaggable_type).first_or_initialize
  flag.update_attributes!(percentage: percentage)
end

.add_record_to_feature(record, feature_name) ⇒ ActiveRecord::Rollout::Flag

Add a record to the given feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised.

Examples:

ActiveRecord::Rollout::Feature.add_record_to_feature user, :new_ui

Parameters:

  • record (ActiveRecord::Base)

    A record to add the feature to.

  • feature_name (String, Symbol)

    The feature to be added to the record.

Returns:



114
115
116
117
# File 'lib/active_record/rollout/feature.rb', line 114

def add_record_to_feature(record, feature_name)
  feature = find_by_name!(feature_name)
  feature.flaggable_flags.create!(flaggable: record)
end

.default_flaggable_class_nameObject

Returns the default flaggable class.



94
95
96
# File 'lib/active_record/rollout/feature.rb', line 94

def default_flaggable_class_name
  @default_flaggable_class_name
end

.default_flaggable_class_name=(klass) ⇒ Object

Sets the default flaggable class.



99
100
101
# File 'lib/active_record/rollout/feature.rb', line 99

def default_flaggable_class_name=(klass)
  @default_flaggable_class_name = klass
end

.defined_groupsObject

Returns the defined groups.



89
90
91
# File 'lib/active_record/rollout/feature.rb', line 89

def defined_groups
  @defined_groups
end

.method_missing(method, *args, &block) ⇒ Object

Allows for methods of the form ‘define_user_group` that call the private method `define_group_for_class`. A new group for any `User` records will be created that rollouts can be attached to.

Examples:

ActiveRecord::Rollout::Feature.define_user_group :admins do |user|
  user.admin?
end


245
246
247
248
249
250
251
# File 'lib/active_record/rollout/feature.rb', line 245

def method_missing(method, *args, &block)
  if /^define_(?<klass>[a-z0-9_]+)_group/ =~ method
    define_group_for_class(klass.classify, args[0], &block)
  else
    super
  end
end

.opt_record_out_of_feature(record, feature_name) ⇒ ActiveRecord::Rollout::OptOut

Opt the given record out of a feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised. An opt out ensures that no matter what, ‘record.rollout?(:rollout)` will always return false for any opted-out-of features.

Examples:

ActiveRecord::Rollout::Feature.opt_record_out_of_feature user, :new_ui

Parameters:

  • record (ActiveRecord::Base)

    A record to opt out of the feature.

  • feature_name (String, Symbol)

    The feature to be opted out of.

Returns:

  • (ActiveRecord::Rollout::OptOut)

    The OptOut created.



146
147
148
149
# File 'lib/active_record/rollout/feature.rb', line 146

def opt_record_out_of_feature(record, feature_name)
  feature = find_by_name!(feature_name)
  feature.opt_out_flags.create!(flaggable: record)
end

.remove_group_from_feature(flaggable_type, group_name, feature_name) ⇒ Object

Remove a group from agiven feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised.

Examples:

ActiveRecord::Rollout::Feature.remove_group_from_feature "User", "admin", :delete_records

Parameters:

  • flaggable_type (String)

    The class (as a string) that the group should be removed from.

  • group_name (String)

    The name of the group to have the feature removed from it.

  • feature_name (String, Symbol)

    The feature to be removed from the group.



195
196
197
198
# File 'lib/active_record/rollout/feature.rb', line 195

def remove_group_from_feature(flaggable_type, group_name, feature_name)
  feature = find_by_name!(feature_name)
  feature.group_flags.where(flaggable_type: flaggable_type, group_name: group_name).destroy_all
end

.remove_percentage_from_feature(flaggable_type, feature_name) ⇒ Object

Remove any percentage flags for the given feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised.

Examples:

ActiveRecord::Rollout::Feature.remove_percentage_from_feature "User", delete_records

Parameters:

  • flaggable_type (String)

    The class (as a string) that the percetnage should be removed from.

  • feature_name (String, Symbol)

    The feature to have the percentage flag removed from.



232
233
234
235
# File 'lib/active_record/rollout/feature.rb', line 232

def remove_percentage_from_feature(flaggable_type, feature_name)
  feature = find_by_name!(feature_name)
  feature.percentage_flags.where(flaggable_type: flaggable_type).destroy_all
end

.remove_record_from_feature(record, feature_name) ⇒ Object

Remove a record from the given feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised.

Examples:

ActiveRecord::Rollout::Feature.remove_record_from_feature user, :new_ui

Parameters:

  • record (ActiveRecord::Base)

    A record to remove the feature from.

  • feature_name (String, Symbol)

    The feature to be removed from the record.



128
129
130
131
# File 'lib/active_record/rollout/feature.rb', line 128

def remove_record_from_feature(record, feature_name)
  feature = find_by_name!(feature_name)
  feature.flaggable_flags.where(flaggable_type: record.class, flaggable_id: record.id).destroy_all
end

.un_opt_record_out_of_feature(record, feature_name) ⇒ Object

Remove any opt out for the given record out of a feature. If the feature is not found, an ActiveRecord::RecordNotFound will be raised.

Examples:

ActiveRecord::Rollout::Feature.un_opt_record_out_of_feature user, :new_ui

Parameters:

  • record (ActiveRecord::Base)

    A record to un-opt-out of the feature.

  • feature_name (String, Symbol)

    The feature to be un-opted-out of.



159
160
161
162
# File 'lib/active_record/rollout/feature.rb', line 159

def un_opt_record_out_of_feature(record, feature_name)
  feature = find_by_name!(feature_name)
  feature.opt_out_flags.where(flaggable_type: record.class.to_s, flaggable_id: record.id).destroy_all
end

Instance Method Details

#match?(instance) ⇒ Boolean

Determines whether or not the given instance has had the feature rolled out to it either via direct flagging-in, percentage, or by group membership.

Examples:

feature.match?(current_user)

Parameters:

  • instance (ActiveRecord::Base)

    A record to be tested for feature rollout.

Returns:

  • (Boolean)

    Whether or not the given instance has the feature rolled out to it.



29
30
31
# File 'lib/active_record/rollout/feature.rb', line 29

def match?(instance)
  match_id?(instance) || match_percentage?(instance) || match_groups?(instance)
end

#match_groups?(instance) ⇒ Boolean

Determines whether or not the given instance has had the feature rolled out to it via group membership.

Examples:

feature.match_groups?(current_user)

Parameters:

  • instance (ActiveRecord::Base)

    A record to be tested for feature rollout.

Returns:

  • (Boolean)

    Whether or not the given instance has the feature rolled out to it via direct group membership.



75
76
77
78
79
80
81
82
83
84
85
# File 'lib/active_record/rollout/feature.rb', line 75

def match_groups?(instance)
  klass = instance.class.to_s

  return unless self.class.defined_groups[klass]

  group_names = group_flags.find_all_by_flaggable_type(klass).collect(&:group_name)

  self.class.defined_groups[klass].collect { |group_name, block|
    block.call(instance) if group_names.include? group_name
  }.any?
end

#match_id?(instance) ⇒ Boolean

Determines whether or not the given instance has had the feature rolled out to it via direct flagging-in.

Examples:

feature.match_id?(current_user)

Parameters:

  • instance (ActiveRecord::Base)

    A record to be tested for feature rollout.

Returns:

  • (Boolean)

    Whether or not the given instance has the feature rolled out to it via direct flagging-in.



44
45
46
# File 'lib/active_record/rollout/feature.rb', line 44

def match_id?(instance)
  flaggable_flags.where(flaggable_type: instance.class, flaggable_id: instance.id).any?
end

#match_percentage?(instance) ⇒ Boolean

Determines whether or not the given instance has had the feature rolled out to it via percentage.

Examples:

feature.match_percentage?(current_user)

Parameters:

  • instance (ActiveRecord::Base)

    A record to be tested for feature rollout.

Returns:

  • (Boolean)

    Whether or not the given instance has the feature rolled out to it via direct percentage.



59
60
61
62
# File 'lib/active_record/rollout/feature.rb', line 59

def match_percentage?(instance)
  percentage = percentage_flags.where("flaggable_type = ?", instance.class.to_s).first.try(:percentage)
  instance.id % 10 < (percentage || 0) / 10
end