power_enum 3.3.0 → 3.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+ 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