power_enum 3.4.0 → 3.7.0

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.
@@ -2,518 +2,523 @@
2
2
  # Copyright (c) 2012 Arthur Shagall
3
3
  # Released under the MIT License. See the LICENSE file for more details.
4
4
 
5
- # Implementation of acts_as_enumerated
6
- module PowerEnum::Enumerated
7
- extend ActiveSupport::Concern
5
+ module PowerEnum
8
6
 
9
- # Class level methods injected into ActiveRecord.
10
- module ClassMethods
7
+ # Implementation of acts_as_enumerated
8
+ module Enumerated
9
+ extend ActiveSupport::Concern
11
10
 
12
- # Returns false for ActiveRecord models that do not act as enumerated.
13
- def acts_as_enumerated?
14
- false
15
- end
11
+ # Class level methods injected into ActiveRecord.
12
+ module ClassMethods
16
13
 
17
- # Declares the model as enumerated. See the README for detailed usage instructions.
18
- #
19
- # === Supported options
20
- # [:conditions]
21
- # SQL search conditions
22
- # [:order]
23
- # SQL load order clause
24
- # [:on_lookup_failure]
25
- # Specifies the name of a class method to invoke when the +[]+ method is unable to locate a BookingStatus
26
- # record for arg. The default is the built-in :enforce_none which returns nil. There are also built-ins for
27
- # :enforce_strict (raise and exception regardless of the type for arg), :enforce_strict_literals (raises an
28
- # exception if the arg is a Integer or Symbol), :enforce_strict_ids (raises and exception if the arg is a
29
- # Integer) and :enforce_strict_symbols (raises an exception if the arg is a Symbol). The purpose of the
30
- # :on_lookup_failure option is that a) under some circumstances a lookup failure is a Bad Thing and action
31
- # should be taken, therefore b) a fallback action should be easily configurable. You can also give it a
32
- # lambda that takes in a single argument (The arg that was passed to +[]+).
33
- # [:name_column]
34
- # Override for the 'name' column. By default, assumed to be 'name'.
35
- # [:alias_name]
36
- # By default, if a name column is not 'name', will create an alias of 'name' to the name_column attribute. Set
37
- # this to +false+ if you don't want this behavior.
38
- #
39
- # === Examples
40
- #
41
- # ====Example 1
42
- # class BookingStatus < ActiveRecord::Base
43
- # acts_as_enumerated
44
- # end
45
- #
46
- # ====Example 2
47
- # class BookingStatus < ActiveRecord::Base
48
- # acts_as_enumerated :on_lookup_failure => :enforce_strict
49
- # end
50
- #
51
- # ====Example 3
52
- # class BookingStatus < ActiveRecord::Base
53
- # acts_as_enumerated :conditions => [:exclude => false],
54
- # :order => 'created_at DESC',
55
- # :on_lookup_failure => :lookup_failed,
56
- # :name_column => :status_code
57
- #
58
- # def self.lookup_failed(arg)
59
- # logger.error("Invalid status code lookup #{arg.inspect}")
60
- # nil
61
- # end
62
- # end
63
- #
64
- # ====Example 4
65
- # class BookingStatus < ActiveRecord::Base
66
- # acts_as_enumerated :conditions => [:exclude => false],
67
- # :order => 'created_at DESC',
68
- # :on_lookup_failure => lambda { |arg| raise CustomError, "BookingStatus lookup failed; #{arg}" },
69
- # :name_column => :status_code
70
- # end
71
- def acts_as_enumerated(options = {})
72
- valid_keys = [:conditions, :order, :on_lookup_failure, :name_column, :alias_name]
73
- options.assert_valid_keys(*valid_keys)
74
-
75
- valid_keys.each do |key|
76
- class_attribute "acts_enumerated_#{key.to_s}"
77
- if options.has_key?( key )
78
- self.send "acts_enumerated_#{key.to_s}=", options[key]
79
- end
14
+ # Returns false for ActiveRecord models that do not act as enumerated.
15
+ def acts_as_enumerated?
16
+ false
80
17
  end
81
18
 
