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.
@@ -2,6 +2,9 @@
2
2
 
3
3
  https://github.com/albertosaurus/power_enum
4
4
 
5
+ [![Build Status](https://travis-ci.org/albertosaurus/power_enum.png)](https://travis-ci.org/albertosaurus/power_enum)
6
+ [![Code Climate](https://codeclimate.com/badge.png)](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
- Run migrations for test environment:
746
+ If this is your first time, create the test database
734
747
 
735
- RAILS_ENV=test rake db:migrate
748
+ RAILS_ENV=test bundle exec rake db:create
736
749
 
737
- You may need to use `bundle exec` if you have gem conflicts:
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
- And finally run tests:
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 = name_column
81
+ self.acts_enumerated_name_column = get_name_column(options)
94
82
 
95
83
  unless self.is_a? PowerEnum::Enumerated::EnumClassMethods
96
- extend PowerEnum::Enumerated::EnumClassMethods
84
+ extend_enum_class_methods( options )
85
+ end
86
+ end
97
87
 
98
- class_eval do
99
- include PowerEnum::Enumerated::EnumInstanceMethods
88
+ # Injects the class methods into model
89
+ def extend_enum_class_methods(options) #:nodoc:
90
+ extend PowerEnum::Enumerated::EnumClassMethods
100
91
 
101
- before_save :enumeration_model_update
102
- before_destroy :enumeration_model_update
103
- validates name_column, :presence => true, :uniqueness => true
92
+ class_eval do
93
+ include PowerEnum::Enumerated::EnumInstanceMethods
104
94
 
105
- define_method :__enum_name__ do
106
- read_attribute( name_column ).to_s
107
- end
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
- if alias_name && name_column != :name
110
- alias_method :name, :__enum_name__
111
- end
112
- end # class_eval
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 name on the model. Also accepts a hash of options as an
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, name, name_foreign_key, acts_enumerated_class_name, lookup_value)</tt>
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
- 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
- empty_name = options[:permit_empty_name]
97
- create_scope = options[: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_#{name}_error_handler"
102
- self.send("has_enumerated_#{name}_error_handler=", failure_handler)
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 #{name}
106
- if @invalid_enum_values && @invalid_enum_values.has_key?(:#{name})
107
- return @invalid_enum_values[:#{name}]
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_#{name}_error_handler.call(self, :read, #{name.inspect}, #{foreign_key.inspect}, #{class_name.inspect}, self.#{foreign_key})
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
- def #{name}=(arg)
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
- #{!empty_name ? 'arg = nil if arg.blank?' : ''}
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 :#{name}
159
+ @invalid_enum_values.delete :#{attribute_name}
133
160
  return nil
134
161
  else
135
- raise TypeError, "#{self.name}: #{name}= argument must be a #{class_name}, String, Symbol or Fixnum but got a: \#{arg.class.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}: #{name}= can't assign a #{class_name} for a value of (\#{arg.inspect})"
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 :#{name}
143
- self.class.has_enumerated_#{name}_error_handler.call(self, :write, #{name.inspect}, #{foreign_key.inspect}, #{class_name.inspect}, arg)
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 :#{name}
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 :'#{name}_bak=', :'#{name}='
178
+ alias_method :'#{attribute_name}_bak=', :'#{attribute_name}='
152
179
  end_eval
180
+ end
181
+ private :define_enum_writer
153
182
 
154
- if failure_opt.to_s == 'validation_error'
155
- module_eval( <<-end_eval, __FILE__, __LINE__ )
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?(:#{name})
158
- errors.add(:#{name}, "is invalid")
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, name, name_foreign_key, acts_enumerated_class_name, lookup_value)
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[name.to_sym] = lookup_value
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
- end_eval
172
- end
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
- unless create_scope == false
189
- module_eval( <<-end_eval, __FILE__, __LINE__)
190
- scope :with_#{name}, lambda { |*args|
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_#{name}, lambda {|*args|
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
- end_eval
233
+ end_eval
203
234
 
204
- if (name_p = name.pluralize) != name
205
- module_eval( <<-end_eval, __FILE__, __LINE__)
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_#{name}
208
- alias_method :exclude_#{name_p}, :exclude_#{name}
238
+ alias_method :with_#{name_p}, :with_#{attribute_name}
239
+ alias_method :exclude_#{name_p}, :exclude_#{attribute_name}
209
240
  end
210
- end_eval
211
- end
241
+ end_eval
212
242
  end
243
+ end
244
+ private :define_enum_scope
213
245
 
214
- end #has_enumerated
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.1
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-27 00:00:00.000000000 Z
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: