classy_enum 2.3.0 → 3.0.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/.gitignore +1 -0
- data/CHANGELOG.md +12 -0
- data/README.md +22 -58
- data/classy_enum.gemspec +1 -1
- data/gemfiles/Gemfile.rails-3.0.x +2 -4
- data/gemfiles/Gemfile.rails-3.1.x +2 -4
- data/gemfiles/Gemfile.rails-3.2.x +2 -4
- data/lib/classy_enum/active_record.rb +58 -0
- data/lib/classy_enum/base.rb +83 -3
- data/lib/classy_enum/collection.rb +76 -0
- data/lib/classy_enum/conversion.rb +69 -0
- data/lib/classy_enum/predicate.rb +35 -0
- data/lib/classy_enum/version.rb +1 -1
- data/lib/classy_enum.rb +5 -8
- data/lib/generators/classy_enum/templates/enum.rb +0 -1
- data/spec/classy_enum/active_record_spec.rb +156 -0
- data/spec/classy_enum/base_spec.rb +50 -0
- data/spec/classy_enum/collection_spec.rb +32 -0
- data/spec/classy_enum/conversion_spec.rb +55 -0
- data/spec/classy_enum/predicate_spec.rb +19 -0
- data/spec/classy_enum_inheritance_spec.rb +28 -0
- data/spec/spec_helper.rb +0 -29
- metadata +21 -16
- data/lib/classy_enum/attributes.rb +0 -72
- data/lib/classy_enum/class_methods.rb +0 -141
- data/lib/classy_enum/instance_methods.rb +0 -122
- data/spec/active_record_spec.rb +0 -70
- data/spec/classy_enum_attributes_spec.rb +0 -97
- data/spec/classy_enum_owner_reference_spec.rb +0 -53
- data/spec/classy_enum_spec.rb +0 -105
@@ -1,122 +0,0 @@
|
|
1
|
-
module ClassyEnum
|
2
|
-
module InstanceMethods
|
3
|
-
# Returns an integer representing the order that this element was defined in.
|
4
|
-
# Also used internally for sorting.
|
5
|
-
#
|
6
|
-
# ==== Example
|
7
|
-
# # Create an Enum with some elements
|
8
|
-
# class Priority < ClassyEnum::Base
|
9
|
-
# enum_classes :low, :medium, :high
|
10
|
-
# end
|
11
|
-
#
|
12
|
-
# @priority = PriorityMedium.new
|
13
|
-
# @priority.index # => 2
|
14
|
-
def index
|
15
|
-
self.class.instance_variable_get('@index')
|
16
|
-
end
|
17
|
-
|
18
|
-
alias :to_i :index
|
19
|
-
|
20
|
-
# Returns the name or string corresponding to element
|
21
|
-
#
|
22
|
-
# ==== Example
|
23
|
-
# # Create an Enum with some elements
|
24
|
-
# class Priority < ClassyEnum::Base
|
25
|
-
# enum_classes :low, :medium, :high
|
26
|
-
# end
|
27
|
-
#
|
28
|
-
# @priority = PriorityLow.new
|
29
|
-
# @priority.to_s # => 'low'
|
30
|
-
def to_s
|
31
|
-
self.class.instance_variable_get('@option').to_s
|
32
|
-
end
|
33
|
-
|
34
|
-
# Returns a Symbol corresponding to a string representation of element,
|
35
|
-
# creating the symbol if it did not previously exist
|
36
|
-
#
|
37
|
-
# ==== Example
|
38
|
-
# # Create an Enum with some elements
|
39
|
-
# class Priority < ClassyEnum::Base
|
40
|
-
# enum_classes :low, :medium, :high
|
41
|
-
# end
|
42
|
-
#
|
43
|
-
# @priority = PriorityLow.new
|
44
|
-
# @priority.to_sym # => :low
|
45
|
-
def to_sym
|
46
|
-
to_s.to_sym
|
47
|
-
end
|
48
|
-
|
49
|
-
# Returns string representing enum in Rails titleize format
|
50
|
-
#
|
51
|
-
# ==== Example
|
52
|
-
# # Create an Enum with some elements
|
53
|
-
# class Priority < ClassyEnum::Base
|
54
|
-
# enum_classes :low, :medium, :high, :really_high
|
55
|
-
# end
|
56
|
-
#
|
57
|
-
# @priority = Priority.build(:really_high)
|
58
|
-
# @priority.name # => "Really High"
|
59
|
-
def name
|
60
|
-
ActiveSupport::Deprecation.warn('name is deprecated, and will be removed in ClassyEnum 3.0. Replace calls with to_s.titleize.', caller)
|
61
|
-
to_s.titleize
|
62
|
-
end
|
63
|
-
|
64
|
-
# Sort an array of elements based on the order they are defined
|
65
|
-
#
|
66
|
-
# ==== Example
|
67
|
-
# # Create an Enum with some elements
|
68
|
-
# class Priority < ClassyEnum::Base
|
69
|
-
# enum_classes :low, :medium, :high
|
70
|
-
# end
|
71
|
-
#
|
72
|
-
# @low = Priority.build(:low)
|
73
|
-
# @medium = Priority.build(:medium)
|
74
|
-
# @high = Priority.build(:high)
|
75
|
-
# priorities = [@low, @high, @medium]
|
76
|
-
# priorities.sort # => [@low, @medium, @high]
|
77
|
-
# priorities.max # => @high
|
78
|
-
# priorities.min # => @low
|
79
|
-
def <=> other
|
80
|
-
index <=> other.index
|
81
|
-
end
|
82
|
-
|
83
|
-
# Overrides as_json to remove owner reference recursion issues
|
84
|
-
def as_json(options=nil)
|
85
|
-
return to_s unless serialize_as_json
|
86
|
-
json = super(options)
|
87
|
-
json.delete('owner')
|
88
|
-
json.delete('serialize_as_json')
|
89
|
-
json
|
90
|
-
end
|
91
|
-
|
92
|
-
protected
|
93
|
-
|
94
|
-
# Determine if the enum attribute is a particular member.
|
95
|
-
#
|
96
|
-
# ==== Example
|
97
|
-
# # Create an Enum with some elements
|
98
|
-
# class Breed < ClassyEnum::Base
|
99
|
-
# enum_classes :golden_retriever, :snoop
|
100
|
-
# end
|
101
|
-
#
|
102
|
-
# # Create an ActiveRecord class using the Breed enum
|
103
|
-
# class Dog < ActiveRecord::Base
|
104
|
-
# classy_enum_attr :breed
|
105
|
-
# end
|
106
|
-
#
|
107
|
-
# @dog = Dog.new(:breed => :snoop)
|
108
|
-
# @dog.breed.snoop? # => true
|
109
|
-
# @dog.breed.golden_retriever? # => false
|
110
|
-
def attribute?(attribute)
|
111
|
-
to_s == attribute
|
112
|
-
end
|
113
|
-
|
114
|
-
private
|
115
|
-
|
116
|
-
# Used by attribute methods
|
117
|
-
def attributes
|
118
|
-
[]
|
119
|
-
end
|
120
|
-
|
121
|
-
end
|
122
|
-
end
|
data/spec/active_record_spec.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
class Color < ClassyEnum::Base
|
4
|
-
enum_classes :white, :black
|
5
|
-
end
|
6
|
-
|
7
|
-
class ColorWhite < Color; end;
|
8
|
-
|
9
|
-
class ColorBlack < Color; end;
|
10
|
-
|
11
|
-
class ActiveDog < ActiveRecord::Base
|
12
|
-
classy_enum_attr :breed, :suffix => 'type'
|
13
|
-
classy_enum_attr :color
|
14
|
-
|
15
|
-
validates :name,
|
16
|
-
:presence => true,
|
17
|
-
:uniqueness => { :scope => [:breed] }
|
18
|
-
|
19
|
-
validates_uniqueness_of :name, :scope => :color
|
20
|
-
|
21
|
-
scope :goldens, where(:breed => 'golden_retriever')
|
22
|
-
|
23
|
-
end
|
24
|
-
|
25
|
-
describe ActiveDog do
|
26
|
-
|
27
|
-
context 'valid instance' do
|
28
|
-
subject { ActiveDog.new(:name => 'sirius', :breed => :golden_retriever, :color => :black) }
|
29
|
-
|
30
|
-
it { should have(:no).errors_on(:breed) }
|
31
|
-
its(:breed_type) { should be_a_golden_retriever }
|
32
|
-
its(:breed) { should == 'golden_retriever' }
|
33
|
-
end
|
34
|
-
|
35
|
-
context 'uniqueness on name' do
|
36
|
-
subject { ActiveDog.new(:name => 'Kitteh', :breed => :golden_retriever, :color => :black) }
|
37
|
-
it { should be_valid }
|
38
|
-
|
39
|
-
context 'with existing kitteh' do
|
40
|
-
before do
|
41
|
-
ActiveDog.create!(:name => 'Kitteh', :breed => :husky, :color => :black)
|
42
|
-
end
|
43
|
-
|
44
|
-
it { should have(1).error_on(:name) }
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
context 'invalid instance' do
|
49
|
-
subject { ActiveDog.new(:name => 'sirius', :breed => :golden_retrievers, :color => :white) }
|
50
|
-
|
51
|
-
it { should have(1).error_on(:breed) }
|
52
|
-
end
|
53
|
-
|
54
|
-
context 'scopes' do
|
55
|
-
let!(:golden) { ActiveDog.create!(:name => 'Sebastian', :breed => :golden_retriever, :color => :white) }
|
56
|
-
let!(:husky) { ActiveDog.create!(:name => 'Sirius', :breed => :husky, :color => :black) }
|
57
|
-
|
58
|
-
after { ActiveDog.destroy_all }
|
59
|
-
|
60
|
-
it 'should know all dogs' do
|
61
|
-
ActiveDog.all.should include(golden, husky)
|
62
|
-
end
|
63
|
-
|
64
|
-
it 'should have a working scope' do
|
65
|
-
ActiveDog.goldens.should include(golden)
|
66
|
-
ActiveDog.goldens.should_not include(husky)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
@@ -1,97 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
describe "A Dog" do
|
4
|
-
|
5
|
-
context "with valid breed options" do
|
6
|
-
subject { Dog.new(:breed => :golden_retriever) }
|
7
|
-
|
8
|
-
it { should be_valid }
|
9
|
-
its(:breed) { should be_a(BreedGoldenRetriever) }
|
10
|
-
its(:breed_options) { should eql({:enum => :breed, :allow_blank => false}) }
|
11
|
-
end
|
12
|
-
|
13
|
-
it "should not be valid with a nil breed" do
|
14
|
-
Dog.new(:breed => nil).should_not be_valid
|
15
|
-
end
|
16
|
-
|
17
|
-
it "should not be valid with a blank breed" do
|
18
|
-
Dog.new(:breed => "").should_not be_valid
|
19
|
-
end
|
20
|
-
|
21
|
-
context "with invalid breed options" do
|
22
|
-
let(:dog) { Dog.new(:breed => :fake_breed) }
|
23
|
-
subject { dog }
|
24
|
-
it { should_not be_valid }
|
25
|
-
|
26
|
-
it 'should have an error message containing the right options' do
|
27
|
-
dog.valid?
|
28
|
-
dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
end
|
33
|
-
|
34
|
-
describe "A ClassyEnum that allows blanks" do
|
35
|
-
|
36
|
-
context "with valid breed options" do
|
37
|
-
subject { AllowBlankBreedDog.new(:breed => :golden_retriever) }
|
38
|
-
|
39
|
-
it { should be_valid }
|
40
|
-
its(:breed_options) { should eql({:enum => :breed, :allow_blank => true}) }
|
41
|
-
end
|
42
|
-
|
43
|
-
it "should be valid with a nil breed" do
|
44
|
-
AllowBlankBreedDog.new(:breed => nil).should be_valid
|
45
|
-
end
|
46
|
-
|
47
|
-
it "should be valid with a blank breed" do
|
48
|
-
AllowBlankBreedDog.new(:breed => "").should be_valid
|
49
|
-
end
|
50
|
-
|
51
|
-
context "with invalid breed options" do
|
52
|
-
let(:dog) { AllowBlankBreedDog.new(:breed => :fake_breed) }
|
53
|
-
subject { dog }
|
54
|
-
it { should_not be_valid }
|
55
|
-
|
56
|
-
it 'should have an error message containing the right options' do
|
57
|
-
dog.valid?
|
58
|
-
dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
end
|
63
|
-
|
64
|
-
describe "A ClassyEnum that allows nils" do
|
65
|
-
|
66
|
-
context "with valid breed options" do
|
67
|
-
subject { AllowNilBreedDog.new(:breed => :golden_retriever) }
|
68
|
-
|
69
|
-
it { should be_valid }
|
70
|
-
its(:breed_options) { should eql({:enum => :breed, :allow_blank => false}) }
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should be valid with a nil breed" do
|
74
|
-
AllowNilBreedDog.new(:breed => nil).should be_valid
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should not be valid with a blank breed" do
|
78
|
-
AllowNilBreedDog.new(:breed => "").should_not be_valid
|
79
|
-
end
|
80
|
-
|
81
|
-
context "with invalid breed options" do
|
82
|
-
let(:dog) { AllowNilBreedDog.new(:breed => :fake_breed) }
|
83
|
-
subject { dog }
|
84
|
-
it { should_not be_valid }
|
85
|
-
|
86
|
-
it 'should have an error message containing the right options' do
|
87
|
-
dog.valid?
|
88
|
-
dog.errors[:breed].should include("must be one of #{Breed.all.map(&:to_sym).join(', ')}")
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
end
|
93
|
-
|
94
|
-
describe "A ClassyEnum that has a different field name than the enum" do
|
95
|
-
subject { OtherDog.new(:other_breed => :snoop) }
|
96
|
-
its(:other_breed) { should be_a(BreedSnoop) }
|
97
|
-
end
|
@@ -1,53 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
class CatBreed < ClassyEnum::Base
|
4
|
-
enum_classes :abyssian, :bengal, :birman, :persian
|
5
|
-
owner :cat
|
6
|
-
|
7
|
-
def breed_color
|
8
|
-
"#{cat.color} #{name}"
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
class CatBreedAbyssian < CatBreed
|
13
|
-
end
|
14
|
-
|
15
|
-
class CatBreedBengal < CatBreed
|
16
|
-
end
|
17
|
-
|
18
|
-
class CatBreedBirman < CatBreed
|
19
|
-
end
|
20
|
-
|
21
|
-
class CatBreedPersian < CatBreed
|
22
|
-
end
|
23
|
-
|
24
|
-
class Cat < ActiveRecord::Base
|
25
|
-
classy_enum_attr :breed, :enum => :cat_breed
|
26
|
-
attr_accessor :color
|
27
|
-
delegate :breed_color, :to => :breed
|
28
|
-
end
|
29
|
-
|
30
|
-
class OtherCat < ActiveRecord::Base
|
31
|
-
classy_enum_attr :breed, :enum => :cat_breed, :serialize_as_json => true
|
32
|
-
attr_accessor :color
|
33
|
-
delegate :breed_color, :to => :breed
|
34
|
-
end
|
35
|
-
|
36
|
-
describe Cat do
|
37
|
-
let(:abyssian) { Cat.new(:breed => :abyssian, :color => 'black') }
|
38
|
-
let(:persian) { OtherCat.new(:breed => :persian, :color => 'white') }
|
39
|
-
|
40
|
-
it 'should delegate breed color to breed with an ownership reference' do
|
41
|
-
abyssian.breed_color { should eql('black Abyssian') }
|
42
|
-
persian.breed_color { should eql('white Persian') }
|
43
|
-
end
|
44
|
-
|
45
|
-
it 'should correctly serialize without the owner reference' do
|
46
|
-
JSON.parse(abyssian.to_json)['cat']['breed'].should == 'abyssian'
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'should convert the enum to a string when serializing' do
|
50
|
-
JSON.parse(persian.to_json)['other_cat']['breed'].should be_a(Hash)
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|
data/spec/classy_enum_spec.rb
DELETED
@@ -1,105 +0,0 @@
|
|
1
|
-
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
-
|
3
|
-
class TestEnum < ClassyEnum::Base
|
4
|
-
enum_classes :one, :two, :three
|
5
|
-
|
6
|
-
def self.test_class_method?
|
7
|
-
false
|
8
|
-
end
|
9
|
-
|
10
|
-
def test_instance_method?
|
11
|
-
false
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
class TestEnumOne < TestEnum
|
16
|
-
end
|
17
|
-
|
18
|
-
class TestEnumTwo < TestEnum
|
19
|
-
def self.test_class_method?
|
20
|
-
true
|
21
|
-
end
|
22
|
-
|
23
|
-
def test_instance_method?
|
24
|
-
true
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
class TestEnumThree < TestEnum
|
29
|
-
end
|
30
|
-
|
31
|
-
describe "A ClassyEnum Descendent" do
|
32
|
-
|
33
|
-
it "should return an array of enums" do
|
34
|
-
TestEnum.all.map(&:class).should == [TestEnumOne, TestEnumTwo, TestEnumThree]
|
35
|
-
end
|
36
|
-
|
37
|
-
it "should return an array of enums for a select tag" do
|
38
|
-
TestEnum.select_options.should == TestEnum.enum_options.map {|o| [TestEnum.build(o).name, TestEnum.build(o).to_s] }
|
39
|
-
end
|
40
|
-
|
41
|
-
it "should return a type error when adding an invalid option" do
|
42
|
-
TestEnum.build(:invalid_option).class.should == TypeError
|
43
|
-
end
|
44
|
-
|
45
|
-
it "should find an enum by symbol" do
|
46
|
-
TestEnum.find(:one).class.should == TestEnumOne
|
47
|
-
end
|
48
|
-
|
49
|
-
it "should find an enum by string" do
|
50
|
-
TestEnum.find("one").class.should == TestEnumOne
|
51
|
-
end
|
52
|
-
|
53
|
-
it "should create an instance with a string" do
|
54
|
-
TestEnum.build("one").should be_a(TestEnumOne)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
describe "A collection of ClassyEnums" do
|
59
|
-
let(:one) { TestEnum.build(:one) }
|
60
|
-
let(:two) { TestEnum.build(:two) }
|
61
|
-
let(:three) { TestEnum.build(:three) }
|
62
|
-
|
63
|
-
subject { [one, three, two] }
|
64
|
-
its(:sort) { should eql([one, two, three]) }
|
65
|
-
its(:max) { should eql(three) }
|
66
|
-
end
|
67
|
-
|
68
|
-
describe "A ClassyEnum element" do
|
69
|
-
it "should instantiate a member" do
|
70
|
-
TestEnumOne.new.should be_a(TestEnumOne)
|
71
|
-
end
|
72
|
-
|
73
|
-
it "should inherit the default class methods" do
|
74
|
-
TestEnumOne.test_class_method?.should be_false
|
75
|
-
end
|
76
|
-
|
77
|
-
it "should compare different elements based on their index" do
|
78
|
-
TestEnumOne.new.should == TestEnumOne.new
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
describe "A ClassyEnum instance" do
|
83
|
-
subject { TestEnum.build(:one) }
|
84
|
-
|
85
|
-
it { should be_a(TestEnum) }
|
86
|
-
its(:class) { should eql(TestEnumOne) }
|
87
|
-
its(:one?) { should be_true }
|
88
|
-
its(:two?) { should be_false }
|
89
|
-
its(:index) { should eql(1) }
|
90
|
-
its(:to_i) { should eql(1) }
|
91
|
-
its(:to_s) { should eql('one') }
|
92
|
-
its(:to_sym) { should be(:one) }
|
93
|
-
its(:name) { should eql('One') }
|
94
|
-
its(:test_instance_method?) { should be_false }
|
95
|
-
end
|
96
|
-
|
97
|
-
describe "A ClassyEnum that overrides values" do
|
98
|
-
subject { TestEnum.build(:two) }
|
99
|
-
|
100
|
-
its(:test_instance_method?) { should be_true }
|
101
|
-
|
102
|
-
it "should override the default class methods" do
|
103
|
-
TestEnumTwo.test_class_method?.should be_true
|
104
|
-
end
|
105
|
-
end
|