82
- class_attribute :acts_enumerated_name_column
83
- self.acts_enumerated_name_column = get_name_column(options)
19
+ # Declares the model as enumerated. See the README for detailed usage instructions.
20
+ #
21
+ # === Supported options
22
+ # [:conditions]
23
+ # SQL search conditions
24
+ # [:order]
25
+ # SQL load order clause
26
+ # [:on_lookup_failure]
27
+ # Specifies the name of a class method to invoke when the +[]+ method is unable to locate a BookingStatus
28
+ # record for arg. The default is the built-in :enforce_none which returns nil. There are also built-ins for
29
+ # :enforce_strict (raise and exception regardless of the type for arg), :enforce_strict_literals (raises an
30
+ # exception if the arg is a Integer or Symbol), :enforce_strict_ids (raises and exception if the arg is a
31
+ # Integer) and :enforce_strict_symbols (raises an exception if the arg is a Symbol). The purpose of the
32
+ # :on_lookup_failure option is that a) under some circumstances a lookup failure is a Bad Thing and action
33
+ # should be taken, therefore b) a fallback action should be easily configurable. You can also give it a
34
+ # lambda that takes in a single argument (The arg that was passed to +[]+).
35
+ # [:name_column]
36
+ # Override for the 'name' column. By default, assumed to be 'name'.
37
+ # [:alias_name]
38
+ # By default, if a name column is not 'name', will create an alias of 'name' to the name_column attribute. Set
39
+ # this to +false+ if you don't want this behavior.
40
+ # [:freeze_members]
41
+ # Specifies whether individual enum instances should be frozen on database load. By default, true in production.
42
+ # Can be either a lambda or a boolean.
43
+ #
44
+ # === Examples
45
+ #
46
+ # ====Example 1
47
+ # class BookingStatus < ActiveRecord::Base
48
+ # acts_as_enumerated
49
+ # end
50
+ #
51
+ # ====Example 2
52
+ # class BookingStatus < ActiveRecord::Base
53
+ # acts_as_enumerated :on_lookup_failure => :enforce_strict
54
+ # end
55
+ #
56
+ # ====Example 3
57
+ # class BookingStatus < ActiveRecord::Base
58
+ # acts_as_enumerated :conditions => [:exclude => false],
59
+ # :order => 'created_at DESC',
60
+ # :on_lookup_failure => :lookup_failed,
61
+ # :name_column => :status_code
62
+ #
63
+ # def self.lookup_failed(arg)
64
+ # logger.error("Invalid status code lookup #{arg.inspect}")
65
+ # nil
66
+ # end
67
+ # end
68
+ #
69
+ # ====Example 4
70
+ # class BookingStatus < ActiveRecord::Base
71
+ # acts_as_enumerated :conditions => [:exclude => false],
72
+ # :order => 'created_at DESC',
73
+ # :on_lookup_failure => lambda { |arg| raise CustomError, "BookingStatus lookup failed; #{arg}" },
74
+ # :name_column => :status_code,
75
+ # :freeze_members => true
76
+ # end
77
+ def acts_as_enumerated(options = {})
78
+ valid_keys = [:conditions, :order, :on_lookup_failure, :name_column, :alias_name, :freeze_members]
79
+ options.assert_valid_keys(*valid_keys)
80
+
81
+ valid_keys.each do |key|
82
+ class_attribute "acts_enumerated_#{key.to_s}"
83
+ if options.has_key?( key )
84
+ self.send "acts_enumerated_#{key.to_s}=", options[key]
85
+ end
86
+ end
84
87
 
85
- unless self.is_a? PowerEnum::Enumerated::EnumClassMethods
86
- preserve_query_aliases
87
- extend_enum_class_methods( options )
88
- end
89
- end
88
+ self.acts_enumerated_name_column = get_name_column(options)
90
89
 
91
- # Rails 4 delegates all the finder methods to 'all'. PowerEnum overrides 'all'. Hence,
92
- # the need to re-alias the query methods.
93
- def preserve_query_aliases
94
- class << self
95
- # I have to do the interesting hack below instead of using alias_method
96
- # because there's some sort of weirdness going on with how __all binds
97
- # to all in Ruby 2.0.
98
- __all = self.instance_method(:all)
99
-
100
- define_method(:__all) do
101
- __all.bind(self).call
90
+ unless self.is_a? PowerEnum::Enumerated::EnumClassMethods
91
+ preserve_query_aliases
92
+ extend_enum_class_methods( options )
102
93
  end
94
+ end
103
95
 
104
- # From ActiveRecord::Querying
105
- delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :to => :__all
106
- delegate :first_or_create, :first_or_create!, :first_or_initialize, :to => :__all
107
- delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :to => :__all
108
- delegate :find_by, :find_by!, :to => :__all
109
- delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, :to => :__all
110
- delegate :find_each, :find_in_batches, :to => :__all
111
- delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins,
112
- :where, :preload, :eager_load, :includes, :from, :lock, :readonly,
113
- :having, :create_with, :uniq, :distinct, :references, :none, :unscope, :to => :__all
114
- delegate :count, :average, :minimum, :maximum, :sum, :calculate, :pluck, :ids, :to => :__all
96
+ # Rails 4 delegates all the finder methods to 'all'. PowerEnum overrides 'all'. Hence,
97
+ # the need to re-alias the query methods.
98
+ def preserve_query_aliases
99
+ class << self
100
+ # I have to do the interesting hack below instead of using alias_method
101
+ # because there's some sort of weirdness going on with how __all binds
102
+ # to all in Ruby 2.0.
103
+ __all = self.instance_method(:all)
104
+
105
+ define_method(:__all) do
106
+ __all.bind(self).call
107
+ end
108
+
109
+ # From ActiveRecord::Querying
110
+ delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :to => :__all
111
+ delegate :first_or_create, :first_or_create!, :first_or_initialize, :to => :__all
112
+ delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, :to => :__all
113
+ delegate :find_by, :find_by!, :to => :__all
114
+ delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, :to => :__all
115
+ delegate :find_each, :find_in_batches, :to => :__all
116
+ delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins,
117
+ :where, :preload, :eager_load, :includes, :from, :lock, :readonly,
118
+ :having, :create_with, :uniq, :distinct, :references, :none, :unscope, :to => :__all
119
+ delegate :count, :average, :minimum, :maximum, :sum, :calculate, :pluck, :ids, :to => :__all
120
+ end
115
121
  end
