power_enum 1.0.1 → 1.0.2
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.
- data/README.markdown +19 -6
- data/lib/power_enum/enumerated.rb +41 -26
- data/lib/power_enum/has_enumerated.rb +89 -59
- metadata +2 -5
data/README.markdown
CHANGED
@@ -2,6 +2,9 @@
|
|
2
2
|
|
3
3
|
https://github.com/albertosaurus/power_enum
|
4
4
|
|
5
|
+
[](https://travis-ci.org/albertosaurus/power_enum)
|
6
|
+
[](https://codeclimate.com/github/albertosaurus/power_enum)
|
7
|
+
|
5
8
|
Enumerations for Rails 3.1/3.2 Done Right.
|
6
9
|
|
7
10
|
NOTICE: Version 1.0 removes support from Rails 3.0, as that version of Rails has no longer been supported for
|
@@ -726,15 +729,25 @@ Of course `Booking.new.status.should === :received` still works, but is liable t
|
|
726
729
|
|
727
730
|
## How to run tests
|
728
731
|
|
732
|
+
### Prepare the test database
|
733
|
+
|
734
|
+
#### Automatically (preferred)
|
735
|
+
|
736
|
+
Execute the test setup script:
|
737
|
+
|
738
|
+
script/test_setup.sh
|
739
|
+
|
740
|
+
#### Manually (if required)
|
741
|
+
|
729
742
|
Go to the 'dummy' project:
|
730
743
|
|
731
744
|
cd ./spec/dummy
|
732
745
|
|
733
|
-
|
746
|
+
If this is your first time, create the test database
|
734
747
|
|
735
|
-
RAILS_ENV=test rake db:
|
748
|
+
RAILS_ENV=test bundle exec rake db:create
|
736
749
|
|
737
|
-
|
750
|
+
Run migrations for test environment:
|
738
751
|
|
739
752
|
RAILS_ENV=test bundle exec rake db:migrate
|
740
753
|
|
@@ -742,9 +755,9 @@ Go back to gem root directory:
|
|
742
755
|
|
743
756
|
cd ../../
|
744
757
|
|
745
|
-
|
758
|
+
### Run tests
|
746
759
|
|
747
|
-
rake spec
|
760
|
+
bundle exec rake spec
|
748
761
|
|
749
762
|
## Copyrights and License
|
750
763
|
|
@@ -760,5 +773,5 @@ Released under the MIT License. See the LICENSE file for more details.
|
|
760
773
|
Contributions are welcome. However, please make sure of the following before issuing a pull request:
|
761
774
|
|
762
775
|
* All specs are passing.
|
763
|
-
* Any new features have test coverage.
|
776
|
+
* Any new features have test coverage. Use the SimpleCov report to confirm.
|
764
777
|
* Anything that breaks backward compatibility has a very good reason for doing so.
|
@@ -77,41 +77,56 @@ module PowerEnum::Enumerated
|
|
77
77
|
end
|
78
78
|
end
|
79
79
|
|
80
|
-
name_column = if options.has_key?(:name_column) && !options[:name_column].blank? then
|
81
|
-
options[:name_column].to_s.to_sym
|
82
|
-
else
|
83
|
-
:name
|
84
|
-
end
|
85
|
-
|
86
|
-
alias_name = if options.has_key?(:alias_name) then
|
87
|
-
options[:alias_name]
|
88
|
-
else
|
89
|
-
true
|
90
|
-
end
|
91
|
-
|
92
80
|
class_attribute :acts_enumerated_name_column
|
93
|
-
self.acts_enumerated_name_column =
|
81
|
+
self.acts_enumerated_name_column = get_name_column(options)
|
94
82
|
|
95
83
|
unless self.is_a? PowerEnum::Enumerated::EnumClassMethods
|
96
|
-
|
84
|
+
extend_enum_class_methods( options )
|
85
|
+
end
|
86
|
+
end
|
97
87
|
|
98
|
-
|
99
|
-
|
88
|
+
# Injects the class methods into model
|
89
|
+
def extend_enum_class_methods(options) #:nodoc:
|
90
|
+
extend PowerEnum::Enumerated::EnumClassMethods
|
100
91
|
|
101
|
-
|
102
|
-
|
103
|
-
validates name_column, :presence => true, :uniqueness => true
|
92
|
+
class_eval do
|
93
|
+
include PowerEnum::Enumerated::EnumInstanceMethods
|
104
94
|
|
105
|
-
|
106
|
-
|
107
|
-
|
95
|
+
before_save :enumeration_model_update
|
96
|
+
before_destroy :enumeration_model_update
|
97
|
+
validates acts_enumerated_name_column, :presence => true, :uniqueness => true
|
108
98
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
99
|
+
define_method :__enum_name__ do
|
100
|
+
read_attribute(acts_enumerated_name_column).to_s
|
101
|
+
end
|
102
|
+
|
103
|
+
if should_alias_name?(options) && acts_enumerated_name_column != :name
|
104
|
+
alias_method :name, :__enum_name__
|
105
|
+
end
|
106
|
+
end # class_eval
|
107
|
+
|
108
|
+
end
|
109
|
+
private :extend_enum_class_methods
|
110
|
+
|
111
|
+
# Determines if the name column should be explicitly aliased
|
112
|
+
def should_alias_name?(options) #:nodoc:
|
113
|
+
if options.has_key?(:alias_name) then
|
114
|
+
options[:alias_name]
|
115
|
+
else
|
116
|
+
true
|
117
|
+
end
|
118
|
+
end
|
119
|
+
private :should_alias_name?
|
120
|
+
|
121
|
+
# Extracts the name column from options or gives the default
|
122
|
+
def get_name_column(options) #:nodoc:
|
123
|
+
if options.has_key?(:name_column) && !options[:name_column].blank? then
|
124
|
+
options[:name_column].to_s.to_sym
|
125
|
+
else
|
126
|
+
:name
|
113
127
|
end
|
114
128
|
end
|
129
|
+
private :get_name_column
|
115
130
|
end
|
116
131
|
|
117
132
|
module EnumClassMethods
|
@@ -19,7 +19,7 @@ module PowerEnum::HasEnumerated # :nodoc:
|
|
19
19
|
enumerated_attributes.include? attribute.to_s
|
20
20
|
end
|
21
21
|
|
22
|
-
# Defines an enumerated attribute with the given
|
22
|
+
# Defines an enumerated attribute with the given attribute_name on the model. Also accepts a hash of options as an
|
23
23
|
# optional second argument.
|
24
24
|
#
|
25
25
|
# === Supported options
|
@@ -37,7 +37,7 @@ module PowerEnum::HasEnumerated # :nodoc:
|
|
37
37
|
# subsequent lookups, but the model will fail validation.
|
38
38
|
# 2) You can specify an instance method to be called in the case of a lookup failure. The method signature is
|
39
39
|
# as follows:
|
40
|
-
# <tt>your_lookup_handler(operation,
|
40
|
+
# <tt>your_lookup_handler(operation, attribute_name, name_foreign_key, acts_enumerated_class_name, lookup_value)</tt>
|
41
41
|
# The 'operation' arg will be either :read or :write. In the case of :read you are expected to return
|
42
42
|
# something or raise an exception, while in the case of a :write you don't have to return anything. Note that
|
43
43
|
# there's enough information in the method signature that you can specify one method to handle all lookup
|
@@ -89,35 +89,62 @@ module PowerEnum::HasEnumerated # :nodoc:
|
|
89
89
|
reflection = PowerEnum::Reflection::EnumerationReflection.new(part_id, options, self)
|
90
90
|
self.reflections = self.reflections.merge(part_id => reflection)
|
91
91
|
|
92
|
-
|
93
|
-
class_name
|
94
|
-
foreign_key
|
95
|
-
failure_opt
|
96
|
-
|
97
|
-
create_scope
|
92
|
+
attribute_name = part_id.to_s
|
93
|
+
class_name = reflection.class_name
|
94
|
+
foreign_key = reflection.foreign_key
|
95
|
+
failure_opt = options[:on_lookup_failure]
|
96
|
+
allow_empty_name = options[:permit_empty_name]
|
97
|
+
create_scope = options[:create_scope]
|
98
98
|
|
99
99
|
failure_handler = get_lookup_failure_handler(failure_opt)
|
100
100
|
|
101
|
-
class_attribute "has_enumerated_#{
|
102
|
-
self.send("has_enumerated_#{
|
101
|
+
class_attribute "has_enumerated_#{attribute_name}_error_handler"
|
102
|
+
self.send( "has_enumerated_#{attribute_name}_error_handler=", failure_handler )
|
103
103
|
|
104
|
+
define_enum_accessor attribute_name, class_name, foreign_key, failure_handler
|
105
|
+
define_enum_writer attribute_name, class_name, foreign_key, failure_handler, allow_empty_name
|
106
|
+
|
107
|
+
if failure_opt.to_s == 'validation_error'
|
108
|
+
define_validation_error( attribute_name )
|
109
|
+
end
|
110
|
+
|
111
|
+
enumerated_attributes << attribute_name
|
112
|
+
|
113
|
+
if options.has_key?(:default)
|
114
|
+
define_default_enum_value( attribute_name, options[:default] )
|
115
|
+
end
|
116
|
+
|
117
|
+
unless create_scope == false
|
118
|
+
define_enum_scope( attribute_name, class_name, foreign_key )
|
119
|
+
end
|
120
|
+
|
121
|
+
end # has_enumerated
|
122
|
+
|
123
|
+
# Defines the accessor method
|
124
|
+
def define_enum_accessor(attribute_name, class_name, foreign_key, failure_handler) #:nodoc:
|
104
125
|
module_eval( <<-end_eval, __FILE__, __LINE__ )
|
105
|
-
def #{
|
106
|
-
if @invalid_enum_values && @invalid_enum_values.has_key?(:#{
|
107
|
-
return @invalid_enum_values[:#{
|
126
|
+
def #{attribute_name}
|
127
|
+
if @invalid_enum_values && @invalid_enum_values.has_key?(:#{attribute_name})
|
128
|
+
return @invalid_enum_values[:#{attribute_name}]
|
108
129
|
end
|
109
130
|
rval = #{class_name}.lookup_id(self.#{foreign_key})
|
110
131
|
if rval.nil? && #{!failure_handler.nil?}
|
111
|
-
self.class.has_enumerated_#{
|
132
|
+
self.class.has_enumerated_#{attribute_name}_error_handler.call(self, :read, #{attribute_name.inspect}, #{foreign_key.inspect}, #{class_name.inspect}, self.#{foreign_key})
|
112
133
|
else
|
113
134
|
rval
|
114
135
|
end
|
115
136
|
end
|
137
|
+
end_eval
|
138
|
+
end
|
139
|
+
private :define_enum_accessor
|
116
140
|
|
117
|
-
|
141
|
+
# Defines the enum attribute writer method
|
142
|
+
def define_enum_writer(attribute_name, class_name, foreign_key, failure_handler, allow_empty_name) #:nodoc:
|
143
|
+
module_eval( <<-end_eval, __FILE__, __LINE__ )
|
144
|
+
def #{attribute_name}=(arg)
|
118
145
|
@invalid_enum_values ||= {}
|
119
146
|
|
120
|
-
#{!
|
147
|
+
#{!allow_empty_name ? 'arg = nil if arg.blank?' : ''}
|
121
148
|
case arg
|
122
149
|
when #{class_name}
|
123
150
|
val = #{class_name}.lookup_id(arg.id)
|
@@ -129,91 +156,94 @@ module PowerEnum::HasEnumerated # :nodoc:
|
|
129
156
|
val = #{class_name}.lookup_id(arg)
|
130
157
|
when nil
|
131
158
|
self.#{foreign_key} = nil
|
132
|
-
@invalid_enum_values.delete :#{
|
159
|
+
@invalid_enum_values.delete :#{attribute_name}
|
133
160
|
return nil
|
134
161
|
else
|
135
|
-
raise TypeError, "#{self.name}: #{
|
162
|
+
raise TypeError, "#{self.name}: #{attribute_name}= argument must be a #{class_name}, String, Symbol or Fixnum but got a: \#{arg.class.attribute_name}"
|
136
163
|
end
|
137
164
|
|
138
165
|
if val.nil?
|
139
166
|
if #{failure_handler.nil?}
|
140
|
-
raise ArgumentError, "#{self.name}: #{
|
167
|
+
raise ArgumentError, "#{self.name}: #{attribute_name}= can't assign a #{class_name} for a value of (\#{arg.inspect})"
|
141
168
|
else
|
142
|
-
@invalid_enum_values.delete :#{
|
143
|
-
self.class.has_enumerated_#{
|
169
|
+
@invalid_enum_values.delete :#{attribute_name}
|
170
|
+
self.class.has_enumerated_#{attribute_name}_error_handler.call(self, :write, #{attribute_name.inspect}, #{foreign_key.inspect}, #{class_name.inspect}, arg)
|
144
171
|
end
|
145
172
|
else
|
146
|
-
@invalid_enum_values.delete :#{
|
173
|
+
@invalid_enum_values.delete :#{attribute_name}
|
147
174
|
self.#{foreign_key} = val.id
|
148
175
|
end
|
149
176
|
end
|
150
177
|
|
151
|
-
alias_method :'#{
|
178
|
+
alias_method :'#{attribute_name}_bak=', :'#{attribute_name}='
|
152
179
|
end_eval
|
180
|
+
end
|
181
|
+
private :define_enum_writer
|
153
182
|
|
154
|
-
|
155
|
-
|
183
|
+
# Defines the default value for the enumerated attribute.
|
184
|
+
def define_default_enum_value(attribute_name, default) #:nodoc:
|
185
|
+
set_default_method = "set_default_value_for_#{attribute_name}".to_sym
|
186
|
+
|
187
|
+
after_initialize set_default_method
|
188
|
+
|
189
|
+
define_method set_default_method do
|
190
|
+
self.send("#{attribute_name}=", default) if self.send(attribute_name).nil?
|
191
|
+
end
|
192
|
+
private set_default_method
|
193
|
+
end
|
194
|
+
private :define_default_enum_value
|
195
|
+
|
196
|
+
# Defines validation_error handling mechanism
|
197
|
+
def define_validation_error(attribute_name) #:nodoc:
|
198
|
+
module_eval(<<-end_eval, __FILE__, __LINE__)
|
156
199
|
validate do
|
157
|
-
if @invalid_enum_values && @invalid_enum_values.has_key?(:#{
|
158
|
-
errors.add(:#{
|
200
|
+
if @invalid_enum_values && @invalid_enum_values.has_key?(:#{attribute_name})
|
201
|
+
errors.add(:#{attribute_name}, "is invalid")
|
159
202
|
end
|
160
203
|
end
|
161
204
|
|
162
|
-
def validation_error(operation,
|
205
|
+
def validation_error(operation, attribute_name, name_foreign_key, acts_enumerated_class_name, lookup_value)
|
163
206
|
@invalid_enum_values ||= {}
|
164
207
|
if operation == :write
|
165
|
-
@invalid_enum_values[
|
208
|
+
@invalid_enum_values[attribute_name.to_sym] = lookup_value
|
166
209
|
else
|
167
210
|
nil
|
168
211
|
end
|
169
212
|
end
|
170
213
|
private :validation_error
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
enumerated_attributes << name
|
175
|
-
|
176
|
-
if options.has_key?(:default)
|
177
|
-
default = options[:default]
|
178
|
-
set_default_method = "set_default_value_for_#{name}".to_sym
|
179
|
-
|
180
|
-
after_initialize set_default_method
|
181
|
-
|
182
|
-
define_method set_default_method do
|
183
|
-
self.send("#{name}=", default) if self.send(name).nil?
|
184
|
-
end
|
185
|
-
private set_default_method
|
186
|
-
end
|
214
|
+
end_eval
|
215
|
+
end
|
216
|
+
private :define_validation_error
|
187
217
|
|
188
|
-
|
189
|
-
|
190
|
-
|
218
|
+
# Defines the enum scopes on the model
|
219
|
+
def define_enum_scope(attribute_name, class_name, foreign_key) #:nodoc:
|
220
|
+
module_eval(<<-end_eval, __FILE__, __LINE__)
|
221
|
+
scope :with_#{attribute_name}, lambda { |*args|
|
191
222
|
ids = args.map{ |arg|
|
192
223
|
n = #{class_name}[arg]
|
193
224
|
}
|
194
225
|
where(:#{foreign_key} => ids)
|
195
226
|
}
|
196
|
-
scope :exclude_#{
|
227
|
+
scope :exclude_#{attribute_name}, lambda {|*args|
|
197
228
|
ids = #{class_name}.all - args.map{ |arg|
|
198
229
|
n = #{class_name}[arg]
|
199
230
|
}
|
200
231
|
where(:#{foreign_key} => ids)
|
201
232
|
}
|
202
|
-
|
233
|
+
end_eval
|
203
234
|
|
204
|
-
|
205
|
-
|
235
|
+
if (name_p = attribute_name.pluralize) != attribute_name
|
236
|
+
module_eval(<<-end_eval, __FILE__, __LINE__)
|
206
237
|
class << self
|
207
|
-
alias_method :with_#{name_p}, :with_#{
|
208
|
-
alias_method :exclude_#{name_p}, :exclude_#{
|
238
|
+
alias_method :with_#{name_p}, :with_#{attribute_name}
|
239
|
+
alias_method :exclude_#{name_p}, :exclude_#{attribute_name}
|
209
240
|
end
|
210
|
-
|
211
|
-
end
|
241
|
+
end_eval
|
212
242
|
end
|
243
|
+
end
|
244
|
+
private :define_enum_scope
|
213
245
|
|
214
|
-
|
215
|
-
|
216
|
-
# If the lookup failure handler is a method name, wraps it in a lambda.
|
246
|
+
# If the lookup failure handler is a method attribute_name, wraps it in a lambda.
|
217
247
|
def get_lookup_failure_handler(failure_opt) # :nodoc:
|
218
248
|
if failure_opt.nil?
|
219
249
|
nil
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: power_enum
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -12,7 +12,7 @@ authors:
|
|
12
12
|
autorequire:
|
13
13
|
bindir: bin
|
14
14
|
cert_chain: []
|
15
|
-
date: 2013-01-
|
15
|
+
date: 2013-01-28 00:00:00.000000000 Z
|
16
16
|
dependencies:
|
17
17
|
- !ruby/object:Gem::Dependency
|
18
18
|
name: rails
|
@@ -142,9 +142,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
142
142
|
- - ! '>='
|
143
143
|
- !ruby/object:Gem::Version
|
144
144
|
version: '0'
|
145
|
-
segments:
|
146
|
-
- 0
|
147
|
-
hash: 1934880016458665867
|
148
145
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
149
146
|
none: false
|
150
147
|
requirements:
|