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,137 +2,141 @@
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 has_enumerated
6
- module PowerEnum::HasEnumerated
7
-
8
- extend ActiveSupport::Concern
9
-
10
- # Class-level behavior injected into ActiveRecord to support has_enumerated
11
- module ClassMethods
12
-
13
- # Returns a list of all the attributes on the ActiveRecord model which are enumerated.
14
- def enumerated_attributes
15
- @enumerated_attributes ||= []
16
- end
17
-
18
- # Returns +true+ if +attribute+ is an enumerated attribute, +false+ otherwise.
19
- def has_enumerated?(attribute)
20
- return false if attribute.nil?
21
- enumerated_attributes.include? attribute.to_s
22
- end
23
-
24
- # Defines an enumerated attribute with the given attribute_name on the model. Also accepts a hash of options as an
25
- # optional second argument.
26
- #
27
- # === Supported options
28
- # [:class_name]
29
- # Name of the enum class. By default it is the camelized version of the has_enumerated attribute.
30
- # [:foreign_key]
31
- # Explicitly set the foreign key column. By default it's assumed to be your_enumerated_attribute_name_id.
32
- # [:on_lookup_failure]
33
- # The :on_lookup_failure option in has_enumerated is there because you may want to create an error handler for
34
- # situations where the argument passed to status=(arg) is invalid. By default, an invalid value will cause an
35
- # ArgumentError to be raised. Since this may not be optimal in your situation, you can do one of three
36
- # things:
37
- #
38
- # 1) You can set it to 'validation_error'. In this case, the invalid value will be cached and returned on
39
- # subsequent lookups, but the model will fail validation.
40
- # 2) You can specify an instance method to be called in the case of a lookup failure. The method signature is
41
- # as follows:
42
- # <tt>your_lookup_handler(operation, attribute_name, name_foreign_key, acts_enumerated_class_name, lookup_value)</tt>
43
- # The 'operation' arg will be either :read or :write. In the case of :read you are expected to return
44
- # something or raise an exception, while in the case of a :write you don't have to return anything. Note that
45
- # there's enough information in the method signature that you can specify one method to handle all lookup
46
- # failures for all has_enumerated fields if you happen to have more than one defined in your model.
47
- # 'NOTE': A nil is always considered to be a valid value for status=(arg) since it's assumed you're trying to
48
- # null out the foreign key. The :on_lookup_failure method will be bypassed.
49
- # 3) You can give it a lambda function. In that case, the lambda needs to accept the ActiveRecord model as
50
- # its first argument, with the rest of the arguments being identical to the signature of the lookup handler
51
- # instance method.
52
- # [:permit_empty_name]
53
- # Setting this to 'true' disables automatic conversion of empty strings to nil. Default is 'false'.
54
- # [:default]
55
- # Setting this option will generate an after_initialize callback to set a default value on the attribute
56
- # unless a non-nil one already exists.
57
- # [:create_scope]
58
- # Setting this option to 'false' will disable automatically creating 'with_enum_attribute' and
59
- # 'exclude_enum_attribute' scope.
60
- #
61
- # === Example
62
- # class Booking < ActiveRecord::Base
63
- # has_enumerated :status,
64
- # :class_name => 'BookingStatus',
65
- # :foreign_key => 'status_id',
66
- # :on_lookup_failure => :optional_instance_method,
67
- # :permit_empty_name => true,
68
- # :default => :unconfirmed,
69
- # :create_cope => false
70
- # end
71
- #
72
- # === Example 2
73
- #
74
- # class Booking < ActiveRecord::Base
75
- # has_enumerated :booking_status,
76
- # :class_name => 'BookingStatus',
77
- # :foreign_key => 'status_id',
78
- # :on_lookup_failure => lambda{ |record, op, attr, fk, cl_name, value|
79
- # # handle lookup failure
80
- # }
81
- # end
82
- def has_enumerated(part_id, options = {})
83
- options.assert_valid_keys( :class_name,
84
- :foreign_key,
85
- :on_lookup_failure,
86
- :permit_empty_name,
87
- :default,
88
- :create_scope )
89
-
90
- # Add a reflection for the enumerated attribute.
91
- reflection = create_ar_reflection(part_id, options)
92
-
93
- attribute_name = part_id.to_s
94
- class_name = reflection.class_name
95
- foreign_key = reflection.foreign_key
96
- failure_opt = options[:on_lookup_failure]
97
- allow_empty_name = options[:permit_empty_name]
98
- create_scope = options[:create_scope]
99
-
100
- failure_handler = get_lookup_failure_handler(failure_opt)
101
-
102
- class_attribute "has_enumerated_#{attribute_name}_error_handler"
103
- self.send( "has_enumerated_#{attribute_name}_error_handler=", failure_handler )
104
-
105
- define_enum_accessor attribute_name, class_name, foreign_key, failure_handler
106
- define_enum_writer attribute_name, class_name, foreign_key, failure_handler, allow_empty_name
107
-
108
- if failure_opt.to_s == 'validation_error'
109
- define_validation_error( attribute_name )
110
- end
5
+ module PowerEnum
6
+
7
+ # Implementation of has_enumerated
8
+ module HasEnumerated
9
+
10
+ extend ActiveSupport::Concern
111
11
 