116
- end
117
122
 
118
- # Injects the class methods into model
119
- def extend_enum_class_methods(options) #:nodoc:
123
+ # Injects the class methods into model
124
+ def extend_enum_class_methods(options) #:nodoc:
120
125
 
121
- extend PowerEnum::Enumerated::EnumClassMethods
126
+ extend PowerEnum::Enumerated::EnumClassMethods
122
127
 
123
- class_eval do
124
- include PowerEnum::Enumerated::EnumInstanceMethods
128
+ class_eval do
129
+ include PowerEnum::Enumerated::EnumInstanceMethods
125
130
 
126
- before_save :enumeration_model_update
127
- before_destroy :enumeration_model_update
128
- validates acts_enumerated_name_column, :presence => true, :uniqueness => true
129
- validate :validate_enumeration_model_updates_permitted
131
+ before_save :enumeration_model_update
132
+ before_destroy :enumeration_model_update
133
+ validates acts_enumerated_name_column, :presence => true, :uniqueness => true
134
+ validate :validate_enumeration_model_updates_permitted
130
135
 
131
- define_method :__enum_name__ do
132
- read_attribute(acts_enumerated_name_column).to_s
133
- end
136
+ define_method :__enum_name__ do
137
+ read_attribute(acts_enumerated_name_column).to_s
138
+ end
134
139
 
135
- if should_alias_name?(options) && acts_enumerated_name_column != :name
136
- alias_method :name, :__enum_name__
137
- end
138
- end # class_eval
140
+ if should_alias_name?(options) && acts_enumerated_name_column != :name
141
+ alias_method :name, :__enum_name__
142
+ end
143
+ end # class_eval
139
144
 
140
- end
141
- private :extend_enum_class_methods
145
+ end
142
146
 
143
- # Determines if the name column should be explicitly aliased
144
- def should_alias_name?(options) #:nodoc:
145
- if options.has_key?(:alias_name) then
146
- options[:alias_name]
147
- else
148
- true
147
+ # Determines if the name column should be explicitly aliased
148
+ def should_alias_name?(options) #:nodoc:
149
+ if options.has_key?(:alias_name) then
150
+ options[:alias_name]
151
+ else
152
+ true
153
+ end
149
154
  end
150
- end
151
- private :should_alias_name?
152
155
 
153
- # Extracts the name column from options or gives the default
154
- def get_name_column(options) #:nodoc:
155
- if options.has_key?(:name_column) && !options[:name_column].blank? then
156
- options[:name_column].to_s.to_sym
157
- else
158
- :name
156
+ # Extracts the name column from options or gives the default
157
+ def get_name_column(options) #:nodoc:
158
+ if options.has_key?(:name_column) && !options[:name_column].blank? then
159
+ options[:name_column].to_s.to_sym
160
+ else
161
+ :name
162
+ end
159
163
  end
160
164
  end
161
- private :get_name_column
162
- end
163
165
 
164
- # These are class level methods which are patched into classes that act as
165
- # enumerated
166
- module EnumClassMethods
167
- attr_accessor :enumeration_model_updates_permitted
166
+ # These are class level methods which are patched into classes that act as
167
+ # enumerated
168
+ module EnumClassMethods
169
+ attr_accessor :enumeration_model_updates_permitted
168
170
 
169
- # Returns true for ActiveRecord models that act as enumerated.
170
- def acts_as_enumerated?
171
- true
172
- end
171
+ # Returns true for ActiveRecord models that act as enumerated.
172
+ def acts_as_enumerated?
173
+ true
174
+ end
173
175
 
174
- # Returns all the enum values. Caches results after the first time this method is run.
175
- def all
176
- return @all if @all
177
- @all = load_all.collect{|val| val.freeze}.freeze
178
- end
176
+ # Returns all the enum values. Caches results after the first time this method is run.
177
+ def all
178
+ return @all if @all
179
+
180
+ freeze_handler = if (handler = self.acts_enumerated_freeze_members).nil?
181
+ -> { Rails.env.production? }
182
+ else
183
+ case handler
184
+ when Proc
185
+ handler
186
+ else
187
+ -> { handler }
188
+ end
189
+ end
190
+
191
+ @all = load_all.collect{ |val| !!freeze_handler.call ? val.freeze : val }.freeze
192
+ end
179
193
 
