classy_enum 3.1.3 → 3.2.0

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/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # ClassyEnum Changelog
2
2
 
3
+ ## 3.2.0
4
+
5
+ * Default values can now be specified within an ActiveRecord model
6
+
7
+ ```ruby
8
+ class Alarm < ActiveRecord::Base
9
+ classy_enum_attr :priority, :default => 'medium'
10
+ end
11
+
12
+ class Alarm < ActiveRecord::Base
13
+ classy_enum_attr :priority, :default => lambda {|enum| enum.last }
14
+ end
15
+ ```
16
+
17
+ * Adding ClassyEnum::Base#last. It's not part of the enumerable module
18
+ but it makes sense in this case.
19
+
20
+ ```ruby
21
+ Priority.last # => Priority::High
22
+ ```
23
+
3
24
  ## 3.1.3
4
25
 
5
26
  * Fixes saving and reloading ActiveRecord models that assign enum using
@@ -10,8 +31,10 @@
10
31
  * Allow enum property to be assigned using enum class. Previously it
11
32
  could only be assigned with an instance, string or symbol.
12
33
 
13
- @alarm.priority = Priority::Medium
14
- @alarm.priority.medium? # => true
34
+ ```ruby
35
+ @alarm.priority = Priority::Medium
36
+ @alarm.priority.medium? # => true
37
+ ```
15
38
 
16
39
  ## 3.1.1
17
40
 
@@ -33,8 +56,10 @@
33
56
  * Equality can now be determined using strings and symbols. The
34
57
  following will return true:
35
58
 
36
- Priority::Low.new == :low # => true
37
- Priority::Low.new == 'low' # => true
59
+ ```ruby
60
+ Priority::Low.new == :low # => true
61
+ Priority::Low.new == 'low' # => true
62
+ ```
38
63
 
39
64
  ## 3.0.0
40
65
 
@@ -62,9 +87,9 @@
62
87
 
63
88
  ## 2.1.0
64
89
 
65
- * Deprecating ClassyEnum::Base.enum_classes() (this is no longer needed)
66
- * Deprecating ClassyEnum::Base.valid_options()(use all.join(', ') instead)
67
- * Deprecating ClassEnum::Base.find() (use build() instead)
90
+ * Deprecating ClassyEnum::Base.enum_classes (this is no longer needed)
91
+ * Deprecating ClassyEnum::Base.valid_options (use all.join(', ') instead)
92
+ * Deprecating ClassEnum::Base.find (use build() instead)
68
93
 
69
94
  ## 2.0.3
70
95
 
data/README.md CHANGED
@@ -1,23 +1,26 @@
1
1
  # ClassyEnum
2
2
 