112
- enumerated_attributes << attribute_name
12
+ # Class-level behavior injected into ActiveRecord to support has_enumerated
13
+ module ClassMethods
14
+
15
+ # Returns a list of all the attributes on the ActiveRecord model which are enumerated.
16
+ def enumerated_attributes
17
+ @enumerated_attributes ||= []
18
+ end
113
19
 
114
- if options.has_key?(:default)
115
- define_default_enum_value( attribute_name, options[:default] )
20
+ # Returns +true+ if +attribute+ is an enumerated attribute, +false+ otherwise.
21
+ def has_enumerated?(attribute)
22
+ return false if attribute.nil?
23
+ enumerated_attributes.include? attribute.to_s
116
24
  end
117
25
 
118
- unless create_scope == false
119
- define_enum_scope( attribute_name, class_name, foreign_key )
26
+ # Defines an enumerated attribute with the given attribute_name on the model. Also accepts a hash of options as an
27
+ # optional second argument.
28
+ #
29
+ # === Supported options
30
+ # [:class_name]
31
+ # Name of the enum class. By default it is the camelized version of the has_enumerated attribute.
32
+ # [:foreign_key]
33
+ # Explicitly set the foreign key column. By default it's assumed to be your_enumerated_attribute_name_id.
34
+ # [:on_lookup_failure]
35
+ # The :on_lookup_failure option in has_enumerated is there because you may want to create an error handler for
36
+ # situations where the argument passed to status=(arg) is invalid. By default, an invalid value will cause an
37
+ # ArgumentError to be raised. Since this may not be optimal in your situation, you can do one of three
38
+ # things:
39
+ #
40
+ # 1) You can set it to 'validation_error'. In this case, the invalid value will be cached and returned on
41
+ # subsequent lookups, but the model will fail validation.
42
+ # 2) You can specify an instance method to be called in the case of a lookup failure. The method signature is
43
+ # as follows:
44
+ # <tt>your_lookup_handler(operation, attribute_name, name_foreign_key, acts_enumerated_class_name, lookup_value)</tt>
45
+ # The 'operation' arg will be either :read or :write. In the case of :read you are expected to return
46
+ # something or raise an exception, while in the case of a :write you don't have to return anything. Note that
47
+ # there's enough information in the method signature that you can specify one method to handle all lookup
48
+ # failures for all has_enumerated fields if you happen to have more than one defined in your model.
49
+ # 'NOTE': A nil is always considered to be a valid value for status=(arg) since it's assumed you're trying to
50
+ # null out the foreign key. The :on_lookup_failure method will be bypassed.
51
+ # 3) You can give it a lambda function. In that case, the lambda needs to accept the ActiveRecord model as
52
+ # its first argument, with the rest of the arguments being identical to the signature of the lookup handler
53
+ # instance method.
54
+ # [:permit_empty_name]
55
+ # Setting this to 'true' disables automatic conversion of empty strings to nil. Default is 'false'.
56
+ # [:default]
57
+ # Setting this option will generate an after_initialize callback to set a default value on the attribute
58
+ # unless a non-nil one already exists.
59
+ # [:create_scope]
60
+ # Setting this option to 'false' will disable automatically creating 'with_enum_attribute' and
61
+ # 'exclude_enum_attribute' scope.
62
+ #
63
+ # === Example
64
+ # class Booking < ActiveRecord::Base
65
+ # has_enumerated :status,
66
+ # :class_name => 'BookingStatus',
67
+ # :foreign_key => 'status_id',
68
+ # :on_lookup_failure => :optional_instance_method,
69
+ # :permit_empty_name => true,
70
+ # :default => :unconfirmed,
71
+ # :create_cope => false
72
+ # end
73
+ #
74
+ # === Example 2
75
+ #
76
+ # class Booking < ActiveRecord::Base
77
+ # has_enumerated :booking_status,
78
+ # :class_name => 'BookingStatus',
79
+ # :foreign_key => 'status_id',
80
+ # :on_lookup_failure => lambda{ |record, op, attr, fk, cl_name, value|
81
+ # # handle lookup failure
82
+ # }
83
+ # end
84
+ def has_enumerated(part_id, options = {})
85
+ options.assert_valid_keys(:class_name,
86
+ :foreign_key,
87
+ :on_lookup_failure,
88
+ :permit_empty_name,
89
+ :default,
90
+ :create_scope)
91
+
92
+ # Add a reflection for the enumerated attribute.
93
+ reflection = create_ar_reflection(part_id, options)
94
+
95
+ attribute_name = part_id.to_s
96
+ class_name = reflection.class_name
97
+ foreign_key = reflection.foreign_key
98
+ failure_opt = options[:on_lookup_failure]
99
+ allow_empty_name = options[:permit_empty_name]
100
+ create_scope = options[:create_scope]
101
+
102
+ failure_handler = get_lookup_failure_handler(failure_opt)
103
+
104
+ class_attribute "has_enumerated_#{attribute_name}_error_handler"
105
+ self.send("has_enumerated_#{attribute_name}_error_handler=", failure_handler)
106
+
107
+ define_enum_accessor attribute_name, class_name, foreign_key, failure_handler
108
+ define_enum_writer attribute_name, class_name, foreign_key, failure_handler, allow_empty_name
109
+
110
+ if failure_opt.to_s == 'validation_error'
111
+ define_validation_error(attribute_name)
112
+ end
113
+
114
+ enumerated_attributes << attribute_name
115
+
116
+ if options.has_key?(:default)
117
+ define_default_enum_value(attribute_name, options[:default])
118
+ end
119
+
120
+ unless create_scope == false
121
+ define_enum_scope(attribute_name, class_name, foreign_key)
122
+ end
123
+
120
124
  end