180
- # Returns all the active enum values. See the 'active?' instance method.
181
- def active
182
- return @all_active if @all_active
183
- @all_active = all.find_all{ |enum| enum.active? }.freeze
184
- end
194
+ # Returns all the active enum values. See the 'active?' instance method.
195
+ def active
196
+ return @all_active if @all_active
197
+ @all_active = all.find_all{ |enum| enum.active? }.freeze
198
+ end
185
199
 
186
- # Returns all the inactive enum values. See the 'inactive?' instance method.
187
- def inactive
188
- return @all_inactive if @all_inactive
189
- @all_inactive = all.find_all{ |enum| !enum.active? }.freeze
190
- end
200
+ # Returns all the inactive enum values. See the 'inactive?' instance method.
201
+ def inactive
202
+ return @all_inactive if @all_inactive
203
+ @all_inactive = all.find_all{ |enum| !enum.active? }.freeze
204
+ end
191
205
 
192
- # Returns the names of all the enum values as an array of symbols.
193
- def names
194
- all.map { |item| item.name_sym }
195
- end
206
+ # Returns the names of all the enum values as an array of symbols.
207
+ def names
208
+ all.map { |item| item.name_sym }
209
+ end
196
210
 
197
- # Returns all except for the given list
198
- def all_except(*excluded)
199
- all.find_all { |item| !(item === excluded) }
200
- end
211
+ # Returns all except for the given list
212
+ def all_except(*excluded)
213
+ all.find_all { |item| !(item === excluded) }
214
+ end
201
215
 
202
- # Enum lookup by Symbol, String, or id. Returns <tt>arg<tt> if arg is
203
- # an enum instance. Passing in a list of arguments returns a list of
204
- # enums. When called with no arguments, returns nil.
205
- def [](*args)
206
- case args.size
207
- when 0
208
- nil
209
- when 1
210
- arg = args.first
211
- lookup_enum_by_type(arg) || handle_lookup_failure(arg)
212
- else
213
- args.map{ |item| self[item] }.uniq
216
+ # Enum lookup by Symbol, String, or id. Returns <tt>arg<tt> if arg is
217
+ # an enum instance. Passing in a list of arguments returns a list of
218
+ # enums. When called with no arguments, returns nil.
219
+ def [](*args)
220
+ case args.size
221
+ when 0
222
+ nil
223
+ when 1
224
+ arg = args.first
225
+ Array === arg ? self[*arg] : (lookup_enum_by_type(arg) || handle_lookup_failure(arg))
226
+ else
227
+ args.map{ |item| self[item] }.uniq
228
+ end
214
229
  end
215
- end
216
230
 
217
- # Returns <tt>true</tt> if the given Symbol, String or id has a member
218
- # instance in the enumeration, <tt>false</tt> otherwise. Returns <tt>true</tt>
219
- # if the argument is an enum instance, returns <tt>false</tt> if the argument
220
- # is nil or any other value.
221
- def contains?(arg)
222
- case arg
223
- when Symbol
224
- !!lookup_name(arg.id2name)
225
- when String
226
- !!lookup_name(arg)
227
- when Integer
228
- !!lookup_id(arg)
229
- when self
230
- true
231
- else
232
- false
231
+ # Returns <tt>true</tt> if the given Symbol, String or id has a member
232
+ # instance in the enumeration, <tt>false</tt> otherwise. Returns <tt>true</tt>
233
+ # if the argument is an enum instance, returns <tt>false</tt> if the argument
234
+ # is nil or any other value.
235
+ def contains?(arg)
236
+ case arg
237
+ when Symbol
238
+ !!lookup_name(arg.id2name)
239
+ when String
240
+ !!lookup_name(arg)
241
+ when Integer
242
+ !!lookup_id(arg)
243
+ when self
244
+ true
245
+ else
246
+ false
247
+ end
233
248
  end
234
- end
235
249
 
236
- # Enum lookup by id
237
- def lookup_id(arg)
238
- all_by_id[arg]
239
- end
250
+ # Enum lookup by id
251
+ def lookup_id(arg)
252
+ all_by_id[arg]
253
+ end
240
254
 
241
- # Enum lookup by String
242
- def lookup_name(arg)
243
- all_by_name[arg]
244
- end
255
+ # Enum lookup by String
256
+ def lookup_name(arg)
257
+ all_by_name[arg]
258
+ end
245
259
 
