classy_enum 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -132,9 +132,9 @@ end
132
132
 
133
133
  h2. Model Validation
134
134
 
135
- An ActiveRecord validator @validates_inclusion_of :field, :in => ENUM.all, :allow_nil => true@ is automatically added to your model when you use @classy_enum_attr@.
135
+ An ActiveRecord validator @validates_inclusion_of :field, :in => ENUM.all@ is automatically added to your model when you use @classy_enum_attr@.
136
136
 
137
- If your enum only has members low, mediume, and high, then the following validation behavior would be expected:
137
+ If your enum only has members low, medium, and high, then the following validation behavior would be expected:
138
138
 
139
139
  <pre>
140
140
  @alarm = Alarm.new(:priority => :really_high)
@@ -143,6 +143,17 @@ If your enum only has members low, mediume, and high, then the following validat
143
143
  @alarm.valid? # => true
144
144
  </pre>
145
145
 
146
+ To allow nil or blank values, you can pass in :allow_nil and :allow_blank as options to classy_enum_attr, like so:
147
+
148
+ <pre>
149
+ class Alarm < ActiveRecord::Base
150
+ classy_enum_attr :priority, :allow_nil => true
151
+ end
152
+
153
+ @alarm = Alarm.new(:priority => nil)
154
+ @alarm.valid? # => true
155
+ </pre>
156
+
146
157
  h2. Working with ClassyEnum outside of ActiveRecord
147
158
 
148
159
  While ClassyEnum was designed to be used directly with ActiveRecord, it can also be used outside of it. Here are some examples based on the enum class defined earlier in this document.
@@ -173,6 +184,8 @@ Formtastic::SemanticFormHelper.builder = ClassyEnum::SemanticFormBuilder
173
184
 
174
185
  Then in your Formtastic view forms, use this syntax: @<%= f.input :priority, :as => :enum_select %>@
175
186
 
187
+ Note: ClassyEnum respects the @:allow_blank@ and @:allow_nil@ options and will include a blank select option in these cases
188
+
176
189
  h2. Copyright
177
190
 
178
191
  Copyright (c) 2011 Peter Brown. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.8.0
1
+ 0.8.1
data/classy_enum.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{classy_enum}
8
- s.version = "0.8.0"
8
+ s.version = "0.8.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Peter Brown"]
12
- s.date = %q{2011-03-24}
12
+ s.date = %q{2011-03-26}
13
13
  s.description = %q{A utility that adds class based enum functionality to ActiveRecord attributes}
14
14
  s.email = %q{github@lette.us}
