classy_enum 3.5.0 → 4.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d42689788d2614aa9bc9c81ef05920c064b88cb3
4
- data.tar.gz: 01cf9ada7b577004ddbe61565df1423fd93e62a5
3
+ metadata.gz: 461b3c90498c65da6f580b4f0b2fd794eb28a832
4
+ data.tar.gz: 02b9a83c3337c4af82268c9e2ed48b18dc23f217
5
5
  SHA512:
6
- metadata.gz: f5cbe7b796bd2967172d963aac361b76fb505f879a2a85fd4f991cce8626373d9f3255c9271c946b355749e75099a328bb7afabc5f20b8ec0f2230344e51bd78
7
- data.tar.gz: 348a62ab03bfb9db36ed18cf306368ad9b941d86f51dbd6fb4148fdf868d6058a9d8853cf7844768a219480c7426f9f8ebd26e0f2256f0dd5e4975664354d877
6
+ metadata.gz: 3c438e006bef648f25c0217a752d1a8b9d8057afd720e0580dc09d10321bb970a81bdc9c369a07b5637a7b12586abfb58559d021c8f3d3ff98bc0fa897546b93
7
+ data.tar.gz: 4f8b082c843c9fbbbf27f36b39cc691c75984f13400bba0cf557a4a8c64b6a3a05cc69a46dd881241490ee519ebdb5dc60f15ebd070dde7825a62fdfa62a5c21
@@ -2,13 +2,9 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
- - 2.1.1
5
+ - 2.1.3
6
6
  gemfile:
7
- - gemfiles/Gemfile.rails-3.0.x
8
- - gemfiles/Gemfile.rails-3.1.x
9
7
  - gemfiles/Gemfile.rails-3.2.x
10
8
  - gemfiles/Gemfile.rails-4.0.x
11
- matrix:
12
- exclude:
13
- - rvm: 1.8.7
14
- gemfile: gemfiles/Gemfile.rails-4.0.x
9
+ - gemfiles/Gemfile.rails-4.1.x
10
+ - gemfiles/Gemfile.rails-4.2.x
@@ -1,5 +1,16 @@
1
1
  # ClassyEnum Changelog
2
2
 
3
+ ## 4.0.0 (Unreleased)
4
+
5
+ * [BREAKING] Removes support for Ruby 1.8.7
6
+ * [BREAKING] Removes support for Rails 3.0.x and 3.1.x
7
+ * [BREAKING] Active Record models must explicitly include ClassyEnum::ActiveRecord now
8
+ * [BREAKING] Removed use of null objects. Blank values are now returned as is from Enum.build.
9
+ * [BREAKING] Removed serialize_as_json option. #as_json should be overriden in ClassyEnum::Base subclasses instead.
10
+ * [BREAKING] Removed allow_blank option from Enum.build. This was used internally for legacy reasons and is no longer needed.
11
+ * [BREAKING] Fixes support for ActiveModel::Dirty. Now dirty attribute methods always return enum class instance (instead of string).
12
+ * Prefer 'class_name' over 'enum' as optional class name argument
13
+
3
14
  ## 3.5.0
4
15
 
5
16
  * Fixes long standing issue with default values not being persisted to