246
- # Returns true if the enum lookup by the given Symbol, String or id would have returned a value, false otherwise.
247
- def include?(arg)
248
- case arg
249
- when Symbol
250
- !lookup_name(arg.id2name).nil?
251
- when String
252
- !lookup_name(arg).nil?
253
- when Integer
254
- !lookup_id(arg).nil?
255
- when self
256
- possible_match = lookup_id(arg.id)
257
- !possible_match.nil? && possible_match == arg
258
- else
259
- false
260
+ # Returns true if the enum lookup by the given Symbol, String or id would have returned a value, false otherwise.
261
+ def include?(arg)
262
+ case arg
263
+ when Symbol
264
+ !lookup_name(arg.id2name).nil?
265
+ when String
266
+ !lookup_name(arg).nil?
267
+ when Integer
268
+ !lookup_id(arg).nil?
269
+ when self
270
+ possible_match = lookup_id(arg.id)
271
+ !possible_match.nil? && possible_match == arg
272
+ else
273
+ false
274
+ end
260
275
  end
261
- end
262
276
 
263
- # NOTE: purging the cache is sort of pointless because
264
- # of the per-process rails model.
265
- # By default this blows up noisily just in case you try to be more
266
- # clever than rails allows.
267
- # For those times (like in Migrations) when you really do want to
268
- # alter the records you can silence the carping by setting
269
- # enumeration_model_updates_permitted to true.
270
- def purge_enumerations_cache
271
- unless self.enumeration_model_updates_permitted
272
- raise "#{self.name}: cache purging disabled for your protection"
273
- end
274
- @all = @all_by_name = @all_by_id = @all_active = nil
275
- end
277
+ # NOTE: purging the cache is sort of pointless because
278
+ # of the per-process rails model.
279
+ # By default this blows up noisily just in case you try to be more
280
+ # clever than rails allows.
281
+ # For those times (like in Migrations) when you really do want to
282
+ # alter the records you can silence the carping by setting
283
+ # enumeration_model_updates_permitted to true.
284
+ def purge_enumerations_cache
285
+ unless self.enumeration_model_updates_permitted
286
+ raise "#{self.name}: cache purging disabled for your protection"
287
+ end
288
+ @all = @all_by_name = @all_by_id = @all_active = nil
289
+ end
276
290
 
277
- # The preferred method to update an enumerations model. The same
278
- # warnings as 'purge_enumerations_cache' and
279
- # 'enumerations_model_update_permitted' apply. Pass a block to this
280
- # method where you perform your updates. Cache will be
281
- # flushed automatically. If your block takes an argument, will pass in
282
- # the model class. The argument is optional.
283
- def update_enumerations_model(&block)
284
- if block_given?
285
- begin
286
- self.enumeration_model_updates_permitted = true
287
- purge_enumerations_cache
288
- @all = load_all
289
- @enumerations_model_updating = true
290
- case block.arity
291
- when 0
292
- yield
293
- else
294
- yield self
291
+ # The preferred method to update an enumerations model. The same
292
+ # warnings as 'purge_enumerations_cache' and
293
+ # 'enumerations_model_update_permitted' apply. Pass a block to this
294
+ # method where you perform your updates. Cache will be
295
+ # flushed automatically. If your block takes an argument, will pass in
296
+ # the model class. The argument is optional.
297
+ def update_enumerations_model(&block)
298
+ if block_given?
299
+ begin
300
+ self.enumeration_model_updates_permitted = true
301
+ purge_enumerations_cache
302
+ @all = load_all
303
+ @enumerations_model_updating = true
304
+ case block.arity
305
+ when 0
306
+ yield
307
+ else
308
+ yield self
309
+ end
310
+ ensure
311
+ purge_enumerations_cache
312
+ @enumerations_model_updating = false
313
+ self.enumeration_model_updates_permitted = false
295
314
  end
296
- ensure
297
- purge_enumerations_cache
298
- @enumerations_model_updating = false
299
- self.enumeration_model_updates_permitted = false
300
315
  end
301
316
  end
302
- end
303
317
 
304
- # Returns true if the enumerations model is in the middle of an
305
- # update_enumerations_model block, false otherwise.
306
- def enumerations_model_updating?
307
- !!@enumerations_model_updating
308
- end
318
+ # Returns true if the enumerations model is in the middle of an
319
+ # update_enumerations_model block, false otherwise.
320
+ def enumerations_model_updating?
321
+ !!@enumerations_model_updating
322
+ end
309
323
 
310
- # Returns the name of the column this enum uses as the basic underlying value.
311
- def name_column
312
- @name_column ||= self.acts_enumerated_name_column
313
- end
324
+ # Returns the name of the column this enum uses as the basic underlying value.
325
+ def name_column
326
+ @name_column ||= self.acts_enumerated_name_column
327
+ end
314
328
 
315
- # ---Private methods---
329
+ # ---Private methods---
316
330
 