15
15
  s.extra_rdoc_files = [
@@ -45,7 +45,7 @@ Gem::Specification.new do |s|
45
45
  s.homepage = %q{http://github.com/beerlington/classy_enum}
46
46
  s.rdoc_options = ["--charset=UTF-8"]
47
47
  s.require_paths = ["lib"]
48
- s.rubygems_version = %q{1.6.2}
48
+ s.rubygems_version = %q{1.6.1}
49
49
  s.summary = %q{A class based enumerator utility for Ruby on Rails}
50
50
  s.test_files = [
51
51
  "spec/classy_enum_attributes_spec.rb",
@@ -23,17 +23,16 @@ module ClassyEnum
23
23
 
24
24
  attribute = args[0]
25
25
  enum = options[:enum] || attribute
26
+ allow_blank = options[:allow_blank] || false
27
+ allow_nil = options[:allow_nil] || false
26
28
 
27
29
  klass = enum.to_s.camelize.constantize
28
30
 
29
31
  self.instance_eval do
30
32
 
31
- # Store the enum class so it can be retrieved by Formtastic input builder
32
- @classy_enums ||= {}
33
- @classy_enums[attribute] = klass
34
-
35
33
  # Add ActiveRecord validation to ensure it won't be saved unless it's an option
36
- validates_inclusion_of attribute, :in => klass.all, :message => "must be one of #{klass.valid_options}"
34
+ validates_inclusion_of attribute, :in => klass.all, :message => "must be one of #{klass.valid_options}",
35
+ :allow_blank => allow_blank, :allow_nil => allow_nil
37
36
 
38
37
  # Define getter method that returns a ClassyEnum instance
39
38
  define_method attribute do
@@ -42,7 +41,13 @@ module ClassyEnum
42
41
 
43
42
  # Define setter method that accepts either string or symbol for member
44
43
  define_method "#{attribute}=" do |value|
45
- super(value.to_s)
44
+ value = value.to_s unless value.nil?
45
+ super(value)
46
+ end
47
+
48
+ # Store the enum options so it can be later retrieved by Formtastic
49
+ define_method "#{attribute}_options" do
50
+ {:enum => enum, :allow_blank => allow_blank}
46
51
  end
47
52
 
48
53
  end
@@ -1,14 +1,14 @@
1
1
  module ClassyEnum
2
2
  class SemanticFormBuilder < Formtastic::SemanticFormBuilder # :nodoc: all
3
3
  def enum_select_input(method, options)
4
- enum_class = object.class.instance_variable_get(:@classy_enums)[method]
4
+ raise Error.invalid_classy_enum_object(method) unless object.respond_to? "#{method}_options"
5
5
 
6
- raise Error.invalid_classy_enum_object(method) if enum_class.nil?
6
+ enum_options = object.send("#{method}_options")
7
+ enum_class = enum_options[:enum].to_s.classify.constantize
7
8
 
8
9
  options[:collection] = enum_class.select_options
9
10
  options[:selected] = object.send(method).to_s
10
-
11
- options[:include_blank] = false
11
+ options[:include_blank] = enum_options[:allow_blank]
12
12
 
13
13
  select_input(method, options)
14
14
  end
@@ -12,6 +12,11 @@ describe "A Dog" do
12
12
  it "should be valid with a valid option" do
13
13
  @dog.should be_valid
14
14
  end
15
+
16
+ it "should have the right classy options for breed" do
17
+ options = {:enum => :breed, :allow_blank => false}
18
+ @dog.breed_options.should == options
19
+ end
15
20
  end
16
21
 
17
22
  it "should not be valid with a nil breed" do
@@ -37,6 +42,82 @@ describe "A Dog" do
37
42
 
38
43
  end
39
44
 
45
+ describe "A ClassyEnum that allows blanks" do
46
+
47
+ context "with valid breed options" do
48
+ before { @dog = AllowBlankBreedDog.new(:breed => :golden_retriever) }
49
+
50
+ it "should be valid with a valid option" do
51
+ @dog.should be_valid
52
+ end
53
+
54
+ it "should have the right classy options for breed" do
55
+ options = {:enum => :breed, :allow_blank => true}
56
+ @dog.breed_options.should == options
57
+ end
58
+ end
59
+
60
+ it "should be valid with a nil breed" do
61
+ AllowBlankBreedDog.new(:breed => nil).should be_valid
62
+ end
63
+
64
+ it "should be valid with a blank breed" do
65
+ AllowBlankBreedDog.new(:breed => "").should be_valid
66
+ end
67
+
68
+ context "with invalid breed options" do
69
+ before { @dog = AllowBlankBreedDog.new(:breed => :fake_breed) }
70
+
71
+ it "should not be valid with an invalid option" do
72
+ @dog.should_not be_valid
73
+ end
74
+
75
+ it "should have an error message containing the right options" do
76
+ @dog.valid?
77
+ @dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
78
+ end
79
+ end
80
+
81
+ end
82
+
83
+ describe "A ClassyEnum that allows nils" do
84
+
85
+ context "with valid breed options" do
86
+ before { @dog = AllowNilBreedDog.new(:breed => :golden_retriever) }
87
+
88
+ it "should be valid with a valid option" do
89
+ @dog.should be_valid
90
+ end
91
+
92
+ it "should have the right classy options for breed" do
93
+ options = {:enum => :breed, :allow_blank => false}
94
+ @dog.breed_options.should == options
95
+ end
96
+ end
97
+
98
+ it "should be valid with a nil breed" do
99
+ AllowNilBreedDog.new(:breed => nil).should be_valid
100
+ end
101
+
102
+ it "should not be valid with a blank breed" do
103
+ AllowNilBreedDog.new(:breed => "").should_not be_valid
104
+ end
105
+
106
+ context "with invalid breed options" do
107
+ before { @dog = AllowNilBreedDog.new(:breed => :fake_breed) }
108
+
109
+ it "should not be valid with an invalid option" do
110
+ @dog.should_not be_valid
111
+ end
112
+
113
+ it "should have an error message containing the right options" do
114
+ @dog.valid?
115
+ @dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
116
+ end
117
+ end
118
+
119
+ end
120
+
40
121
  describe "A ClassyEnum that has a different field name than the enum" do
41
122
  before { @dog = OtherDog.new(:other_breed => :snoop) }
42
123
 
@@ -5,86 +5,91 @@ describe 'using enum_select input' do
5
5
 
6
6
  Formtastic::SemanticFormHelper.builder = ClassyEnum::SemanticFormBuilder
7
7
 
8
- # Copied from how formtastic tests its form helpers
9
- before do
10
- @output_buffer = ""
11
- end
8
+ # Reset output buffer
9
+ before { @output_buffer = "" }
12
10
 
13
- context "when building a form with a classy_enum select" do
14
- context "with an object that has the enum set" do
15
- before(:each) do
16
- @output = semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
11
+ context 'when building a form with a classy_enum select' do
12
+ context 'with an object that has the enum set' do
13
+ let(:output) do
14
+ semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
17
15
  concat(builder.input(:breed, :as => :enum_select))
18
16
  end
19
17
  end
20
18
 
21
- it "should produce an unselected option tag for Golden Retriever" do
22
- regex = Regexp.new("<option value=\\\"golden_retriever\\\">Golden Retriever")
23
- @output.should =~ regex
19
+ it 'should produce an unselected option tag for Golden Retriever' do
20
+ output.should =~ Regexp.new(%q{option value="golden_retriever">Golden Retriever})
24
21
  end
25
22
 
26
- it "should produce a selected option tag for Snoop" do
27
- regex = Regexp.new("<option value=\\\"snoop\\\" selected=\\\"selected\\\">Snoop")
28
- @output.should =~ regex
23
+ it 'should produce a selected option tag for Snoop' do
24
+ output.should =~ Regexp.new(%q{<option value="snoop" selected="selected">Snoop})
29
25
  end
30
26
 
31
- it "should not produce a blank selected option tag" do
32
- regex = Regexp.new("<option value=\"\"><")
33
- @output.should_not =~ regex
27
+ it 'should not produce a blank option tag' do
28
+ output.should_not =~ Regexp.new(%q{<option value=""><})
34
29
  end
35
30
  end
36
31
 
37
- context "with an object that has a nil enum" do
38
- before(:each) do
39
- @output = semantic_form_for(Dog.new, :url => "/") do |builder|
32
+ context 'with an object that has a nil enum' do
33
+ let(:output) do
34
+ semantic_form_for(Dog.new, :url => "/") do |builder|
40
35
  concat(builder.input(:breed, :as => :enum_select))
41
36
  end
42
37
  end
43
38
 
44
- it "should produce an unselected option tag for Golden Retriever" do
45
- regex = Regexp.new("<option value=\\\"golden_retriever\\\">Golden Retriever")
46
- @output.should =~ regex
39
+ it 'should produce an unselected option tag for Golden Retriever' do
40
+ output.should =~ Regexp.new(%q{<option value="golden_retriever">Golden Retriever})
47
41
  end
48
42
 
49
- it "should not produce an selected option tag" do
50
- regex = Regexp.new("selected")
51
- @output.should_not =~ regex
43
+ it 'should not produce an selected option tag' do
44
+ output.should_not =~ Regexp.new("selected")
52
45
  end
53
-
54
46
  end
55
47
 
56
- context "with an object with a different attribute name which requires the enum_class" do
57
- before(:each) do
58
- @output = semantic_form_for(OtherDog.new, :url => "/") do |builder|
59
- concat(builder.input(:other_breed, :as => :enum_select))
48
+ context 'with an object that allows blank enums' do
49
+ let(:output) do
50
+ semantic_form_for(AllowBlankBreedDog.new, :url => "/") do |builder|
51
+ concat(builder.input(:breed, :as => :enum_select))
60
52
  end
61
53
  end
62
54
 
63
- it "should produce an unselected option tag for Golden Retriever" do
64
- regex = Regexp.new("<option value=\\\"golden_retriever\\\">Golden Retriever")
65
- @output.should =~ regex
55
+ it 'should produce an unselected option tag for Golden Retriever' do
56
+ output.should =~ Regexp.new(%q{<option value="golden_retriever">Golden Retriever})
66
57
  end
67
58
 
68
- it "should not produce an selected option tag" do
69
- regex = Regexp.new("selected")
70
- @output.should_not =~ regex
59
+ it 'should produce a blank option tag' do
60
+ output.should =~ Regexp.new(%q{<option value=""><})
71
61
  end
62
+ end
72
63
 
64
+ context 'with an object that allows nil enums' do
65
+ let(:output) do
66
+ semantic_form_for(AllowNilBreedDog.new, :url => "/") do |builder|
67
+ concat(builder.input(:breed, :as => :enum_select))
68
+ end
69
+ end
70
+
71
+ it 'should produce an unselected option tag for Golden Retriever' do
72
+ output.should =~ Regexp.new(%q{<option value="golden_retriever">Golden Retriever})
73
+ end
74
+
75
+ it 'should produce a blank option tag' do
76
+ output.should_not =~ Regexp.new(%q{<option value=""><})
77
+ end
73
78
  end
74
79
 
75
80
  end
76
81
 
77
- it "should raise an error if the attribute is not a ClassyEnum object" do
82
+ it 'should raise an error if the attribute is not a ClassyEnum object' do
78
83
  lambda do
79
- @output = semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
84
+ semantic_form_for(Dog.new(:breed => :snoop), :url => "/") do |builder|
80
85
  concat(builder.input(:id, :as => :enum_select))
81
86
  end
82
87
  end.should raise_error("id is not a ClassyEnum object. Make sure you've added 'classy_enum_attr :id' to your model")
83
88
  end
84
89
 
85
- it "should raise an error if the attribute is not a ClassyEnum object and its value is nil" do
90
+ it 'should raise an error if the attribute is not a ClassyEnum object and its value is nil' do
86
91
  lambda do
87
- @output = semantic_form_for(Dog.new, :url => "/") do |builder|
92
+ semantic_form_for(Dog.new, :url => "/") do |builder|
88
93
  concat(builder.input(:id, :as => :enum_select))
89
94
  end
90
95
  end.should raise_error("id is not a ClassyEnum object. Make sure you've added 'classy_enum_attr :id' to your model")
data/spec/spec_helper.rb CHANGED
@@ -12,6 +12,10 @@ require 'classy_enum'
12
12
 
13
13
  ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
14
14
 
15
+ RSpec.configure do |config|
16
+ config.color_enabled = true
17
+ end
18
+
15
19
  ActiveRecord::Schema.define(:version => 1) do
16
20
  create_table :dogs, :force => true do |t|
17
21
  t.string :breed
@@ -21,6 +25,13 @@ ActiveRecord::Schema.define(:version => 1) do
21
25
  t.string :other_breed
22
26
  end
23
27
 
28
+ create_table :allow_blank_breed_dogs, :force => true do |t|
29
+ t.string :breed
30
+ end
31
+
32
+ create_table :allow_nil_breed_dogs, :force => true do |t|
33
+ t.string :breed
34
+ end
24
35
  end
25
36
 
26
37
  class Breed < ClassyEnum::Base
@@ -31,6 +42,14 @@ class Dog < ActiveRecord::Base
31
42
  classy_enum_attr :breed
32
43
  end
33
44
 
45
+ class AllowBlankBreedDog < ActiveRecord::Base
46
+ classy_enum_attr :breed, :allow_blank => true
47
+ end
48
+
49
+ class AllowNilBreedDog < ActiveRecord::Base
50
+ classy_enum_attr :breed, :allow_nil => true
51
+ end
52
+
34
53
  class OtherDog < ActiveRecord::Base
35
54
  classy_enum_attr :other_breed, :enum => :breed
36
55
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: classy_enum
3
3
  version: !ruby/object:Gem::Version
4
- hash: 63
4
+ hash: 61
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 8
9
- - 0
10
- version: 0.8.0
9
+ - 1
10
+ version: 0.8.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Peter Brown
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-24 00:00:00 -04:00
18
+ date: 2011-03-26 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -156,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
156
  requirements: []
157
157
 
158
158
  rubyforge_project:
159
- rubygems_version: 1.6.2
159
+ rubygems_version: 1.6.1
160
160
  signing_key:
161
161
  specification_version: 3
162
162
  summary: A class based enumerator utility for Ruby on Rails