121
125
 
122
- end # has_enumerated
126
+ # has_enumerated
123
127
 
124
- # Creates the ActiveRecord reflection
125
- def create_ar_reflection(part_id, options)
126
- reflection = PowerEnum::Reflection::EnumerationReflection.new(part_id, options, self)
128
+ # Creates the ActiveRecord reflection
129
+ private def create_ar_reflection(part_id, options)
130
+ reflection = PowerEnum::Reflection::EnumerationReflection.new(part_id, options, self)
127
131
 
128
- self._reflections = self._reflections.merge(part_id.to_s => reflection)
129
- reflection
130
- end
131
- private :create_ar_reflection
132
+ self._reflections = self._reflections.merge(part_id.to_s => reflection)
133
+ reflection
134
+ end
132
135
 
133
- # Defines the accessor method
134
- def define_enum_accessor(attribute_name, class_name, foreign_key, failure_handler) #:nodoc:
135
- module_eval( <<-end_eval, __FILE__, __LINE__ )
136
+ # Defines the accessor method
137
+ private def define_enum_accessor(attribute_name, class_name, foreign_key, failure_handler)
138
+ #:nodoc:
139
+ module_eval(<<-end_eval, __FILE__, __LINE__)
136
140
  def #{attribute_name}
137
141
  if @invalid_enum_values && @invalid_enum_values.has_key?(:#{attribute_name})
138
142
  return @invalid_enum_values[:#{attribute_name}]
@@ -144,13 +148,13 @@ module PowerEnum::HasEnumerated
144
148
  rval
145
149
  end
146
150
  end
147
- end_eval
148
- end
149
- private :define_enum_accessor
151
+ end_eval
152
+ end
150
153
 
151
- # Defines the enum attribute writer method
152
- def define_enum_writer(attribute_name, class_name, foreign_key, failure_handler, allow_empty_name) #:nodoc:
153
- module_eval( <<-end_eval, __FILE__, __LINE__ )
154
+ # Defines the enum attribute writer method
155
+ private def define_enum_writer(attribute_name, class_name, foreign_key, failure_handler, allow_empty_name)
156
+ #:nodoc:
157
+ module_eval(<<-end_eval, __FILE__, __LINE__)
154
158
  def #{attribute_name}=(arg)
155
159
  @invalid_enum_values ||= {}
156
160
 
@@ -186,26 +190,26 @@ module PowerEnum::HasEnumerated
186
190
  end
187
191
 
188
192
  alias_method :'#{attribute_name}_bak=', :'#{attribute_name}='
189
- end_eval
190
- end
191
- private :define_enum_writer
193
+ end_eval
194
+ end
192
195
 
193
- # Defines the default value for the enumerated attribute.
194
- def define_default_enum_value(attribute_name, default) #:nodoc:
195
- set_default_method = "set_default_value_for_#{attribute_name}".to_sym
196
+ # Defines the default value for the enumerated attribute.
197
+ private def define_default_enum_value(attribute_name, default)
198
+ #:nodoc:
199
+ set_default_method = "set_default_value_for_#{attribute_name}".to_sym
196
200
 
197
- after_initialize set_default_method
201
+ after_initialize set_default_method
198
202
 
199
- define_method set_default_method do
200
- self.send("#{attribute_name}=", default) if self.send(attribute_name).nil?
203
+ define_method set_default_method do
204
+ self.send("#{attribute_name}=", default) if self.send(attribute_name).nil?
205
+ end
206
+ private set_default_method
201
207
  end
202
- private set_default_method
203
- end
204
- private :define_default_enum_value
205
208
 
206
- # Defines validation_error handling mechanism
207
- def define_validation_error(attribute_name) #:nodoc:
208
- module_eval(<<-end_eval, __FILE__, __LINE__)
209
+ # Defines validation_error handling mechanism
210
+ private def define_validation_error(attribute_name)
211
+ #:nodoc:
212
+ module_eval(<<-end_eval, __FILE__, __LINE__)
209
213
  validate do
210
214
  if @invalid_enum_values && @invalid_enum_values.has_key?(:#{attribute_name})
211
215
  errors.add(:#{attribute_name}, "is invalid")
@@ -221,13 +225,13 @@ module PowerEnum::HasEnumerated
221
225
  end
222
226
  end
223
227
  private :validation_error
224
- end_eval
225
- end
226
- private :define_validation_error
228
+ end_eval
229
+ end
227
230
 
228
- # Defines the enum scopes on the model
229
- def define_enum_scope(attribute_name, class_name, foreign_key) #:nodoc:
230
- module_eval(<<-end_eval, __FILE__, __LINE__)
231
+ # Defines the enum scopes on the model
232
+ private def define_enum_scope(attribute_name, class_name, foreign_key)
233
+ #:nodoc:
234
+ module_eval(<<-end_eval, __FILE__, __LINE__)
231
235
  scope :with_#{attribute_name}, lambda { |*args|
232
236
  ids = args.map{ |arg|
233
237
  n = #{class_name}[arg]
@@ -240,37 +244,36 @@ module PowerEnum::HasEnumerated
240
244
  }
241
245
  where(:#{foreign_key} => ids)
242
246
  }
243
- end_eval
247
+ end_eval
244
248
 
245
- if (name_p = attribute_name.pluralize) != attribute_name
246
- module_eval(<<-end_eval, __FILE__, __LINE__)
249
+ if (name_p = attribute_name.pluralize) != attribute_name
250
+ module_eval(<<-end_eval, __FILE__, __LINE__)
247
251
  class << self
248
252
  alias_method :with_#{name_p}, :with_#{attribute_name}
249
253
  alias_method :exclude_#{name_p}, :exclude_#{attribute_name}
250
254
  end
251
- end_eval
255
+ end_eval
256
+ end
252
257
  end
253
- end
254
- private :define_enum_scope
255
-
256
- # If the lookup failure handler is a method attribute_name, wraps it in a lambda.
257
- def get_lookup_failure_handler(failure_opt) # :nodoc:
258
- if failure_opt.nil?
259
- nil
260
- else
261
- case failure_opt
262
- when Proc
263
- failure_opt
258
+
259
+ # If the lookup failure handler is a method attribute_name, wraps it in a lambda.
260
+ private def get_lookup_failure_handler(failure_opt)
261
+ # :nodoc:
262
+ if failure_opt.nil?
263
+ nil
264
264
  else
265
- lambda { |record, op, attr, fk, cl_name, value|
266
- record.send(failure_opt.to_s, op, attr, fk, cl_name, value)
267
- }
268
- end
265
+ case failure_opt
266
+ when Proc
267
+ failure_opt
268
+ else
269
+ lambda { |record, op, attr, fk, cl_name, value|
270
+ record.send(failure_opt.to_s, op, attr, fk, cl_name, value)
271
+ }
272
+ end
269
273
 
274
+ end
270
275
  end
271
- end
272
- private :get_lookup_failure_handler
273
-
274
- end #module MacroMethods
275
276
 
277
+ end #module MacroMethods
278
+ end
276
279
  end #module PowerEnum::HasEnumerated
@@ -120,6 +120,11 @@ of these associations is deprecated and will be removed in the future.
120
120
  false
121
121
  end
122
122
 
123
+ # Always returns true.
124
+ def collection?
125
+ true
126
+ end
127
+
123
128
  # In this case, returns [[]]
124
129
  def conditions
125
130
  [[]]
data/lib/power_enum.rb CHANGED
@@ -2,34 +2,44 @@ require 'rails'
2
2
  require 'active_record'
3
3
  require 'testing/rspec'
4
4
 
5
+ require "power_enum/has_enumerated"
6
+ require "power_enum/enumerated"
7
+ require "power_enum/reflection"
8
+
9
+ require "power_enum/schema/schema_statements"
10
+ require "power_enum/migration/command_recorder"
11
+
12
+ require "active_record/virtual_enumerations"
13
+
5
14
  # Power Enum allows you to treat instances of your ActiveRecord models as
6
15
  # though they were an enumeration of values. It allows you to cleanly solve
7
16
  # many of the problems that the traditional Rails alternatives handle poorly
8
17
  # if at all. It is particularly suitable for scenarios where your Rails
9
18
  # application is not the only user of the database, such as when it's used for
10
19
  # analytics or reporting.
11
- class PowerEnum < Rails::Engine
12
- config.autoload_paths << File.expand_path(File.join(__FILE__, "../"))
20
+ module PowerEnum
21
+ class Engine < Rails::Engine
13
22
 
14
- initializer 'power_enum' do
15
- ActiveSupport.on_load(:active_record) do
16
- include PowerEnum::Enumerated
17
- include PowerEnum::HasEnumerated
23
+ initializer 'power_enum' do
24
+ ActiveSupport.on_load(:active_record) do
25
+ include PowerEnum::Enumerated
26
+ include PowerEnum::HasEnumerated
18
27
 
19
- ActiveRecord::Base.module_eval do
20
- class << self
21
- prepend ::PowerEnum::Reflection
28
+ ActiveRecord::Base.module_eval do
29
+ class << self
30
+ prepend ::PowerEnum::Reflection
31
+ end
22
32
  end
23
- end
24
33
 
25
- ActiveRecord::ConnectionAdapters.module_eval do
26
- include PowerEnum::Schema::SchemaStatements
27
- end
34
+ ActiveRecord::ConnectionAdapters.module_eval do
35
+ include PowerEnum::Schema::SchemaStatements
36
+ end
28
37
 
29
- ActiveRecord::Migration::CommandRecorder.class_eval do
30
- include PowerEnum::Migration::CommandRecorder
38
+ ActiveRecord::Migration::CommandRecorder.class_eval do
39
+ include PowerEnum::Migration::CommandRecorder
40
+ end
31
41
  end
32
- end
33
42
 
43
+ end
34
44
  end
35
45
  end
metadata CHANGED
@@ -1,17 +1,17 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: power_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.0
4
+ version: 3.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Trevor Squires
8
8
  - Pivotal Labs
9
9
  - Arthur Shagall
10
10
  - Sergey Potapov
11
- autorequire:
11
+ autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2019-01-26 00:00:00.000000000 Z
14
+ date: 2021-12-08 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: bundler
@@ -64,7 +64,7 @@ dependencies:
64
64
  version: '4.2'
65
65
  - - "<"
66
66
  - !ruby/object:Gem::Version
67
- version: '6'
67
+ version: '7'
68
68
  type: :development
69
69
  prerelease: false
70
70
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  version: '4.2'
75
75
  - - "<"
76
76
  - !ruby/object:Gem::Version
77
- version: '6'
77
+ version: '7'
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: railties
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -84,7 +84,7 @@ dependencies:
84
84
  version: '4.2'
85
85
  - - "<"
86
86
  - !ruby/object:Gem::Version
87
- version: '6'
87
+ version: '7'
88
88
  type: :runtime
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
@@ -94,7 +94,7 @@ dependencies:
94
94
  version: '4.2'
95
95
  - - "<"
96
96
  - !ruby/object:Gem::Version
97
- version: '6'
97
+ version: '7'
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: activerecord
100
100
  requirement: !ruby/object:Gem::Requirement
@@ -104,7 +104,7 @@ dependencies:
104
104
  version: '4.2'
105
105
  - - "<"
106
106
  - !ruby/object:Gem::Version
107
- version: '6'
107
+ version: '7'
108
108
  type: :runtime
109
109
  prerelease: false
110
110
  version_requirements: !ruby/object:Gem::Requirement
@@ -114,7 +114,7 @@ dependencies:
114
114
  version: '4.2'
115
115
  - - "<"
116
116
  - !ruby/object:Gem::Version
117
- version: '6'
117
+ version: '7'
118
118
  description: |
119
119
  Power Enum allows you to treat instances of your ActiveRecord models as though they were an enumeration of values.
120
120
  It allows you to cleanly solve many of the problems that the traditional Rails alternatives handle poorly if at all.
@@ -126,9 +126,11 @@ extensions: []
126
126
  extra_rdoc_files:
127
127
  - LICENSE
128
128
  - README.markdown
129
+ - VERSION
129
130
  files:
130
131
  - LICENSE
131
132
  - README.markdown
133
+ - VERSION
132
134
  - lib/active_record/virtual_enumerations.rb
133
135
  - lib/generators/enum/USAGE
134
136
  - lib/generators/enum/enum_generator.rb
@@ -149,7 +151,7 @@ homepage: http://github.com/albertosaurus/power_enum_2
149
151
  licenses:
150
152
  - MIT
151
153
  metadata: {}
152
- post_install_message:
154
+ post_install_message:
153
155
  rdoc_options: []
154
156
  require_paths:
155
157
  - lib
@@ -164,9 +166,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
166
  - !ruby/object:Gem::Version
165
167
  version: '0'
166
168
  requirements: []
167
- rubyforge_project:
168
- rubygems_version: 2.6.14.1
169
- signing_key:
169
+ rubygems_version: 3.0.8
170
+ signing_key:
170
171
  specification_version: 4
171
172
  summary: Allows you to treat instances of your ActiveRecord models as though they
172
173
  were an enumeration of values