data/README.md CHANGED
@@ -11,9 +11,9 @@ This README is also available in a [user-friendly DocumentUp format](http://beer
11
11
 
12
12
  ## Rails & Ruby Versions Supported
13
13
 
14
- *Rails:* 3.0.x - 4.0.x
14
+ *Rails:* 3.2.x - 4.1.x
15
15
 
16
- *Ruby:* 1.8.7, 1.9.2, 1.9.3 and 2.0.0
16
+ *Ruby:* 1.9.2, 1.9.3, 2.0.0 and 2.1.0
17
17
 
18
18
  ## Installation
19
19
 
@@ -104,10 +104,12 @@ end
104
104
  NOTE: Alternatively, you may use an enum type if your database supports it. See
105
105
  [this issue](https://github.com/beerlington/classy_enum/issues/12) for more information.
106
106
 
107
- Then in my model I've added a line that calls `classy_enum_attr` with a single argument representing the enum I want to associate with my model. I am also delegating the `#send_email?` method to my Priority enum class.
107
+ Then in my model I've included `ClassyEnum::ActiveRecord` and added a line that calls `classy_enum_attr` with a single argument representing the enum I want to associate with my model. I am also delegating the `#send_email?` method to my Priority enum class.
108
108
 
109
109
  ```ruby
110
110
  class Alarm < ActiveRecord::Base
111
+ include ClassyEnum::ActiveRecord
112
+
111
113
  classy_enum_attr :priority
112
114
 
113
115
  delegate :send_email?, to: :priority
@@ -134,11 +136,13 @@ The enum field works like any other model attribute. It can be mass-assigned usi
134
136
 
135
137
  #### What if your enum class name is not the same as your model's attribute name?
136
138
 
137
- Just provide an optional `enum` or `class_name` argument to declare the attribute name. In this case, the model's attribute is called *alarm_priority*.
139
+ Just provide an optional `class_name` argument to declare the enum's class name. In this case, the model's attribute is called *alarm_priority*.
138
140
 
139
141
  ```ruby
140
142
  class Alarm < ActiveRecord::Base
141
- classy_enum_attr :alarm_priority, enum: 'Priority'
143
+ include ClassyEnum::ActiveRecord
144
+
145
+ classy_enum_attr :alarm_priority, class_name: 'Priority'
142
146
  end
143
147
 
144
148
  @alarm = Alarm.create(alarm_priority: :medium)
@@ -177,7 +181,7 @@ I18n.locale = :es
177
181
 
178
182
  ## Using Enum as a Collection
179
183
 
180
- ClassyEnum::Base extends the [Enumerable module](http://ruby-doc.org/core-1.9.3/Enumerable.html)
184
+ ClassyEnum::Base extends the [Enumerable module](http://ruby-doc.org/core-2.1.3/Enumerable.html)
181
185
  which provides several traversal and searching methods. This can
182
186
  be useful for situations where you are working with the collection,
183
187
  as opposed to the attributes on an Active Record object.
@@ -198,8 +202,7 @@ Priority.map { |p| p.to_s } # => ["low", "medium", "high"]
198
202
  Priority.find(&:send_email?) # => Priority::High.new
199
203
 
200
204
  # Find the priorities that are lower than Priority::High
201
- high_priority = Priority::High.new
202
- Priority.select {|p| p < high_priority } # => [Priority::Low.new, Priority::Medium.new]
205
+ Priority.select {|p| p < :high } # => [Priority::Low.new, Priority::Medium.new]
203
206
 
204
207
  # Iterate over each priority:
205
208
  Priority.each do |priority|
@@ -217,6 +220,8 @@ so:
217
220
 
218
221
  ```ruby
219
222
  class Alarm < ActiveRecord::Base
223
+ include ClassyEnum::ActiveRecord
224
+
220
225
  classy_enum_attr :priority, default: 'medium'
221
226
  end
222
227
 
@@ -229,6 +234,8 @@ runtime.
229
234
 
230
235
  ```ruby
231
236
  class Alarm < ActiveRecord::Base
237
+ include ClassyEnum::ActiveRecord
238
+
232
239
  classy_enum_attr :priority, default: ->(enum){ enum.max }
233
240
  end
234
241
 
@@ -287,26 +294,6 @@ In the above examples, high priority alarms are only emailed if the owning alarm
287
294
  @alarm.send_email? # => false
288
295
  ```
289
296
 
290
- ## Serializing as JSON
291
-
292
- By default, the enum will be serialized as a string representing the value:
293
-
294
- ```ruby
295
- @alarm = Alarm.create(priority: :high, enabled: true)
296
- @alarm.to_json.should == "{\"alarm\":{\"priority\":\"high\"}}"
297
- ```
298
-
299
- This behavior can be overridden by using the `serialize_as_json: true` option in your Active Record model:
300
-
301
- ```ruby
302
- class Alarm < ActiveRecord::Base
303
- classy_enum_attr :priority, serialize_as_json: true
304
- end
305
-
306
- @alarm = Alarm.create(priority: :high, enabled: true)
307
- @alarm.to_json.should == "{\"alarm\":{\"priority\":{}}}"
308
- ```
309
-
310
297
  ## Model Validation
311
298
 
312
299
  An Active Record validator `validates_inclusion_of :field, in: ENUM` is automatically added to your model when you use `classy_enum_attr`.
@@ -324,6 +311,8 @@ To allow nil or blank values, you can pass in `:allow_nil` and `:allow_blank` as
324
311
 
325
312
  ```ruby
326
313
  class Alarm < ActiveRecord::Base
314
+ include ClassyEnum::ActiveRecord
315
+
327
316
  classy_enum_attr :priority, allow_nil: true
328
317
  end
329
318
 
@@ -334,8 +323,7 @@ end
334
323
  ## Form Usage
335
324
 
336
325
  ClassyEnum includes a `select_options` helper method to generate an array of enum options
337
- that can be used by Rails' form builders such as SimpleForm and
338
- Formtastic.
326
+ that can be used by Rails' form builders such as SimpleForm and Formtastic.
339
327
 
340
328
  ```erb
341
329
  # SimpleForm
@@ -346,19 +334,6 @@ Formtastic.
346
334
  <% end %>
347
335
  ```
348
336
 
349
- ```erb
350
- # Formtastic
351
-
352
- <%= semantic_form_for @alarm do |f| %>
353
- <%= f.input :priority, as: :select, collection: Priority.select_options %>
354
- <%= f.button :submit %>
355
- <% end %>
356
- ```
357
-
358
- Built-in Formtastic support has been removed as of ClassyEnum 2.0. It is still
359
- available but needs to be enabled manually. To enable support visit
360
- [the wiki](https://github.com/beerlington/classy_enum/wiki/Formtastic-Support)
361
-
362
337
  ## Copyright
363
338
 
364
339
  Copyright (c) 2010-2014 [Peter Brown](https://github.com/beerlington). See LICENSE for details.
@@ -15,7 +15,7 @@ Gem::Specification.new do |gem|
15
15
  gem.require_paths = ["lib"]
16
16
  gem.version = ClassyEnum::VERSION
17
17
 
18
- gem.add_dependency('activerecord', '>= 3.0')
18
+ gem.add_dependency('activerecord', '>= 3.2')
19
19
 
20
20
  gem.add_development_dependency('rspec', '>= 2.11')
21
21
  gem.add_development_dependency('sqlite3', '>= 1.3')
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gem 'rails', '~> 4.1.0'
4
+ gem 'rspec-rails', '~> 2.11'
5
+ gem 'sqlite3'
6
+ gem 'json', '~> 1.7'
@@ -0,0 +1,6 @@
1
+ source :rubygems
2
+
3
+ gem 'rails', '~> 4.2.0.beta'
4
+ gem 'rspec-rails', '~> 2.11'
5
+ gem 'sqlite3'
6
+ gem 'json', '~> 1.7'
@@ -28,58 +28,82 @@ module ClassyEnum
28
28
  end
29
29
 
30
30
  module ActiveRecord
31
+ def self.included(klass)
32
+ klass.extend self
33
+ end
31
34
 
32
35
  # Class macro used to associate an enum with an attribute on an ActiveRecord model.
33
- # This method is automatically added to all ActiveRecord models when the classy_enum gem
34
- # is installed. Accepts an argument for the enum class to be associated with
36
+ # This method is added to an ActiveRecord model when ClassEnum::ActiveRecord
37
+ # is included. Accepts an argument for the enum class to be associated with
35
38
  # the model. ActiveRecord validation is automatically added to ensure
36
39
  # that a value is one of its pre-defined enum members.
37
40
  #
38
41
  # ==== Example
39
42
  # # Associate an enum Priority with Alarm model's priority attribute
40
43
  # class Alarm < ActiveRecord::Base
44
+ # include ClassyEnum::ActiveRecord
45
+ #
41
46
  # classy_enum_attr :priority
42
47
  # end
43
- #
48
+
44
49
  # # Associate an enum Priority with Alarm model's alarm_priority attribute
45
- # classy_enum_attr :alarm_priority, :enum => 'Priority'
50
+ # classy_enum_attr :alarm_priority, class_name: 'Priority'
46
51
  #
47
52
  # # Allow enum value to be nil
48
- # classy_enum_attr :priority, :allow_nil => true
53
+ # classy_enum_attr :priority, allow_nil: true
49
54
  #
50
55
  # # Allow enum value to be blank
51
- # classy_enum_attr :priority, :allow_blank => true
56
+ # classy_enum_attr :priority, allow_blank: true
52
57
  #
53
58
  # # Specifying a default enum value
54
- # classy_enum_attr :priority, :default => 'low'
59
+ # classy_enum_attr :priority, default: 'low'
55
60
  def classy_enum_attr(attribute, options={})
56
- enum = (options[:enum] || options[:class_name] || attribute).to_s.camelize.constantize
61
+ enum = (options[:class_name] || options[:enum] || attribute).to_s.camelize.constantize
57
62
  allow_blank = options[:allow_blank] || false
58
63
  allow_nil = options[:allow_nil] || false
59
- serialize_as_json = options[:serialize_as_json] || false
60
64
  default = ClassyEnum._normalize_default(options[:default], enum)
61
65
 
62
66
  # Add ActiveRecord validation to ensure it won't be saved unless it's an option
63
67
  validates_inclusion_of attribute,
64
- :in => enum,
65
- :allow_blank => allow_blank,
66
- :allow_nil => allow_nil
67
-
68
- # Define getter method that returns a ClassyEnum instance
69
- define_method attribute do
70
- enum.build(read_attribute(attribute),
71
- :owner => self,
72
- :serialize_as_json => serialize_as_json,
73
- :allow_blank => (allow_blank || allow_nil)
74
- )
75
- end
68
+ in: enum,
69
+ allow_blank: allow_blank,
70
+ allow_nil: allow_nil
71
+
72
+ # Use a module so that the reader methods can be overridden in classes and
73
+ # use super to get the enum value.
74
+ mod = Module.new do
75
+
76
+ # Define getter method that returns a ClassyEnum instance
77
+ define_method attribute do
78
+ enum.build(read_attribute(attribute), owner: self)
79
+ end
76
80
 
77
- # Define setter method that accepts string, symbol, instance or class for member
78
- define_method "#{attribute}=" do |value|
79
- value = ClassyEnum._normalize_value(value, default, (allow_nil || allow_blank))
80
- super(value)
81
+ # Define setter method that accepts string, symbol, instance or class for member
82
+ define_method "#{attribute}=" do |value|
83
+ value = ClassyEnum._normalize_value(value, default, (allow_nil || allow_blank))
84
+ super(value)
85
+ end
86
+
87
+ define_method :save_changed_attribute do |attr_name, arg|
88
+ if attribute.to_s == attr_name.to_s && !attribute_changed?(attr_name)
89
+ arg = enum.build(arg)
90
+ current_value = clone_attribute_value(:read_attribute, attr_name)
91
+
92
+ if arg != current_value
93
+ if respond_to?(:set_attribute_was, true)
94
+ set_attribute_was(attr_name, enum.build(arg, owner: self))
95
+ else
96
+ changed_attributes[attr_name] = enum.build(current_value, owner: self)
97
+ end
98
+ end
99
+ else
100
+ super(attr_name, arg)
101
+ end
102
+ end
81
103
  end
82
104
 
105
+ include mod
106
+
83
107
  # Initialize the object with the default value if it is present
84
108
  # because this will let you store the default value in the
85
109
  # database and make it searchable.
@@ -97,7 +121,3 @@ module ClassyEnum
97
121
 
98
122
  end
99
123
  end
100
-
101
- if defined?(ActiveRecord::Base)
102
- ActiveRecord::Base.send :extend, ClassyEnum::ActiveRecord
103
- end
@@ -8,7 +8,7 @@ module ClassyEnum
8
8
  include Translation
9
9
  include Collection
10
10
 
11
- attr_accessor :owner, :serialize_as_json, :allow_blank
11
+ attr_accessor :owner, :allow_blank
12
12
 
13
13
  def base_class
14
14
  self.class.base_class
@@ -24,8 +24,6 @@ module ClassyEnum
24
24
  end
25
25
 
26
26
  def inherited(klass)
27
- return if klass.anonymous?
28
-
29
27
  if self == ClassyEnum::Base
30
28
  klass.base_class = klass
31
29
  else
@@ -35,32 +33,6 @@ module ClassyEnum
35
33
  raise SubclassNameError, "subclass must be namespaced with #{base_class.name}::"
36
34
  end
37
35
 
38
- # Add visit_EnumMember methods to support validates_uniqueness_of with enum field
39
- # This is due to a bug in Rails where it uses the method result as opposed to the
40
- # database value for validation scopes. A fix will be released in Rails 4, but
41
- # this will remain until Rails 3.x is no longer prevalent.
42
- if defined?(Arel::Visitors::ToSql)
43
- visitor_method = "visit_#{klass.name.split('::').join('_')}"
44
-
45
- Arel::Visitors::ToSql.class_eval do
46
- define_method visitor_method, lambda {|*values|
47
- values[0] = values[0].to_s
48
- begin
49
- quoted(*values)
50
- rescue NoMethodError
51
- quote(*values)
52
- end
53
- }
54
- end
55
-
56
- Arel::Visitors::DepthFirst.class_eval do
57
- define_method visitor_method, lambda {|*values|
58
- values[0] = values[0].to_s
59
- terminal(*values)
60
- }
61
- end
62
- end
63
-
64
36
  # Convert from MyEnumClass::NumberTwo to :number_two
65
37
  enum = klass.name.split('::').last.underscore.to_sym
66
38
 
@@ -88,18 +60,12 @@ module ClassyEnum
88
60
  def build(value, options={})
89
61
  object = find(value)
90
62
 
91
- if object.nil? || (options[:allow_blank] && object.nil?)
92
- if value.blank?
93
- object = build_null_object(value)
94
- else
95
- return value
96
- end
63
+ if object.nil?
64
+ value
65
+ else
66
+ object.owner = options[:owner]
67
+ object
97
68
  end
98
-
99
- object.owner = options[:owner]
100
- object.serialize_as_json = options[:serialize_as_json]
101
- object.allow_blank = options[:allow_blank]
102
- object
103
69
  end
104
70
 
105
71
  # DSL setter method for overriding reference to enum owner (ActiveRecord model)
@@ -116,20 +82,8 @@ module ClassyEnum
116
82
  # end
117
83
  # end
118
84
  def owner(owner)
119
- define_method owner, lambda { @owner }
120
- end
121
-
122
- private
123
-
124
- # Subclass the base class and make it behave like the value that it is
125
- def build_null_object(value)
126
- Class.new(base_class) {
127
- @option = value
128
- @index = 0
129
- delegate :blank?, :nil?, :to => :option
130
- }.new
85
+ define_method owner, -> { @owner }
131
86
  end
132
87
  end
133
-
134
88
  end
135
89
  end
@@ -21,6 +21,8 @@ module ClassyEnum
21
21
  def <=> other
22
22
  if other.is_a?(Symbol) || other.is_a?(String)
23
23
  other = self.class.find(other)
24
+ elsif other.is_a?(Class)
25
+ other = other.new
24
26
  end
25
27
 
26
28
  index <=> other.index
@@ -58,11 +58,7 @@ module ClassyEnum
58
58
 
59
59
  # Overrides as_json to remove owner reference recursion issues
60
60
  def as_json(options=nil)
61
- return to_s unless serialize_as_json
62
- json = super(options)
63
- json.delete('owner')
64
- json.delete('serialize_as_json')
65
- json
61
+ to_s
66
62
  end
67
63
 
68
64
  private
@@ -4,7 +4,7 @@ module ClassyEnum
4
4
  # Define attribute methods like two?
5
5
  def self.define_predicate_method(klass, enum)
6
6
  klass.base_class.class_eval do
7
- define_method "#{enum}?", lambda { attribute?(enum) }
7
+ define_method "#{enum}?", -> { attribute?(enum) }
8
8
  end
9
9
  end
10
10
 
@@ -22,10 +22,12 @@ module ClassyEnum
22
22
  #
23
23
  # # Create an ActiveRecord class using the Breed enum
24
24
  # class Dog < ActiveRecord::Base
25
+ # include ClassyEnum::ActiveRecord
26
+ #
25
27
  # classy_enum_attr :breed
26
28
  # end
27
29
  #
28
- # @dog = Dog.new(:breed => :snoop)
30
+ # @dog = Dog.new(breed: :snoop)
29
31
  # @dog.breed.snoop? # => true
30
32
  # @dog.breed.golden_retriever? # => false
31
33
  def attribute?(attribute)
@@ -26,7 +26,7 @@ module ClassyEnum
26
26
  #
27
27
  # Priority::Low.new.text # => 'Bajo'
28
28
  def text
29
- I18n.translate to_s, :scope => i18n_scope, :default => to_s.titleize
29
+ I18n.translate to_s, scope: i18n_scope, default: to_s.titleize
30
30
  end
31
31
 
32
32
  private
@@ -1,3 +1,3 @@
1
1
  module ClassyEnum
2
- VERSION = "3.5.0"
2
+ VERSION = "4.0.0.beta1"
3
3
  end
@@ -1,8 +1,8 @@
1
1
  class ClassyEnumGenerator < Rails::Generators::NamedBase
2
2
  desc "Generate a ClassyEnum definition in app/enums/"
3
3
 
4
- argument :name, :type => :string, :required => true, :banner => 'EnumName'
5
- argument :values, :type => :array, :default => [], :banner => 'value1 value2 value3 etc...'
4
+ argument :name, type: :string, required: true, banner: 'EnumName'
5
+ argument :values, type: :array, default: [], banner: 'value1 value2 value3 etc...'
6
6
 
7
7
  source_root File.expand_path("../templates", __FILE__)
8
8
 
@@ -3,8 +3,8 @@ module Rspec
3
3
  class ClassyEnumGenerator < Rails::Generators::NamedBase
4
4
  desc "Generate a ClassyEnum spec in spec/enums/"
5
5
 
6
- argument :name, :type => :string, :required => true, :banner => 'EnumName'
7
- argument :values, :type => :array, :default => [], :banner => 'value1 value2 value3 etc...'
6
+ argument :name, type: :string, required: true, banner: 'EnumName'
7
+ argument :values, type: :array, default: [], banner: 'value1 value2 value3 etc...'
8
8
 
9
9
  source_root File.expand_path("../templates", __FILE__)
10
10
 
@@ -3,8 +3,8 @@ module TestUnit
3
3
  class ClassyEnumGenerator < Rails::Generators::NamedBase
4
4
  desc "Generate a ClassyEnum test in test/enums/"
5
5
 
6
- argument :name, :type => :string, :required => true, :banner => 'EnumName'
7
- argument :values, :type => :array, :default => [], :banner => 'value1 value2 value3 etc...'
6
+ argument :name, type: :string, required: true, banner: 'EnumName'
7
+ argument :values, type: :array, default: [], banner: 'value1 value2 value3 etc...'
8
8
 
9
9
  source_root File.expand_path("../templates", __FILE__)
10
10
 
@@ -1,7 +1,9 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
- ActiveRecord::Schema.define(:version => 1) do
4
- create_table :dogs, :force => true do |t|
3
+ ActiveRecord::Schema.define(version: 1) do
4
+ self.verbose = false
5
+
6
+ create_table :dogs, force: true do |t|
5
7
  t.string :breed
6
8
  t.string :other_breed
7
9
  t.string :color
@@ -9,7 +11,7 @@ ActiveRecord::Schema.define(:version => 1) do
9
11
  t.integer :age
10
12
  end
11
13
 
12
- create_table :cats, :force => true do |t|
14
+ create_table :cats, force: true do |t|
13
15
  t.string :breed
14
16
  t.string :other_breed
15
17
  t.string :another_breed
@@ -38,31 +40,33 @@ class CatBreed::Bengal < CatBreed; end
38
40
  class CatBreed::Birman < CatBreed; end
39
41
  class CatBreed::Persian < CatBreed; end
40
42
 
41
- class Dog < ActiveRecord::Base; end
43
+ class Dog < ActiveRecord::Base
44
+ include ClassyEnum::ActiveRecord
45
+ end
42
46
 
43
47
  class DefaultDog < Dog
44
48
  classy_enum_attr :breed
45
49
  end
46
50
 
47
51
  class AllowBlankBreedDog < Dog
48
- classy_enum_attr :breed, :allow_blank => true
52
+ classy_enum_attr :breed, allow_blank: true
49
53
  end
50
54
 
51
55
  class AllowNilBreedDog < Dog
52
- classy_enum_attr :breed, :allow_nil => true
56
+ classy_enum_attr :breed, allow_nil: true
53
57
  end
54
58
 
55
59
  class OtherDog < Dog
56
- classy_enum_attr :other_breed, :class_name => 'Breed'
60
+ classy_enum_attr :other_breed, class_name: 'Breed'
57
61
  end
58
62
 
59
63
  describe DefaultDog do
60
- specify { DefaultDog.new(:breed => nil).should_not be_valid }
61
- specify { DefaultDog.new(:breed => '').should_not be_valid }
64
+ specify { DefaultDog.new(breed: nil).should_not be_valid }
65
+ specify { DefaultDog.new(breed: '').should_not be_valid }
62
66
 
63
67
  [:golden_retriever, 'golden_retriever', Breed::GoldenRetriever.new, Breed::GoldenRetriever].each do |option|
64
68
  context "with a valid breed option" do
65
- subject { DefaultDog.new(:breed => option) }
69
+ subject { DefaultDog.new(breed: option) }
66
70
  it { should be_valid }
67
71
  its(:breed) { should be_a(Breed::GoldenRetriever) }
68
72
  its('breed.allow_blank') { should be_false }
@@ -75,8 +79,80 @@ describe DefaultDog do
75
79
  end
76
80
  end
77
81
 
82
+ if ::ActiveRecord::VERSION::MAJOR == 4 && ::ActiveRecord::VERSION::MINOR > 0
83
+ context "works with ActiveModel's attributes" do
84
+ subject { DefaultDog.create(breed: :golden_retriever) }
85
+ let(:old_breed) { Breed::GoldenRetriever.new }
86
+
87
+ it "sets changed_attributes to enum object" do
88
+ subject.breed = :snoop
89
+ subject.changed_attributes[:breed].should eq(old_breed)
90
+ end
91
+
92
+ it "sets changes to array" do
93
+ subject.breed = :snoop
94
+ subject.changes[:breed].should eq([old_breed, :snoop])
95
+ end
96
+
97
+ it "works with attribute_changed?" do
98
+ subject.breed = :snoop
99
+ subject.breed_was.should eq(old_breed)
100
+ subject.breed_changed?.should be_true
101
+
102
+ if subject.respond_to? :attribute_changed?
103
+ subject.attribute_changed?(:breed, to: Breed::Snoop.new).should be_true
104
+ subject.breed_changed?(
105
+ from: Breed::GoldenRetriever.new,
106
+ to: Breed::Snoop.new
107
+ ).should be_true
108
+ end
109
+ end
110
+
111
+ it "returns enum object for *_was" do
112
+ subject.breed = :snoop
113
+ subject.breed_was.golden_retriever?.should be_true
114
+ end
115
+
116
+ it "reverts changes" do
117
+ subject.breed = :snoop
118
+ subject.breed_changed?.should be_true
119
+ subject.breed = old_breed
120
+ subject.breed_changed?.should be_false
121
+ end
122
+
123
+ it "does not track the same value" do
124
+ subject.breed = :golden_retriever
125
+ subject.breed_changed?.should be_false
126
+ end
127
+
128
+ it "retains changes with multiple assignments" do
129
+ subject.breed = :snoop
130
+ subject.breed_changed?.should be_true
131
+ subject.breed = :husky
132
+ subject.breed_changed?.should be_true
133
+ end
134
+
135
+ it "allows tracks changes when nil is allowed" do
136
+ dog = AllowNilBreedDog.create(breed: :snoop)
137
+ dog.breed = nil
138
+ dog.save!
139
+ dog.breed = :snoop
140
+ dog.breed_changed?.should be_true
141
+ dog.breed = nil
142
+ dog.breed_changed?.should be_false
143
+ end
144
+
145
+ it "restores breed (Rails 4.2+)" do
146
+ if subject.respond_to?(:restore_breed)
147
+ subject.restore_breed!
148
+ subject.breed.should eq(:golden_retriever)
149
+ end
150
+ end
151
+ end
152
+ end
153
+
78
154
  context "with invalid breed options" do
79
- subject { DefaultDog.new(:breed => :fake_breed) }
155
+ subject { DefaultDog.new(breed: :fake_breed) }
80
156
  it { should_not be_valid }
81
157
  it 'has an error on :breed' do
82
158
  subject.valid?
@@ -86,17 +162,16 @@ describe DefaultDog do
86
162
  end
87
163
 
88
164
  describe "A ClassyEnum that allows blanks" do
89
- specify { AllowBlankBreedDog.new(:breed => nil).should be_valid }
90
- specify { AllowBlankBreedDog.new(:breed => '').should be_valid }
165
+ specify { AllowBlankBreedDog.new(breed: nil).should be_valid }
166
+ specify { AllowBlankBreedDog.new(breed: '').should be_valid }
91
167
 
92
168
  context "with valid breed options" do
93
- subject { AllowBlankBreedDog.new(:breed => :golden_retriever) }
169
+ subject { AllowBlankBreedDog.new(breed: :golden_retriever) }
94
170
  it { should be_valid }
95
- its('breed.allow_blank') { should be_true }
96
171
  end
97
172
 
98
173
  context "with invalid breed options" do
99
- subject { AllowBlankBreedDog.new(:breed => :fake_breed) }
174
+ subject { AllowBlankBreedDog.new(breed: :fake_breed) }
100
175
  it { should_not be_valid }
101
176
  it 'has an error on :breed' do
102
177
  subject.valid?
@@ -106,17 +181,16 @@ describe "A ClassyEnum that allows blanks" do
106
181
  end
107
182
 
108
183
  describe "A ClassyEnum that allows nils" do
109
- specify { AllowNilBreedDog.new(:breed => nil).should be_valid }
110
- specify { AllowNilBreedDog.new(:breed => '').should_not be_valid }
184
+ specify { AllowNilBreedDog.new(breed: nil).should be_valid }
185
+ specify { AllowNilBreedDog.new(breed: '').should_not be_valid }
111
186
 
112
187
  context "with valid breed options" do
113
- subject { AllowNilBreedDog.new(:breed => :golden_retriever) }
188
+ subject { AllowNilBreedDog.new(breed: :golden_retriever) }
114
189
  it { should be_valid }
115
- its('breed.allow_blank') { should be_true }
116
190
  end
117
191
 
118
192
  context "with invalid breed options" do
119
- subject { AllowNilBreedDog.new(:breed => :fake_breed) }
193
+ subject { AllowNilBreedDog.new(breed: :fake_breed) }
120
194
  it { should_not be_valid }
121
195
  it 'has an error on :breed' do
122
196
  subject.valid?
@@ -126,24 +200,24 @@ describe "A ClassyEnum that allows nils" do
126
200
  end
127
201
 
128
202
  describe "A ClassyEnum that has a different field name than the enum" do
129
- subject { OtherDog.new(:other_breed => :snoop) }
203
+ subject { OtherDog.new(other_breed: :snoop) }
130
204
  its(:other_breed) { should be_a(Breed::Snoop) }
131
205
  end
132
206
 
133
207
  class ActiveDog < Dog
134
208
  classy_enum_attr :color
135
- validates_uniqueness_of :name, :scope => :color
136
- scope :goldens, lambda { where(:breed => Breed.build('golden_retriever')) }
209
+ validates_uniqueness_of :name, scope: :color
210
+ scope :goldens, -> { where(breed: Breed.build('golden_retriever').to_s) }
137
211
  end
138
212
 
139
213
  describe ActiveDog do
140
214
  context 'uniqueness on name' do
141
- subject { ActiveDog.new(:name => 'Kitteh', :breed => :golden_retriever, :color => :black) }
215
+ subject { ActiveDog.new(name: 'Kitteh', breed: :golden_retriever, color: :black) }
142
216
  it { should be_valid }
143
217
 
144
218
  context 'with existing kitteh' do
145
219
  before do
146
- ActiveDog.create!(:name => 'Kitteh', :breed => :husky, :color => :black)
220
+ ActiveDog.create!(name: 'Kitteh', breed: :husky, color: :black)
147
221
  end
148
222
 
149
223
  it 'has an error on :name' do
@@ -154,8 +228,8 @@ describe ActiveDog do
154
228
  end
155
229
 
156
230
  context 'scopes' do
157
- let!(:golden) { ActiveDog.create!(:name => 'Sebastian', :breed => :golden_retriever, :color => :white) }
158
- let!(:husky) { ActiveDog.create!(:name => 'Sirius', :breed => :husky, :color => :black) }
231
+ let!(:golden) { ActiveDog.create!(name: 'Sebastian', breed: :golden_retriever, color: :white) }
232
+ let!(:husky) { ActiveDog.create!(name: 'Sirius', breed: :husky, color: :black) }
159
233
 
160
234
  after { ActiveDog.destroy_all }
161
235
 
@@ -176,7 +250,7 @@ describe ActiveDog do
176
250
  end
177
251
 
178
252
  class DefaultValueDog < Dog
179
- classy_enum_attr :breed, :default => :snoop
253
+ classy_enum_attr :breed, default: :snoop
180
254
  end
181
255
 
182
256
  describe DefaultValueDog do
@@ -184,7 +258,7 @@ describe DefaultValueDog do
184
258
  end
185
259
 
186
260
  class DynamicDefaultValueDog < Dog
187
- classy_enum_attr :breed, :default => lambda { |enum| enum.max }
261
+ classy_enum_attr :breed, default: ->(enum) { enum.max }
188
262
  end
189
263
 
190
264
  describe DynamicDefaultValueDog do
@@ -194,32 +268,35 @@ end
194
268
  describe Dog, 'with invalid default value' do
195
269
  it 'raises error with invalid default' do
196
270
  expect {
197
- Class.new(Dog) { classy_enum_attr :breed, :default => :nope }
271
+ Class.new(Dog) { classy_enum_attr :breed, default: :nope }
198
272
  }.to raise_error(ClassyEnum::InvalidDefault)
199
273
  end
200
274
  end
201
275
 
202
276
  class Cat < ActiveRecord::Base
277
+ include ClassyEnum::ActiveRecord
203
278
  end
204
279
 
205
280
  class DefaultCat < Cat
206
- classy_enum_attr :breed, :enum => 'CatBreed'
207
- classy_enum_attr :other_breed, :enum => 'CatBreed', :default => 'persian'
281
+ classy_enum_attr :breed, class_name: 'CatBreed'
282
+ classy_enum_attr :other_breed, class_name: 'CatBreed', default: 'persian'
208
283
  attr_accessor :color
209
- delegate :breed_color, :to => :breed
284
+ delegate :breed_color, to: :breed
210
285
  end
211
286
 
212
287
  class OtherCat < Cat
213
- classy_enum_attr :breed, :enum => 'CatBreed', :serialize_as_json => true
214
- classy_enum_attr :other_breed, :enum => 'CatBreed', :default => 'persian', :allow_nil => true
215
- classy_enum_attr :another_breed, :enum => 'CatBreed', :default => 'persian', :allow_blank => true
288
+ classy_enum_attr :breed, class_name: 'CatBreed'
289
+ classy_enum_attr :other_breed, class_name: 'CatBreed', default: 'persian', allow_nil: true
290
+
291
+ # Use enum option to ensure the tests are covering it somewhere
292
+ classy_enum_attr :another_breed, enum: 'CatBreed', default: 'persian', allow_blank: true
216
293
  attr_accessor :color
217
- delegate :breed_color, :to => :breed
294
+ delegate :breed_color, to: :breed
218
295
  end
219
296
 
220
297
  describe DefaultCat do
221
- let(:abyssian) { DefaultCat.new(:breed => :abyssian, :color => 'black') }
222
- let(:persian) { OtherCat.new(:breed => :persian, :color => 'white') }
298
+ let(:abyssian) { DefaultCat.new(breed: :abyssian, color: 'black') }
299
+ let(:persian) { OtherCat.new(breed: :persian, color: 'white') }
223
300
 
224
301
  it 'should delegate breed color to breed with an ownership reference' do
225
302
  abyssian.breed_color { should eql('black Abyssian') }
@@ -227,31 +304,31 @@ describe DefaultCat do
227
304
  end
228
305
 
229
306
  it 'persists the default, when set to nil' do
230
- cat = DefaultCat.create(:breed => :abyssian)
231
- expect(DefaultCat.where(:other_breed => 'persian')).to include(cat)
307
+ cat = DefaultCat.create(breed: :abyssian)
308
+ expect(DefaultCat.where(other_breed: 'persian')).to include(cat)
232
309
  end
233
310
 
234
311
  it 'uses the default if explictly set to nil and does not allow nil' do
235
- abyssian.update_attributes!(:other_breed => nil)
236
- DefaultCat.where(:other_breed => 'persian').should include(abyssian)
312
+ abyssian.update_attributes!(other_breed: nil)
313
+ DefaultCat.where(other_breed: 'persian').should include(abyssian)
237
314
  DefaultCat.last.other_breed.should == 'persian'
238
315
  end
239
316
 
240
317
  it 'uses the default if explictly set to blank and does not allow blank' do
241
- abyssian.update_attributes!(:other_breed => '')
242
- DefaultCat.where(:other_breed => 'persian').should include(abyssian)
318
+ abyssian.update_attributes!(other_breed: '')
319
+ DefaultCat.where(other_breed: 'persian').should include(abyssian)
243
320
  DefaultCat.last.other_breed.should == 'persian'
244
321
  end
245
322
 
246
323
  it 'allows nil even with a default' do
247
- persian.update_attributes!(:other_breed => nil)
248
- OtherCat.where(:other_breed => nil).count.should eql(1)
324
+ persian.update_attributes!(other_breed: nil)
325
+ OtherCat.where(other_breed: nil).count.should eql(1)
249
326
  OtherCat.last.other_breed.should be_nil
250
327
  end
251
328
 
252
329
  it 'allows blank even with a default' do
253
- persian.update_attributes!(:another_breed => '')
254
- OtherCat.where(:another_breed => '').count.should eql(1)
330
+ persian.update_attributes!(another_breed: '')
331
+ OtherCat.where(another_breed: '').count.should eql(1)
255
332
  OtherCat.last.another_breed.should be_blank
256
333
  OtherCat.last.another_breed.should_not be_nil
257
334
  end
@@ -29,16 +29,12 @@ describe ClassyEnum::Base do
29
29
 
30
30
  context 'nil' do
31
31
  subject { ClassyEnumBase.build(nil) }
32
- it { should be_a(ClassyEnumBase) }
33
- it { should be_nil }
34
- it { should be_blank }
32
+ it { should eq(nil) }
35
33
  end
36
34
 
37
35
  context 'empty string' do
38
36
  subject { ClassyEnumBase.build('') }
39
- it { should be_a(ClassyEnumBase) }
40
- it { should_not be_nil }
41
- it { should be_blank }
37
+ it { should eq('') }
42
38
  end
43
39
  end
44
40
 
@@ -50,7 +46,7 @@ describe ClassyEnum::Base do
50
46
 
51
47
  context 'Subclass naming' do
52
48
  it 'should raise an error when invalid' do
53
- lambda {
49
+ -> {
54
50
  class WrongSublcassName < ClassyEnumBase; end
55
51
  }.should raise_error(ClassyEnum::SubclassNameError)
56
52
  end
@@ -66,9 +62,3 @@ describe ClassyEnum::Base do
66
62
  end
67
63
  end
68
64
  end
69
-
70
- describe ClassyEnum::Base, 'Arel visitor' do
71
- specify do
72
- Arel::Visitors::ToSql.instance_methods.map(&:to_sym).should include(:'visit_ClassyEnumBase_One', :'visit_ClassyEnumBase_Two')
73
- end
74
- end
@@ -23,6 +23,7 @@ describe ClassyEnum::Collection do
23
23
  context '.map' do
24
24
  it 'should behave like an enumerable' do
25
25
  enum.map(&:to_s).should == %w(one two three)
26
+ enum.select {|e| e < :three }.should include(:one, :two)
26
27
  end
27
28
  end
28
29
 
@@ -34,6 +35,7 @@ describe ClassyEnum::Collection do
34
35
 
35
36
  context '#<=> (equality)' do
36
37
  its(:first) { should == ClassyEnumCollection::One.new }
38
+ its(:first) { should == ClassyEnumCollection::One }
37
39
  its(:first) { should == :one }
38
40
  its(:first) { should == 'one' }
39
41
  its(:first) { should_not == :two }
@@ -31,25 +31,7 @@ describe ClassyEnum::Conversion do
31
31
  end
32
32
 
33
33
  context '#as_json' do
34
- context 'serialize_as_json is false' do
35
- specify { ClassyEnumConversion::One.new.as_json.should == 'one' }
36
- specify { ClassyEnumConversion::Two.new.as_json.should == 'two' }
37
- end
38
-
39
- context 'serialize_as_json is true' do
40
- specify do
41
- enum = ClassyEnumConversion::One.new
42
- enum.serialize_as_json = true
43
- enum.instance_variable_set('@key', 'value')
44
- enum.as_json.should == {'key' => 'value' }
45
- end
46
-
47
- specify do
48
- enum = ClassyEnumConversion::One.new
49
- enum.serialize_as_json = true
50
- enum.instance_variable_set('@key', 'value')
51
- enum.as_json.should == {'key' => 'value' }
52
- end
53
- end
34
+ specify { ClassyEnumConversion::One.new.as_json.should == 'one' }
35
+ specify { ClassyEnumConversion::Two.new.as_json.should == 'two' }
54
36
  end
55
37
  end
@@ -13,8 +13,9 @@ describe ClassyEnum::Translation do
13
13
 
14
14
  before do
15
15
  I18n.reload!
16
- I18n.backend.store_translations :en, :classy_enum => {:classy_enum_translation => {:one => 'One!', :two => 'Two!' } }
17
- I18n.backend.store_translations :es, :classy_enum => {:classy_enum_translation => {:one => 'Uno', :two => 'Dos' } }
16
+ I18n.available_locales = ['en', 'es']
17
+ I18n.backend.store_translations :en, classy_enum: {classy_enum_translation: {one: 'One!', two: 'Two!' } }
18
+ I18n.backend.store_translations :es, classy_enum: {classy_enum_translation: {one: 'Uno', two: 'Dos' } }
18
19
  end
19
20
 
20
21
  context '#text' do
@@ -45,7 +45,7 @@ describe ClassyEnum do
45
45
  end
46
46
 
47
47
  it 'allows a proc' do
48
- value = lambda {|enum| enum.max }
48
+ value = ->(enum) { enum.max }
49
49
  default = ClassyEnum._normalize_default(value, enum)
50
50
  default.should == enum.max
51
51
  end
@@ -5,7 +5,9 @@ require 'rubygems'
5
5
  require 'active_record'
6
6
  require 'classy_enum'
7
7
 
8
- ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
8
+ I18n.enforce_available_locales = true
9
+
10
+ ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
9
11
 
10
12
  RSpec.configure do |config|
11
13
  config.color_enabled = true
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: classy_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.5.0
4
+ version: 4.0.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Brown
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-06-15 00:00:00.000000000 Z
11
+ date: 2014-12-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '3.0'
19
+ version: '3.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '3.0'
26
+ version: '3.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rspec
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -81,10 +81,10 @@ files:
81
81
  - README.md
82
82
  - Rakefile
83
83
  - classy_enum.gemspec
84
- - gemfiles/Gemfile.rails-3.0.x
85
- - gemfiles/Gemfile.rails-3.1.x
86
84
  - gemfiles/Gemfile.rails-3.2.x
87
85
  - gemfiles/Gemfile.rails-4.0.x
86
+ - gemfiles/Gemfile.rails-4.1.x
87
+ - gemfiles/Gemfile.rails-4.2.x
88
88
  - init.rb
89
89
  - lib/classy_enum.rb
90
90
  - lib/classy_enum/active_record.rb
@@ -124,9 +124,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
124
  version: '0'
125
125
  required_rubygems_version: !ruby/object:Gem::Requirement
126
126
  requirements:
127
- - - ">="
127
+ - - ">"
128
128
  - !ruby/object:Gem::Version
129
- version: '0'
129
+ version: 1.3.1
130
130
  requirements: []
131
131
  rubyforge_project:
132
132
  rubygems_version: 2.2.2
@@ -1,6 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'rails', '~> 3.0.0'
4
- gem 'rspec-rails', '~> 2.11.0'
5
- gem 'sqlite3-ruby', :require => 'sqlite3'
6
- gem 'json', '~> 1.6.5'
@@ -1,6 +0,0 @@
1
- source :rubygems
2
-
3
- gem 'rails', '~> 3.1.0'
4
- gem 'rspec-rails', '~> 2.11.0'
5
- gem 'sqlite3'
6
- gem 'json', '~> 1.6.5'