Class: Trebuchet::Feature

Inherits:
Object
  • Object
show all
Includes:
Stubbing
Defined in:
lib/trebuchet/feature.rb,
lib/trebuchet/feature/stubbing.rb

Defined Under Namespace

Modules: Stubbing

Constant Summary collapse

@@deprecated_strategies_enabled =
true
@@features =
{}

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Stubbing

included, #stub, #stubbed?

Constructor Details

#initialize(name) ⇒ Feature

Returns a new instance of Feature.



11
12
13
# File 'lib/trebuchet/feature.rb', line 11

def initialize(name)
  @name = name
end

Instance Attribute Details

#nameObject

Returns the value of attribute name.



9
10
11
# File 'lib/trebuchet/feature.rb', line 9

def name
  @name
end

Class Method Details

.allObject



31
32
33
# File 'lib/trebuchet/feature.rb', line 31

def self.all
  Trebuchet.backend.get_feature_names.map{|name| new(name)}
end

.dismantledObject



35
36
37
# File 'lib/trebuchet/feature.rb', line 35

def self.dismantled
  Trebuchet.backend.get_archived_feature_names.map{|name| new(name)}
end

.exist?(name) ⇒ Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/trebuchet/feature.rb', line 39

def self.exist?(name)
  !!all.detect{|feature| feature.name == name }
end

.find(name) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
# File 'lib/trebuchet/feature.rb', line 15

def self.find(name)
  feature = @@features[name]
  if !feature
    feature = new(name)
    @@features[name] = feature
  end

  feature.reset

  feature
end

.with_deprecated_strategies_enabled(value = true, &block) ⇒ Object

Runs the block with deprecated features enabled so that various methods do not raise exceptions. This was added to allow specs to test deprecated features. Not thread safe.



46
47
48
49
50
51
52
53
54
# File 'lib/trebuchet/feature.rb', line 46

def self.with_deprecated_strategies_enabled(value=true, &block)
  original_value = @@deprecated_strategies_enabled
  begin
    @@deprecated_strategies_enabled = value
    block.call()
  ensure
    @@deprecated_strategies_enabled = original_value
  end
end

Instance Method Details

#add_comment(comment) ⇒ Object

add comments for a feature, as a place to hold change logs for example, to supported backends



117
118
119
120
121
# File 'lib/trebuchet/feature.rb', line 117

def add_comment(comment)
  if Trebuchet.backend.respond_to?(:add_comment)
    Trebuchet.backend.add_comment(self.name, comment)
  end
end

#adjust(strategy_name, options = nil) ⇒ Object

add/edit just one strategy without affecting other chained strategies



85
86
87
88
# File 'lib/trebuchet/feature.rb', line 85

def adjust(strategy_name, options = nil)
  Trebuchet.backend.append_strategy(self.name, strategy_name, options)
  self
end

#aim(strategy_name, options = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/trebuchet/feature.rb', line 70

def aim(strategy_name, options = nil)
  if !@@deprecated_strategies_enabled &&
     Trebuchet::Strategy.deprecated_strategy_names.include?(strategy_name)
    raise "The #{strategy_name} strategy is deprecated."
  end
  if chained?
    Trebuchet.backend.append_strategy(self.name, strategy_name, options)
  else
    Trebuchet.backend.set_strategy(self.name, strategy_name, options)
  end
  @chained = true
  self
end

#as_json(options = {}) ⇒ Object



151
152
153
# File 'lib/trebuchet/feature.rb', line 151

def as_json(options = {})
  {:name => @name, :strategy => strategy.export}
end

#augment(strategy_name, new_options) ⇒ Object

add to the options of a strategy (if it is an integer, hash or array)



91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'lib/trebuchet/feature.rb', line 91

def augment(strategy_name, new_options)
  # get old options if any
  strategy_array = Trebuchet.backend.get_strategy(self.name)
  i = strategy_array.index(strategy_name)
  old_options = i ? strategy_array[i+1] : nil
  # augment them carefully
  options = if old_options == nil
    new_options
  elsif old_options.is_a?(Array) && new_options.is_a?(Array)
    old_options + new_options
  elsif old_options.is_a?(Hash) && new_options.is_a?(Hash)
    old_options.merge(new_options)
  elsif old_options.is_a?(Numeric) && new_options.is_a?(Numeric)
    old_options + new_options
  else # otherwise, change nothing
    old_options
  end
  # adjust that strategy
  self.adjust(strategy_name, options)
end

#dismantleObject



112
113
114
# File 'lib/trebuchet/feature.rb', line 112

def dismantle
  Trebuchet.backend.remove_feature(self.name)
end

#expiration_dateObject

Retrieve the expiration date of the feature. Return nil if the feature does not have an expiration date.



125
126
127
128
# File 'lib/trebuchet/feature.rb', line 125

def expiration_date
  return unless Trebuchet.backend.respond_to?(:expiration_date)
  Trebuchet.backend.expiration_date(self.name)
end

#exportObject



164
165
166
# File 'lib/trebuchet/feature.rb', line 164

def export
  {:feature_name => name, :strategy => strategy.export}
end

#feature_idObject



143
144
145
146
147
148
149
# File 'lib/trebuchet/feature.rb', line 143

def feature_id
  begin
    @feature_id ||= Trebuchet::SHA1.hexdigest(@name).to_i(16)
  rescue
    return 0
  end
end

#historyObject



136
137
138
139
140
141
# File 'lib/trebuchet/feature.rb', line 136

def history
  return [] unless Trebuchet.backend.respond_to?(:get_history)
  Trebuchet.backend.get_history(self.name).map do |row|
    [Time.at(row.first), Trebuchet::Strategy.find(*row.last)]
  end
end

#inspectObject



160
161
162
# File 'lib/trebuchet/feature.rb', line 160

def inspect
  "#<#{self.class.name} #{self}>"
end

#launch_at?(user, request = nil) ⇒ Boolean

Returns:

  • (Boolean)


64
65
66
67
68
# File 'lib/trebuchet/feature.rb', line 64

def launch_at?(user, request = nil)
  # Store strategy so that only one call to the backend is needed.
  s = strategy
  (!s.needs_user? || !user.nil?) && s.launch_at?(user, request)
end

#resetObject



27
28
29
# File 'lib/trebuchet/feature.rb', line 27

def reset
  @chained = false
end

#set_expiration_date(expiration_date) ⇒ Object

Set the expiration date of the feature.



131
132
133
134
# File 'lib/trebuchet/feature.rb', line 131

def set_expiration_date(expiration_date)
  return unless Trebuchet.backend.respond_to?(:set_expiration_date)
  Trebuchet.backend.set_expiration_date(self.name, expiration_date)
end

#strategyObject



56
57
58
# File 'lib/trebuchet/feature.rb', line 56

def strategy
  Trebuchet::Strategy.for_feature(self)
end

#to_sObject



155
156
157
158
# File 'lib/trebuchet/feature.rb', line 155

def to_s
  str = "name: \"#{@name}\", "
  str << "#{strategy.name == :multiple ? 'strategies' : 'strategy'}: #{strategy}"
end

#valid?Boolean

Returns:

  • (Boolean)


60
61
62
# File 'lib/trebuchet/feature.rb', line 60

def valid?
  strategy.name != :invalid
end