317
- def load_all
318
- conditions = self.acts_enumerated_conditions
319
- order = self.acts_enumerated_order
320
- unscoped.where(conditions).order(order)
321
- end
322
- private :load_all
323
-
324
- # Looks up the enum based on the type of the argument.
325
- def lookup_enum_by_type(arg)
326
- case arg
327
- when Symbol
328
- lookup_name(arg.id2name)
329
- when String
330
- lookup_name(arg)
331
- when Integer
332
- lookup_id(arg)
333
- when self
334
- arg
335
- when nil
336
- nil
337
- else
338
- raise TypeError, "#{self.name}[]: argument should"\
339
- " be a String, Symbol or Integer but got a: #{arg.class.name}"
331
+ private def load_all
332
+ conditions = self.acts_enumerated_conditions
333
+ order = self.acts_enumerated_order
334
+ unscoped.where(conditions).order(order)
340
335
  end
341
- end
342
- private :lookup_enum_by_type
343
-
344
- # Deals with a lookup failure for the given argument.
345
- def handle_lookup_failure(arg)
346
- if (lookup_failure_handler = self.acts_enumerated_on_lookup_failure)
347
- case lookup_failure_handler
348
- when Proc
349
- lookup_failure_handler.call(arg)
336
+
337
+ # Looks up the enum based on the type of the argument.
338
+ private def lookup_enum_by_type(arg)
339
+ case arg
340
+ when Symbol
341
+ lookup_name(arg.id2name)
342
+ when String
343
+ lookup_name(arg)
344
+ when Integer
345
+ lookup_id(arg)
346
+ when self
347
+ arg
348
+ when nil
349
+ nil
350
350
  else
351
- self.send(lookup_failure_handler, arg)
351
+ raise TypeError, "#{self.name}[]: argument should"\
352
+ " be a String, Symbol or Integer but got a: #{arg.class.name}"
352
353
  end
353
- else
354
- self.send(:enforce_none, arg)
355
354
  end
356
- end
357
- private :handle_lookup_failure
358
355
 
359
- # Returns a hash of all enumeration members keyed by their ids.
360
- def all_by_id
361
- @all_by_id ||= all_by_attribute( primary_key )
362
- end
363
- private :all_by_id
364
-
365
- # Returns a hash of all the enumeration members keyed by their names.
366
- def all_by_name
367
- begin
368
- @all_by_name ||= all_by_attribute( :__enum_name__ )
369
- rescue NoMethodError => err
370
- if err.name == name_column
371
- raise TypeError, "#{self.name}: you need to define a '#{name_column}' column in the table '#{table_name}'"
356
+ # Deals with a lookup failure for the given argument.
357
+ private def handle_lookup_failure(arg)
358
+ if (lookup_failure_handler = self.acts_enumerated_on_lookup_failure)
359
+ case lookup_failure_handler
360
+ when Proc
361
+ lookup_failure_handler.call(arg)
362
+ else
363
+ self.send(lookup_failure_handler, arg)
364
+ end
365
+ else
366
+ self.send(:enforce_none, arg)
372
367
  end
373
- raise
374
368
  end
375
- end
376
- private :all_by_name
377
-
378
- def all_by_attribute(attr) # :nodoc:
379
- aba = all.inject({}) { |memo, item|
380
- memo[item.send(attr)] = item
381
- memo
382
- }
383
- aba.freeze unless enumerations_model_updating?
384
- aba
385
- end
386
- private :all_by_attribute
387
369
 
388
- def enforce_none(arg) # :nodoc:
389
- nil
390
- end
391
- private :enforce_none
370
+ # Returns a hash of all enumeration members keyed by their ids.
371
+ private def all_by_id
372
+ @all_by_id ||= all_by_attribute( primary_key )
373
+ end
392
374
 
393
- def enforce_strict(arg) # :nodoc:
394
- raise_record_not_found(arg)
395
- end
396
- private :enforce_strict
375
+ # Returns a hash of all the enumeration members keyed by their names.
376
+ private def all_by_name
377
+ begin
378
+ @all_by_name ||= all_by_attribute( :__enum_name__ )
379
+ rescue NoMethodError => err
380
+ if err.name == name_column
381
+ raise TypeError, "#{self.name}: you need to define a '#{name_column}' column in the table '#{table_name}'"
382
+ end
383
+ raise
384
+ end
385
+ end
397
386
 
398
- def enforce_strict_literals(arg) # :nodoc:
399
- raise_record_not_found(arg) if (Integer === arg) || (Symbol === arg)
400
- nil
401
- end
402
- private :enforce_strict_literals
387
+ private def all_by_attribute(attr) # :nodoc:
388
+ aba = all.inject({}) { |memo, item|
389
+ memo[item.send(attr)] = item
390
+ memo
391
+ }
392
+ aba.freeze unless enumerations_model_updating?
393
+ aba
394
+ end
403
395
 
