haz_enum 0.4.3 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +103 -1
- data/Rakefile +3 -2
- data/VERSION +1 -1
- data/haz_enum.gemspec +11 -8
- data/lib/haz_enum/enum.rb +4 -0
- data/lib/haz_enum/set.rb +6 -3
- data/lib/haz_enum.rb +5 -0
- data/spec/enum_spec.rb +11 -0
- data/spec/set_spec.rb +16 -0
- data/spec/spec_helper.rb +26 -1
- metadata +24 -11
data/README.rdoc
CHANGED
@@ -1,6 +1,108 @@
|
|
1
1
|
= haz_enum
|
2
2
|
|
3
|
-
|
3
|
+
haz_enum is a ActiveRecord extension to allow associations to enumerations.
|
4
|
+
|
5
|
+
== Installation
|
6
|
+
|
7
|
+
haz_enum is hostet on rubygems.org, so yoou can just do
|
8
|
+
|
9
|
+
gem install haz_enum
|
10
|
+
|
11
|
+
or if you use bundler, just add the following line to your Gemfile:
|
12
|
+
|
13
|
+
gem "haz_enum"
|
14
|
+
|
15
|
+
|
16
|
+
== Example with renum
|
17
|
+
|
18
|
+
renum is a perfect library for enumerations in ruby (see http://github.com/duelinmarkers/renum). Here is a simple renum definition:
|
19
|
+
|
20
|
+
enum :Roles do
|
21
|
+
Admin()
|
22
|
+
Supervisor()
|
23
|
+
ContentManager()
|
24
|
+
end
|
25
|
+
|
26
|
+
in your AR-model you can now write
|
27
|
+
|
28
|
+
class User < ActiveRecord
|
29
|
+
has_enum :role
|
30
|
+
end
|
31
|
+
|
32
|
+
what you need is a column in your db named <code>role</code> with type <code>string</code>.
|
33
|
+
|
34
|
+
user = User.create(:role => Roles::Admin)
|
35
|
+
user.has_role?(Roles::Admin) => true
|
36
|
+
user.has_role?(Roles::Supervisor) => false
|
37
|
+
|
38
|
+
The example above realizes one role per user. But what if you want to have multiple Roles per user? Just change <code>has_enum</code> to <code>has_set</code> and rename the column to <code>roles</code>:
|
39
|
+
|
40
|
+
class User < ActiveRecord
|
41
|
+
has_set :roles
|
42
|
+
end
|
43
|
+
|
44
|
+
user = User.create(:roles => Roles::Admin)
|
45
|
+
user.has_role?(Roles::Admin) => true
|
46
|
+
user.has_role?(Roles::Supervisor) => false
|
47
|
+
|
48
|
+
or
|
49
|
+
|
50
|
+
user = User.create(:roles => [Roles::Admin, Roles::Supervisor])
|
51
|
+
user.has_role?(Roles::Admin) => true
|
52
|
+
user.has_role?(Roles::Supervisor) => true
|
53
|
+
|
54
|
+
now <code>roles</code> behaves just like an array, so you can also do
|
55
|
+
|
56
|
+
user = User.create(:roles => Roles::Admin)
|
57
|
+
user.roles << Roles::Supervisor
|
58
|
+
user.has_role?(Roles::Admin) => true
|
59
|
+
user.has_role?(Roles::Supervisor) => true
|
60
|
+
|
61
|
+
== Using bitfields
|
62
|
+
|
63
|
+
If you have an enum with many possible values you can switch from :yml to field_type :bitfield.
|
64
|
+
|
65
|
+
class User < ActiveRecord
|
66
|
+
has_set :roles, :field_type => :bitfield
|
67
|
+
end
|
68
|
+
|
69
|
+
Your db-column has to be an integer for field_type bitfield. If you use mysql with int(11) you are able to have up to 64 different values in your enumeration.
|
70
|
+
|
71
|
+
== You do not need renum
|
72
|
+
|
73
|
+
...but it really makes sense to use this library. If you really do not want to use it you have to implement against an interface. Here is a simple ruby module example to get the same results as above for has_enum:
|
74
|
+
|
75
|
+
module Roles
|
76
|
+
class Admin; def self.name; "Admin"; end; end
|
77
|
+
class Supervisor; def self.name; "Supervisor"; end; end
|
78
|
+
class ContentManager; def self.name; "ContentManager"; end; end
|
79
|
+
end
|
80
|
+
|
81
|
+
You cannot use this for <code>has_set</code> and <code>field_type :yml</code> since you cannot dump anonymous classes. But you can use <code>field_type :bitfield</code>. Then your class could look something like that:
|
82
|
+
|
83
|
+
module Roles
|
84
|
+
class Admin
|
85
|
+
def self.bitfield_index; 1; end
|
86
|
+
end
|
87
|
+
class Supervisor
|
88
|
+
def self.bitfield_index; 2; end
|
89
|
+
end
|
90
|
+
class ContentManager
|
91
|
+
def self.bitfield_index; 3; end
|
92
|
+
end
|
93
|
+
class <<self
|
94
|
+
def values
|
95
|
+
Roles.constants.collect { |c| Roles.const_get(c) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
As you can see, your classes have to respond to <code>bitfield_index</code> and your wrapping module has to respond to values and return all available classes. So now you could do:
|
101
|
+
|
102
|
+
class User < ActiveRecord
|
103
|
+
has_enum :role, :field_type => :bitfield
|
104
|
+
end
|
105
|
+
|
4
106
|
|
5
107
|
== Note on Patches/Pull Requests
|
6
108
|
|
data/Rakefile
CHANGED
@@ -10,8 +10,9 @@ begin
|
|
10
10
|
gem.email = "andi@galaxycats.com"
|
11
11
|
gem.homepage = "http://github.com/galaxycats/haz_enum"
|
12
12
|
gem.authors = ["thyphoon"]
|
13
|
-
gem.add_dependency "activerecord", "
|
14
|
-
gem.add_development_dependency "rspec", "
|
13
|
+
gem.add_dependency "activerecord", "~> 3.0.0"
|
14
|
+
gem.add_development_dependency "rspec", "~> 1.3.0"
|
15
|
+
gem.add_development_dependency "renum", "~> 1.3.1"
|
15
16
|
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
16
17
|
end
|
17
18
|
Jeweler::GemcutterTasks.new
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/haz_enum.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{haz_enum}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.5.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["thyphoon"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-09-16}
|
13
13
|
s.description = %q{use has_set and has_enum in your ActiveRecord models if you want to have one (has_enum) value from a defined enumeration or more (has_set))}
|
14
14
|
s.email = %q{andi@galaxycats.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -49,15 +49,18 @@ Gem::Specification.new do |s|
|
|
49
49
|
s.specification_version = 3
|
50
50
|
|
51
51
|
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
52
|
-
s.add_runtime_dependency(%q<activerecord>, ["
|
53
|
-
s.add_development_dependency(%q<rspec>, ["
|
52
|
+
s.add_runtime_dependency(%q<activerecord>, ["~> 3.0.0"])
|
53
|
+
s.add_development_dependency(%q<rspec>, ["~> 1.3.0"])
|
54
|
+
s.add_development_dependency(%q<renum>, ["~> 1.3.1"])
|
54
55
|
else
|
55
|
-
s.add_dependency(%q<activerecord>, ["
|
56
|
-
s.add_dependency(%q<rspec>, ["
|
56
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
57
|
+
s.add_dependency(%q<rspec>, ["~> 1.3.0"])
|
58
|
+
s.add_dependency(%q<renum>, ["~> 1.3.1"])
|
57
59
|
end
|
58
60
|
else
|
59
|
-
s.add_dependency(%q<activerecord>, ["
|
60
|
-
s.add_dependency(%q<rspec>, ["
|
61
|
+
s.add_dependency(%q<activerecord>, ["~> 3.0.0"])
|
62
|
+
s.add_dependency(%q<rspec>, ["~> 1.3.0"])
|
63
|
+
s.add_dependency(%q<renum>, ["~> 1.3.1"])
|
61
64
|
end
|
62
65
|
end
|
63
66
|
|
data/lib/haz_enum/enum.rb
CHANGED
data/lib/haz_enum/set.rb
CHANGED
@@ -2,7 +2,7 @@ module HazEnum
|
|
2
2
|
module Set
|
3
3
|
def has_set(set_name, options={})
|
4
4
|
|
5
|
-
field_type = options.has_key?(:field_type) ? options[:field_type].to_s : "
|
5
|
+
field_type = options.has_key?(:field_type) ? options[:field_type].to_s : "yml"
|
6
6
|
set_column = options.has_key?(:column_name) ? options[:column_name].to_s : "#{set_name}_#{field_type}"
|
7
7
|
enum_class = options.has_key?(:class_name) ? options[:class_name].to_s.camelize.constantize : set_name.to_s.camelize.constantize
|
8
8
|
separator = options.has_key?(:separator) ? options[:separator].to_s : ", "
|
@@ -15,11 +15,14 @@ module HazEnum
|
|
15
15
|
end
|
16
16
|
|
17
17
|
define_method("#{set_name}=") do |value|
|
18
|
+
value = [value].flatten
|
18
19
|
value.collect! { |val| val.is_a?(String) ? val.constantize : val }.compact! if value.is_a?(Array)
|
19
20
|
value.instance_variable_set("@separator", separator)
|
20
21
|
class <<value
|
21
|
-
define_method :
|
22
|
-
self.
|
22
|
+
define_method :human do
|
23
|
+
self.collect do |enum|
|
24
|
+
enum.respond_to?(:model_name) ? enum.model_name.human : enum.name
|
25
|
+
end.join(@separator)
|
23
26
|
end
|
24
27
|
yield if block_given?
|
25
28
|
end
|
data/lib/haz_enum.rb
CHANGED
data/spec/enum_spec.rb
CHANGED
@@ -21,6 +21,12 @@ describe "HazEnum" do
|
|
21
21
|
ClassWithEnum.new(:product => "Silver").product.should be(Products::Silver)
|
22
22
|
end
|
23
23
|
|
24
|
+
it "should have has_<association>? method" do
|
25
|
+
class_with_enum = ClassWithEnum.new(:product => "Silver")
|
26
|
+
class_with_enum.has_product?(Products::Silver).should == true
|
27
|
+
class_with_enum.has_product?(Products::Gold).should == false
|
28
|
+
end
|
29
|
+
|
24
30
|
it "should not be able to set enum-attribute by colum-name via hash in initializer" do
|
25
31
|
ClassWithCustomNameEnum.new(:custom_name => Products::Silver).product.should_not be(Products::Silver)
|
26
32
|
ClassWithCustomNameEnum.new(:custom_name => Products::Silver.name).product.should_not be(Products::Silver)
|
@@ -59,6 +65,11 @@ describe "HazEnum" do
|
|
59
65
|
enum_mixin.errors[:product].size.should > 0
|
60
66
|
end
|
61
67
|
|
68
|
+
it "should work without renum (just ruby module with classes)" do
|
69
|
+
role_enum = ClassWithEnum.new(:module_role => ModuleRoles::Admin)
|
70
|
+
role_enum.has_module_role?(ModuleRoles::Admin).should == true
|
71
|
+
end
|
72
|
+
|
62
73
|
after(:all) do
|
63
74
|
teardown_db
|
64
75
|
end
|
data/spec/set_spec.rb
CHANGED
@@ -21,6 +21,12 @@ describe "HazEnum" do
|
|
21
21
|
ClassWithSet.new.roles.should == []
|
22
22
|
end
|
23
23
|
|
24
|
+
it "should have has_<association>? method" do
|
25
|
+
class_with_enum = ClassWithSet.new(:roles => Roles::Admin)
|
26
|
+
class_with_enum.has_role?(Roles::Admin).should == true
|
27
|
+
class_with_enum.has_role?(Roles::User).should == false
|
28
|
+
end
|
29
|
+
|
24
30
|
it "should be able to save values as yml" do
|
25
31
|
YmlSet.new(:roles => [Roles::User, Roles::Admin]).roles[1].should be(Roles::Admin)
|
26
32
|
yml_set = YmlSet.create(:roles => [Roles::User, Roles::Admin])
|
@@ -67,6 +73,16 @@ describe "HazEnum" do
|
|
67
73
|
extended.to_s.should == "Admin, Supervisor, User"
|
68
74
|
end
|
69
75
|
|
76
|
+
it "should be able to work without renum and bitfield" do
|
77
|
+
roles_set = ClassWithSet.new(:module_bitfield_roles => [ModuleBitfieldRoles::Admin, ModuleBitfieldRoles::Supervisor])
|
78
|
+
roles_set.has_module_bitfield_role?(ModuleBitfieldRoles::Admin).should == true
|
79
|
+
roles_set.has_module_bitfield_role?(ModuleBitfieldRoles::Supervisor).should == true
|
80
|
+
roles_set.save
|
81
|
+
roles_set.reload
|
82
|
+
roles_set.has_module_bitfield_role?(ModuleBitfieldRoles::Admin).should == true
|
83
|
+
roles_set.has_module_bitfield_role?(ModuleBitfieldRoles::Supervisor).should == true
|
84
|
+
end
|
85
|
+
|
70
86
|
after(:all) do
|
71
87
|
teardown_db
|
72
88
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -54,13 +54,36 @@ end
|
|
54
54
|
|
55
55
|
enum :Fakes, [:NOT_DEFINIED]
|
56
56
|
enum :Products, [:Silver, :Gold, :Titanium]
|
57
|
-
|
58
57
|
enum :Roles, [:Admin, :Supervisor, :User]
|
59
58
|
|
59
|
+
module ModuleRoles
|
60
|
+
class Admin; def self.name; "Admin"; end; end
|
61
|
+
class Supervisor; def self.name; "Supervisor"; end; end
|
62
|
+
class ContentManager; def self.name; "ContentManager"; end; end
|
63
|
+
end
|
64
|
+
|
65
|
+
module ModuleBitfieldRoles
|
66
|
+
class Admin
|
67
|
+
def self.bitfield_index; 1; end
|
68
|
+
end
|
69
|
+
class Supervisor
|
70
|
+
def self.bitfield_index; 2; end
|
71
|
+
end
|
72
|
+
class ContentManager
|
73
|
+
def self.bitfield_index; 3; end
|
74
|
+
end
|
75
|
+
class <<self
|
76
|
+
def values
|
77
|
+
ModuleBitfieldRoles.constants.collect { |c| ModuleBitfieldRoles.const_get(c) }
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
60
82
|
setup_db # Init the database for class creation
|
61
83
|
|
62
84
|
class ClassWithEnum < ActiveRecord::Base
|
63
85
|
has_enum :product
|
86
|
+
has_enum :module_role
|
64
87
|
end
|
65
88
|
|
66
89
|
class ClassWithCustomNameEnum < ActiveRecord::Base
|
@@ -74,6 +97,8 @@ class ClassWithSet < ActiveRecord::Base
|
|
74
97
|
extended_roles.collect(&:name).join(", ")
|
75
98
|
end
|
76
99
|
end
|
100
|
+
has_set :module_roles
|
101
|
+
has_set :module_bitfield_roles, :field_type => :bitfield
|
77
102
|
end
|
78
103
|
|
79
104
|
class YmlSet < ActiveRecord::Base
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
8
|
-
-
|
9
|
-
version: 0.
|
7
|
+
- 5
|
8
|
+
- 0
|
9
|
+
version: 0.5.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- thyphoon
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-09-16 00:00:00 +02:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -22,14 +22,13 @@ dependencies:
|
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ~>
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
segments:
|
28
28
|
- 3
|
29
29
|
- 0
|
30
30
|
- 0
|
31
|
-
|
32
|
-
version: 3.0.0.beta3
|
31
|
+
version: 3.0.0
|
33
32
|
type: :runtime
|
34
33
|
version_requirements: *id001
|
35
34
|
- !ruby/object:Gem::Dependency
|
@@ -37,15 +36,29 @@ dependencies:
|
|
37
36
|
prerelease: false
|
38
37
|
requirement: &id002 !ruby/object:Gem::Requirement
|
39
38
|
requirements:
|
40
|
-
- -
|
39
|
+
- - ~>
|
41
40
|
- !ruby/object:Gem::Version
|
42
41
|
segments:
|
43
42
|
- 1
|
44
|
-
-
|
45
|
-
-
|
46
|
-
version: 1.
|
43
|
+
- 3
|
44
|
+
- 0
|
45
|
+
version: 1.3.0
|
47
46
|
type: :development
|
48
47
|
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: renum
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 1
|
57
|
+
- 3
|
58
|
+
- 1
|
59
|
+
version: 1.3.1
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
49
62
|
description: use has_set and has_enum in your ActiveRecord models if you want to have one (has_enum) value from a defined enumeration or more (has_set))
|
50
63
|
email: andi@galaxycats.com
|
51
64
|
executables: []
|