power_enum 1.0.1 → 1.0.2

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