classy_enum 3.1.3 → 3.2.0

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