3
3
  [![Build Status](https://secure.travis-ci.org/beerlington/classy_enum.png?branch=master)](http://travis-ci.org/beerlington/classy_enum)
4
+ [![Gem Version](https://badge.fury.io/rb/classy_enum.png)](http://badge.fury.io/rb/classy_enum)
5
+ [![Code Climate](https://codeclimate.com/github/beerlington/classy_enum.png)](https://codeclimate.com/github/beerlington/classy_enum)
4
6
 
5
7
  ClassyEnum is a Ruby on Rails gem that adds class-based enumerator functionality to ActiveRecord attributes.
6
8
 
7
9
  ## README Topics
8
10
 
9
- * [Example Usage](https://github.com/beerlington/classy_enum#example-usage)
10
- * [Internationalization](https://github.com/beerlington/classy_enum#internationalization)
11
- * [Using Enum as a Collection](https://github.com/beerlington/classy_enum#using-enum-as-a-collection)
12
- * [Reference to Owning Object](https://github.com/beerlington/classy_enum#back-reference-to-owning-object)
13
- * [Serializing as JSON](https://github.com/beerlington/classy_enum#serializing-as-json)
14
- * [Special Cases](https://github.com/beerlington/classy_enum#special-cases)
15
- * [Built-in Model Validation](https://github.com/beerlington/classy_enum#model-validation)
16
- * [Formtastic Support](https://github.com/beerlington/classy_enum#formtastic-support)
11
+ * [Example Usage](#example-usage)
12
+ * [Internationalization](#internationalization)
13
+ * [Using Enum as a Collection](#using-enum-as-a-collection)
14
+ * [Default Enum Value](#default-enum-value)
15
+ * [Reference to Owning Object](#back-reference-to-owning-object)
16
+ * [Serializing as JSON](#serializing-as-json)
17
+ * [Special Cases](#special-cases)
18
+ * [Built-in Model Validation](#model-validation)
19
+ * [Formtastic Support](#formtastic-support)
17
20
 
18
21
  ## Rails & Ruby Versions Supported
19
22
 
20
- *Rails:* 3.0.x - 3.2.x
23
+ *Rails:* 3.0.x - 4.0.0.beta
21
24
 
22
25
  *Ruby:* 1.8.7, 1.9.2 and 1.9.3
23
26
 
@@ -187,6 +190,34 @@ Priority.each do |priority|
187
190
  end
188
191
  ```
189
192
 
193
+ ## Default Enum Value
194
+
195
+ As with any ActiveRecord attribute, default values can be specified in
196
+ the database table and will propagate to new instances. However, there
197
+ may be times when you can't or don't want to set the default value in
198
+ the database. For these occasions, a default value can be specified like
199
+ so:
200
+
201
+ ```ruby
202
+ class Alarm < ActiveRecord::Base
203
+ classy_enum_attr :priority, :default => 'medium'
204
+ end
205
+
206
+ Alarm.new.priority # => Priority::Medium
207
+ ```
208
+
209
+ You may also use a Proc object to set the default value. The enum class
210
+ is yielded to the block and can be used to determine the default at
211
+ runtime.
212
+
213
+ ```ruby
214
+ class Alarm < ActiveRecord::Base
215
+ classy_enum_attr :priority, :default => lambda {|enum| enum.max }
216
+ end
217
+
218
+ Alarm.new.priority # => Priority::High
219
+ ```
220
+
190
221
  ## Back reference to owning object
191
222
 
192
223
  In some cases you may want an enum class to reference the owning object
data/classy_enum.gemspec CHANGED
@@ -16,8 +16,8 @@ Gem::Specification.new do |gem|
16
16
 
17
17
  gem.add_dependency('rails', '>= 3.0')
18
18
 
19
- gem.add_development_dependency('rspec-rails', '~> 2.11.0')
20
- gem.add_development_dependency('sqlite3', '~> 1.3.6')
21
- gem.add_development_dependency('json', '~> 1.6.5')
19
+ gem.add_development_dependency('rspec-rails', '~> 2.11')
20
+ gem.add_development_dependency('sqlite3', '~> 1.3')
21
+ gem.add_development_dependency('json', '~> 1.6')
22
22
 
23
23
  end
@@ -1,4 +1,6 @@
1
1
  module ClassyEnum
2
+ class InvalidDefault < StandardError; end
3
+
2
4
  module ActiveRecord
3
5
 
4
6
  # Class macro used to associate an enum with an attribute on an ActiveRecord model.
@@ -21,11 +23,25 @@ module ClassyEnum
21
23
  #
22
24
  # # Allow enum value to be blank
23
25
  # classy_enum_attr :priority, :allow_blank => true
26
+ #
27
+ # # Specifying a default enum value
28
+ # classy_enum_attr :priority, :default => 'low'
24
29
  def classy_enum_attr(attribute, options={})
25
30
  enum = (options[:enum] || attribute).to_s.camelize.constantize
26
31
  allow_blank = options[:allow_blank] || false
27
32
  allow_nil = options[:allow_nil] || false
28
33
  serialize_as_json = options[:serialize_as_json] || false
34
+ default = options[:default]
35
+
36
+ if default.present?
37
+ if default.is_a? Proc
38
+ default = default.call(enum)
39
+ end
40
+
41
+ unless enum.include? default
42
+ raise InvalidDefault, "must be one of [#{enum.to_a.join(',')}]"
43
+ end
44
+ end
29
45
 
30
46
  # Add ActiveRecord validation to ensure it won't be saved unless it's an option
31
47
  validates_inclusion_of attribute,
@@ -35,7 +51,9 @@ module ClassyEnum
35
51
 
36
52
  # Define getter method that returns a ClassyEnum instance
37
53
  define_method attribute do
38
- enum.build(read_attribute(attribute),
54
+ value = read_attribute(attribute) || default
55
+
56
+ enum.build(value,
39
57
  :owner => self,
40
58
  :serialize_as_json => serialize_as_json,
41
59
  :allow_blank => (allow_blank || allow_nil)
@@ -64,6 +64,22 @@ module ClassyEnum
64
64
  enum_options.each {|e| yield e.new }
65
65
  end
66
66
 
67
+ # Returns the last enum instance in the collection
68
+ #
69
+ # ==== Example
70
+ # # Create an Enum with some elements
71
+ # class Priority < ClassyEnum::Base
72
+ # end
73
+ #
74
+ # class Priority::Low < Priority; end
75
+ # class Priority::Medium < Priority; end
76
+ # class Priority::High < Priority; end
77
+ #
78
+ # Priority.last # => Priority::High
79
+ def last
80
+ to_a.last
81
+ end
82
+
67
83
  # Finds an enum instance by symbol, string, or block.
68
84
  #
69
85
  # If a block is given, it passes each entry in enum to block, and returns
@@ -1,3 +1,3 @@
1
1
  module ClassyEnum
2
- VERSION = "3.1.3"
2
+ VERSION = "3.2.0"
3
3
  end
@@ -1,5 +1,19 @@
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|
5
+ t.string :breed
6
+ t.string :other_breed
7
+ t.string :color
8
+ t.string :name
9
+ t.integer :age
10
+ end
11
+
12
+ create_table :cats, :force => true do |t|
13
+ t.string :breed
14
+ end
15
+ end
16
+
3
17
  class Breed < ClassyEnum::Base; end
4
18
  class Breed::GoldenRetriever < Breed; end
5
19
  class Breed::Snoop < Breed; end
@@ -22,29 +36,31 @@ class CatBreed::Bengal < CatBreed; end
22
36
  class CatBreed::Birman < CatBreed; end
23
37
  class CatBreed::Persian < CatBreed; end
24
38
 
25
- class Dog < ActiveRecord::Base
39
+ class Dog < ActiveRecord::Base; end
40
+
41
+ class DefaultDog < Dog
26
42
  classy_enum_attr :breed
27
43
  end
28
44
 
29
- class AllowBlankBreedDog < ActiveRecord::Base
45
+ class AllowBlankBreedDog < Dog
30
46
  classy_enum_attr :breed, :allow_blank => true
31
47
  end
32
48
 
33
- class AllowNilBreedDog < ActiveRecord::Base
49
+ class AllowNilBreedDog < Dog
34
50
  classy_enum_attr :breed, :allow_nil => true
35
51
  end
36
52
 
37
- class OtherDog < ActiveRecord::Base
53
+ class OtherDog < Dog
38
54
  classy_enum_attr :other_breed, :enum => 'Breed'
39
55
  end
40
56
 
41
- describe Dog do
42
- specify { Dog.new(:breed => nil).should_not be_valid }
43
- specify { Dog.new(:breed => '').should_not be_valid }
57
+ describe DefaultDog do
58
+ specify { DefaultDog.new(:breed => nil).should_not be_valid }
59
+ specify { DefaultDog.new(:breed => '').should_not be_valid }
44
60
 
45
61
  context "with valid breed options" do
46
62
  [:golden_retriever, 'golden_retriever', Breed::GoldenRetriever.new, Breed::GoldenRetriever].each do |option|
47
- subject { Dog.new(:breed => option) }
63
+ subject { DefaultDog.new(:breed => option) }
48
64
  it { should be_valid }
49
65
  its(:breed) { should be_a(Breed::GoldenRetriever) }
50
66
  its('breed.allow_blank') { should be_false }
@@ -58,7 +74,7 @@ describe Dog do
58
74
  end
59
75
 
60
76
  context "with invalid breed options" do
61
- subject { Dog.new(:breed => :fake_breed) }
77
+ subject { DefaultDog.new(:breed => :fake_breed) }
62
78
  it { should_not be_valid }
63
79
  it { should have(1).error_on(:breed) }
64
80
  end
@@ -103,10 +119,10 @@ describe "A ClassyEnum that has a different field name than the enum" do
103
119
  its(:other_breed) { should be_a(Breed::Snoop) }
104
120
  end
105
121
 
106
- class ActiveDog < ActiveRecord::Base
122
+ class ActiveDog < Dog
107
123
  classy_enum_attr :color
108
124
  validates_uniqueness_of :name, :scope => :color
109
- scope :goldens, where(:breed => 'golden_retriever')
125
+ scope :goldens, lambda { where(:breed => 'golden_retriever') }
110
126
  end
111
127
 
112
128
  describe ActiveDog do
@@ -141,20 +157,47 @@ describe ActiveDog do
141
157
 
142
158
  end
143
159
 
160
+ class DefaultValueDog < Dog
161
+ classy_enum_attr :breed, :default => :snoop
162
+ end
163
+
164
+ describe DefaultValueDog do
165
+ its(:breed) { should == :snoop }
166
+ end
167
+
168
+ class DynamicDefaultValueDog < Dog
169
+ classy_enum_attr :breed, :default => lambda { |enum| enum.max }
170
+ end
171
+
172
+ describe DynamicDefaultValueDog do
173
+ its(:breed) { should == :husky }
174
+ end
175
+
176
+ describe Dog, 'with invalid default value' do
177
+ it 'raises error with invalid default' do
178
+ expect {
179
+ Class.new(Dog) { classy_enum_attr :breed, :default => :nope }
180
+ }.to raise_error(ClassyEnum::InvalidDefault)
181
+ end
182
+ end
183
+
144
184
  class Cat < ActiveRecord::Base
185
+ end
186
+
187
+ class DefaultCat < Cat
145
188
  classy_enum_attr :breed, :enum => 'CatBreed'
146
189
  attr_accessor :color
147
190
  delegate :breed_color, :to => :breed
148
191
  end
149
192
 
150
- class OtherCat < ActiveRecord::Base
193
+ class OtherCat < Cat
151
194
  classy_enum_attr :breed, :enum => 'CatBreed', :serialize_as_json => true
152
195
  attr_accessor :color
153
196
  delegate :breed_color, :to => :breed
154
197
  end
155
198
 
156
- describe Cat do
157
- let(:abyssian) { Cat.new(:breed => :abyssian, :color => 'black') }
199
+ describe DefaultCat do
200
+ let(:abyssian) { DefaultCat.new(:breed => :abyssian, :color => 'black') }
158
201
  let(:persian) { OtherCat.new(:breed => :persian, :color => 'white') }
159
202
 
160
203
  it 'should delegate breed color to breed with an ownership reference' do
@@ -26,6 +26,12 @@ describe ClassyEnum::Collection do
26
26
  end
27
27
  end
28
28
 
29
+ context '.last' do
30
+ its(:last) { should == ClassyEnumCollection::Three.new }
31
+ its(:last) { should == :three }
32
+ its(:last) { should_not == :one }
33
+ end
34
+
29
35
  context '#<=> (equality)' do
30
36
  its(:first) { should == ClassyEnumCollection::One.new }
31
37
  its(:first) { should == :one }
data/spec/spec_helper.rb CHANGED
@@ -13,36 +13,3 @@ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":me
13
13
  RSpec.configure do |config|
14
14
  config.color_enabled = true
15
15
  end
16
-
17
- ActiveRecord::Schema.define(:version => 1) do
18
- create_table :dogs, :force => true do |t|
19
- t.string :breed
20
- end
21
-
22
- create_table :other_dogs, :force => true do |t|
23
- t.string :other_breed
24
- end
25
-
26
- create_table :allow_blank_breed_dogs, :force => true do |t|
27
- t.string :breed
28
- end
29
-
30
- create_table :allow_nil_breed_dogs, :force => true do |t|
31
- t.string :breed
32
- end
33
-
34
- create_table :active_dogs, :force => true do |t|
35
- t.string :breed
36
- t.string :color
37
- t.string :name
38
- t.integer :age
39
- end
40
-
41
- create_table :cats, :force => true do |t|
42
- t.string :breed
43
- end
44
-
45
- create_table :other_cats, :force => true do |t|
46
- t.string :breed
47
- end
48
- end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: classy_enum
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.1.3
4
+ version: 3.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-01-13 00:00:00.000000000 Z
12
+ date: 2013-02-08 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 2.11.0
37
+ version: '2.11'
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 2.11.0
45
+ version: '2.11'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: sqlite3
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 1.3.6
53
+ version: '1.3'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 1.3.6
61
+ version: '1.3'
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: json
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: 1.6.5
69
+ version: '1.6'
70
70
  type: :development
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: 1.6.5
77
+ version: '1.6'
78
78
  description: A utility that adds class based enum functionality to ActiveRecord attributes
79
79
  email:
80
80
  - github@lette.us
@@ -126,7 +126,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
126
126
  version: '0'
127
127
  segments:
128
128
  - 0
129
- hash: -4175373577725624230
129
+ hash: 3178964087580650038
130
130
  required_rubygems_version: !ruby/object:Gem::Requirement
131
131
  none: false
132
132
  requirements:
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  version: '0'
136
136
  segments:
137
137
  - 0
138
- hash: -4175373577725624230
138
+ hash: 3178964087580650038
139
139
  requirements: []
140
140
  rubyforge_project:
141
141
  rubygems_version: 1.8.24