404
- def enforce_strict_ids(arg) # :nodoc:
405
- raise_record_not_found(arg) if Integer === arg
406
- nil
407
- end
408
- private :enforce_strict_ids
396
+ private def enforce_none(arg) # :nodoc:
397
+ nil
398
+ end
409
399
 
410
- def enforce_strict_symbols(arg) # :nodoc:
411
- raise_record_not_found(arg) if Symbol === arg
412
- nil
413
- end
414
- private :enforce_strict_symbols
400
+ private def enforce_strict(arg) # :nodoc:
401
+ raise_record_not_found(arg)
402
+ end
415
403
 
416
- # raise the {ActiveRecord::RecordNotFound} error.
417
- # @private
418
- def raise_record_not_found(arg)
419
- raise ActiveRecord::RecordNotFound, "Couldn't find a #{self.name} identified by (#{arg.inspect})"
420
- end
421
- private :raise_record_not_found
422
-
423
- end
424
-
425
- # These are instance methods for objects which are enums.
426
- module EnumInstanceMethods
427
- # Behavior depends on the type of +arg+.
428
- #
429
- # * If +arg+ is +nil+, returns +false+.
430
- # * If +arg+ is an instance of +Symbol+, +Integer+ or +String+, returns the result of +BookingStatus[:foo] == BookingStatus[arg]+.
431
- # * If +arg+ is an +Array+, returns +true+ if any member of the array returns +true+ for +===(arg)+, +false+ otherwise.
432
- # * In all other cases, delegates to +===(arg)+ of the superclass.
433
- #
434
- # Examples:
435
- #
436
- # BookingStatus[:foo] === :foo #Returns true
437
- # BookingStatus[:foo] === 'foo' #Returns true
438
- # BookingStatus[:foo] === :bar #Returns false
439
- # BookingStatus[:foo] === [:foo, :bar, :baz] #Returns true
440
- # BookingStatus[:foo] === nil #Returns false
441
- #
442
- # You should note that defining an +:on_lookup_failure+ method that raises an exception will cause +===+ to
443
- # also raise an exception for any lookup failure of +BookingStatus[arg]+.
444
- def ===(arg)
445
- case arg
446
- when nil
447
- false
448
- when Symbol, String, Integer
449
- return self == self.class[arg]
450
- when Array
451
- return self.in?(*arg)
452
- else
453
- super
404
+ private def enforce_strict_literals(arg) # :nodoc:
405
+ raise_record_not_found(arg) if (Integer === arg) || (Symbol === arg)
406
+ nil
407
+ end
408
+
409
+ private def enforce_strict_ids(arg) # :nodoc:
410
+ raise_record_not_found(arg) if Integer === arg
411
+ nil
454
412
  end
455
- end
456
413
 
457
- alias_method :like?, :===
414
+ private def enforce_strict_symbols(arg) # :nodoc:
415
+ raise_record_not_found(arg) if Symbol === arg
416
+ nil
417
+ end
458
418
 
459
- # Returns true if any element in the list returns true for ===(arg), false otherwise.
460
- def in?(*list)
461
- for item in list
462
- self === item and return true
419
+ # raise the {ActiveRecord::RecordNotFound} error.
420
+ # @private
421
+ private def raise_record_not_found(arg)
422
+ raise ActiveRecord::RecordNotFound, "Couldn't find a #{self.name} identified by (#{arg.inspect})"
463
423
  end
464
- false
465
- end
466
424
 
467
- # Returns the symbol representation of the name of the enum. BookingStatus[:foo].name_sym returns :foo.
468
- def name_sym
469
- self.__enum_name__.to_sym
470
425
  end
471
426
 
472
- alias_method :to_sym, :name_sym
427
+ # These are instance methods for objects which are enums.
428
+ module EnumInstanceMethods
429
+ # Behavior depends on the type of +arg+.
430
+ #
431
+ # * If +arg+ is +nil+, returns +false+.
432
+ # * If +arg+ is an instance of +Symbol+, +Integer+ or +String+, returns the result of +BookingStatus[:foo] == BookingStatus[arg]+.
433
+ # * If +arg+ is an +Array+, returns +true+ if any member of the array returns +true+ for +===(arg)+, +false+ otherwise.
434
+ # * In all other cases, delegates to +===(arg)+ of the superclass.
435
+ #
436
+ # Examples:
437
+ #
438
+ # BookingStatus[:foo] === :foo #Returns true
439
+ # BookingStatus[:foo] === 'foo' #Returns true
440
+ # BookingStatus[:foo] === :bar #Returns false
441
+ # BookingStatus[:foo] === [:foo, :bar, :baz] #Returns true
442
+ # BookingStatus[:foo] === nil #Returns false
443
+ #
444
+ # You should note that defining an +:on_lookup_failure+ method that raises an exception will cause +===+ to
445
+ # also raise an exception for any lookup failure of +BookingStatus[arg]+.
446
+ def ===(arg)
447
+ case arg
448
+ when nil
449
+ false
450
+ when Symbol, String, Integer
451
+ return self == self.class[arg]
452
+ when Array
453
+ return self.in?(*arg)
454
+ else
455
+ super
456
+ end
457
+ end
473
458
 
