haz_enum 0.4.3 → 0.5.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/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: []
|