474
- # By default enumeration #to_s should return stringified name of the enum. BookingStatus[:foo].to_s returns "foo"
475
- def to_s
476
- self.__enum_name__
477
- end
459
+ alias_method :like?, :===
478
460
 
479
- # Returns true if the instance is active, false otherwise. If it has an attribute 'active',
480
- # returns the attribute cast to a boolean, otherwise returns true. This method is used by the 'active'
481
- # class method to select active enums.
482
- def active?
483
- @_active_status ||= ( attributes.include?('active') ? !!self.active : true )
484
- end
461
+ # Returns true if any element in the list returns true for ===(arg), false otherwise.
462
+ def in?(*list)
463
+ for item in list
464
+ self === item and return true
465
+ end
466
+ false
467
+ end
485
468
 
486
- # Returns true if the instance is inactive, false otherwise. Default implementations returns !active?
487
- # This method is used by the 'inactive' class method to select inactive enums.
488
- def inactive?
489
- !active?
490
- end
469
+ # Returns the symbol representation of the name of the enum. BookingStatus[:foo].name_sym returns :foo.
470
+ def name_sym
471
+ self.__enum_name__.to_sym
472
+ end
491
473
 
492
- # NOTE: updating the models that back an acts_as_enumerated is
493
- # rather dangerous because of rails' per-process model.
494
- # The cached values could get out of synch between processes
495
- # and rather than completely disallow changes I make you jump
496
- # through an extra hoop just in case you're defining your enumeration
497
- # values in Migrations. I.e. set enumeration_model_updates_permitted = true
498
- private def enumeration_model_update
499
- if self.class.enumeration_model_updates_permitted
500
- self.class.purge_enumerations_cache
501
- true
502
- else
503
- # Ugh. This just seems hack-ish. I wonder if there's a better way.
504
- if Rails.version =~ /^4\.2\.*/
505
- false
474
+ alias_method :to_sym, :name_sym
475
+
476
+ # By default enumeration #to_s should return stringified name of the enum. BookingStatus[:foo].to_s returns "foo"
477
+ def to_s
478
+ self.__enum_name__
479
+ end
480
+
481
+ # Returns true if the instance is active, false otherwise. If it has an attribute 'active',
482
+ # returns the attribute cast to a boolean, otherwise returns true. This method is used by the 'active'
483
+ # class method to select active enums.
484
+ def active?
485
+ @_active_status ||= ( attributes.include?('active') ? !!self.active : true )
486
+ end
487
+
488
+ # Returns true if the instance is inactive, false otherwise. Default implementations returns !active?
489
+ # This method is used by the 'inactive' class method to select inactive enums.
490
+ def inactive?
491
+ !active?
492
+ end
493
+
494
+ # NOTE: updating the models that back an acts_as_enumerated is
495
+ # rather dangerous because of rails' per-process model.
496
+ # The cached values could get out of synch between processes
497
+ # and rather than completely disallow changes I make you jump
498
+ # through an extra hoop just in case you're defining your enumeration
499
+ # values in Migrations. I.e. set enumeration_model_updates_permitted = true
500
+ private def enumeration_model_update
501
+ if self.class.enumeration_model_updates_permitted
502
+ self.class.purge_enumerations_cache
503
+ true
506
504
  else
507
- throw(:abort)
505
+ # Ugh. This just seems hack-ish. I wonder if there's a better way.
506
+ if Rails.version =~ /^4\.2\.*/
507
+ false
508
+ else
509
+ throw(:abort)
510
+ end
508
511
  end
509
512
  end
510
- end
511
513
 
512
- # Validates that model updates are enabled.
513
- private def validate_enumeration_model_updates_permitted
514
- unless self.class.enumeration_model_updates_permitted
515
- self.errors.add(self.class.name_column, "changes to acts_as_enumeration model instances are not permitted")
514
+ # Validates that model updates are enabled.
515
+ private def validate_enumeration_model_updates_permitted
516
+ unless self.class.enumeration_model_updates_permitted
517
+ self.errors.add(self.class.name_column, "changes to acts_as_enumeration model instances are not permitted")
518
+ end
516
519
  end
517
- end
518
- end # module EnumInstanceMethods
519
- end # module PowerEnum::Enumerated
520
+ end # module EnumInstanceMethods
521
+
522
+ end # module Enumerated
523
+
524
+ end # module PowerEnum