degu 0.0.5 → 0.1.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/Rakefile +1 -0
- data/VERSION +1 -1
- data/degu.gemspec +5 -2
- data/lib/degu/has_set.rb +54 -67
- data/lib/degu/renum/enumerated_value.rb +20 -0
- data/lib/degu/version.rb +1 -1
- data/test/has_set_test.rb +13 -3
- metadata +20 -6
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0
|
1
|
+
0.1.0
|
data/degu.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "degu"
|
5
|
-
s.version = "0.0
|
5
|
+
s.version = "0.1.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Florian Frank"]
|
9
|
-
s.date = "2011-12-
|
9
|
+
s.date = "2011-12-15"
|
10
10
|
s.description = "Library that includes enums, and rails support for enums and bitfield sets."
|
11
11
|
s.email = "dev@pkw.de"
|
12
12
|
s.extra_rdoc_files = ["README.rdoc", "lib/degu/has_enum.rb", "lib/degu/has_set.rb", "lib/degu/polite.rb", "lib/degu/renum/enumerated_value.rb", "lib/degu/renum/enumerated_value_type_factory.rb", "lib/degu/renum.rb", "lib/degu/rude.rb", "lib/degu/version.rb", "lib/degu.rb"]
|
@@ -27,6 +27,7 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency(%q<sqlite3>, [">= 0"])
|
28
28
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
29
29
|
s.add_development_dependency(%q<ruby-debug>, [">= 0"])
|
30
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
30
31
|
s.add_runtime_dependency(%q<activerecord>, ["~> 3.0"])
|
31
32
|
else
|
32
33
|
s.add_dependency(%q<gem_hadar>, ["~> 0.1.3"])
|
@@ -34,6 +35,7 @@ Gem::Specification.new do |s|
|
|
34
35
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
35
36
|
s.add_dependency(%q<rspec>, [">= 0"])
|
36
37
|
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
38
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
37
39
|
s.add_dependency(%q<activerecord>, ["~> 3.0"])
|
38
40
|
end
|
39
41
|
else
|
@@ -42,6 +44,7 @@ Gem::Specification.new do |s|
|
|
42
44
|
s.add_dependency(%q<sqlite3>, [">= 0"])
|
43
45
|
s.add_dependency(%q<rspec>, [">= 0"])
|
44
46
|
s.add_dependency(%q<ruby-debug>, [">= 0"])
|
47
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
45
48
|
s.add_dependency(%q<activerecord>, ["~> 3.0"])
|
46
49
|
end
|
47
50
|
end
|
data/lib/degu/has_set.rb
CHANGED
@@ -5,7 +5,7 @@ require 'active_support'
|
|
5
5
|
require 'active_record'
|
6
6
|
module Degu
|
7
7
|
module HasSet
|
8
|
-
|
8
|
+
extend ActiveSupport::Concern
|
9
9
|
|
10
10
|
module ClassMethods
|
11
11
|
# Use like this:
|
@@ -14,105 +14,92 @@ module Degu
|
|
14
14
|
# has_set :interests
|
15
15
|
# end
|
16
16
|
def has_set(set_name, options = {})
|
17
|
-
|
17
|
+
set_name_singular = set_name.to_s.singularize
|
18
18
|
set_column = options.has_key?(:column_name) ? options[:column_name].to_s : "#{set_name}_bitfield"
|
19
19
|
|
20
20
|
begin
|
21
|
-
enum_class = options
|
21
|
+
enum_class = options[:class_name] || options[:enum_class] || set_name.to_s.camelcase.constantize
|
22
22
|
rescue NameError => ne
|
23
23
|
raise NameError, "There ist no class to take the set entries from (#{ne.message})."
|
24
24
|
end
|
25
25
|
|
26
|
-
# Extend enum_class with field_name method
|
27
|
-
enum_class.class_eval <<-EOF
|
28
|
-
def field_name
|
29
|
-
'#{set_name.to_s.singularize}_' + self.name.underscore
|
30
|
-
end
|
31
|
-
EOF
|
32
|
-
|
33
26
|
define_method("#{set_name}=") do |argument_value|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
argument_value.split(',').map(&:strip)
|
40
|
-
else
|
41
|
-
Array(argument_value)
|
42
|
-
end.map do |set_element|
|
43
|
-
if result = enum_class[set_element]
|
44
|
-
result
|
45
|
-
else
|
46
|
-
invalid_set_elements << set_element
|
47
|
-
nil
|
48
|
-
end
|
49
|
-
end
|
50
|
-
if set_elements.any? { |set_element| set_element.nil? }
|
51
|
-
raise ArgumentError, "element #{argument_value.inspect} contains invalid elements: #{invalid_set_elements.inspect}"
|
52
|
-
end
|
53
|
-
value = 0
|
54
|
-
set_elements.each do |set_element|
|
55
|
-
mask = 1 << set_element.bitfield_index
|
56
|
-
if mask & value == mask
|
57
|
-
next
|
58
|
-
else
|
59
|
-
value |= mask
|
60
|
-
end
|
61
|
-
end
|
62
|
-
value
|
27
|
+
value = nil
|
28
|
+
unless argument_value.nil?
|
29
|
+
value = 0
|
30
|
+
has_set_coerce_argument_value(enum_class, argument_value).each do |set_element|
|
31
|
+
value |= 1 << set_element.bitfield_index
|
63
32
|
end
|
33
|
+
end
|
34
|
+
write_attribute set_column, value
|
64
35
|
end
|
65
36
|
|
66
37
|
define_method(set_name) do
|
67
|
-
value =
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
end
|
77
|
-
# special to_s method for element-array
|
78
|
-
class << set_elements
|
79
|
-
def to_s
|
80
|
-
map(&:name) * ', '
|
81
|
-
end
|
38
|
+
value = read_attribute(set_column) or return
|
39
|
+
set_elements = enum_class.select do |enum_element|
|
40
|
+
mask = 1 << enum_element.bitfield_index
|
41
|
+
value & mask == mask
|
42
|
+
end
|
43
|
+
# special to_s method for element-array
|
44
|
+
class << set_elements
|
45
|
+
def to_s
|
46
|
+
map(&:underscored_name) * ','
|
82
47
|
end
|
83
|
-
set_elements
|
84
48
|
end
|
49
|
+
set_elements
|
85
50
|
end
|
86
51
|
|
87
|
-
|
52
|
+
class << self; self; end.instance_eval do
|
53
|
+
define_method("available_#{set_name}") do
|
54
|
+
enum_class.underscored_names.map { |name| "#{set_name_singular}_#{name}" }
|
55
|
+
end
|
56
|
+
end
|
88
57
|
define_method("available_#{set_name}") do
|
89
|
-
|
58
|
+
enum_class.underscored_names.map { |name| "#{set_name_singular}_#{name}" }
|
90
59
|
end
|
91
60
|
|
92
|
-
enum_class.
|
93
|
-
define_method("#{
|
61
|
+
enum_class.each do |enum|
|
62
|
+
define_method("#{set_name_singular}_#{enum.underscored_name}?") do
|
94
63
|
mask = 1 << enum.bitfield_index
|
95
|
-
|
64
|
+
read_attribute(set_column) & mask == mask
|
96
65
|
end
|
97
66
|
|
98
|
-
alias_method :"#{
|
67
|
+
alias_method :"#{set_name_singular}_#{enum.underscored_name}", :"#{set_name_singular}_#{enum.underscored_name}?"
|
99
68
|
|
100
|
-
define_method("#{
|
69
|
+
define_method("#{set_name_singular}_#{enum.underscored_name}=") do |true_or_false|
|
101
70
|
mask = 1 << enum.bitfield_index
|
102
|
-
|
71
|
+
total_value = read_attribute(set_column)
|
72
|
+
current_value = mask & total_value == mask
|
103
73
|
true_or_false = true if true_or_false.to_s == "true" || true_or_false.respond_to?(:to_i) && true_or_false.to_i == 1
|
104
74
|
true_or_false = false if true_or_false.to_s == "false" || true_or_false.respond_to?(:to_i) && true_or_false.to_i == 0
|
105
|
-
|
106
75
|
if current_value != true_or_false
|
107
|
-
true_or_false ?
|
76
|
+
write_attribute set_column, true_or_false ? total_value | mask : total_value & ~mask
|
108
77
|
end
|
109
78
|
end
|
110
79
|
end
|
111
80
|
end
|
112
81
|
end
|
113
82
|
|
114
|
-
|
115
|
-
|
83
|
+
module InstanceMethods
|
84
|
+
def has_set_coerce_argument_value(enum_class, argument_value)
|
85
|
+
invalid_set_elements = []
|
86
|
+
set_elements =
|
87
|
+
if String === argument_value
|
88
|
+
argument_value.split(',').map(&:strip)
|
89
|
+
else
|
90
|
+
Array(argument_value)
|
91
|
+
end.map do |set_element|
|
92
|
+
if result = enum_class[set_element]
|
93
|
+
result
|
94
|
+
else
|
95
|
+
invalid_set_elements << set_element
|
96
|
+
nil
|
97
|
+
end
|
98
|
+
end
|
99
|
+
invalid_set_elements.empty? or
|
100
|
+
raise ArgumentError, "element #{argument_value.inspect} contains invalid elements: #{invalid_set_elements.inspect}"
|
101
|
+
set_elements
|
102
|
+
end
|
116
103
|
end
|
117
104
|
end
|
118
105
|
end
|
@@ -25,6 +25,18 @@ module Degu
|
|
25
25
|
|
26
26
|
alias all values
|
27
27
|
|
28
|
+
def names
|
29
|
+
all.map(&:name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def underscored_names
|
33
|
+
all.map(&:underscored_name)
|
34
|
+
end
|
35
|
+
|
36
|
+
def field_names
|
37
|
+
all.map(&:field_name)
|
38
|
+
end
|
39
|
+
|
28
40
|
# This class encapsulates an enum field (аctually a method with arity == 0).
|
29
41
|
class Field < Struct.new('Field', :name, :options, :block)
|
30
42
|
# Returns true if the :default option was given.
|
@@ -145,6 +157,14 @@ module Degu
|
|
145
157
|
|
146
158
|
alias_method :id, :index
|
147
159
|
|
160
|
+
def underscored_name
|
161
|
+
name.underscore
|
162
|
+
end
|
163
|
+
|
164
|
+
def field_name
|
165
|
+
"#{self.class.name.underscore.singularize}_#{underscored_name}"
|
166
|
+
end
|
167
|
+
|
148
168
|
# Creates an enumerated value named +name+ with a unique autoincrementing
|
149
169
|
# index number.
|
150
170
|
def initialize name
|
data/lib/degu/version.rb
CHANGED
data/test/has_set_test.rb
CHANGED
@@ -95,10 +95,10 @@ class HasSetTest < Test::Unit::TestCase
|
|
95
95
|
|
96
96
|
def test_should_have_to_s_method
|
97
97
|
party = Party.new(:location => "Beach House", :drinks => [Drinks::Beer, Drinks::CubaLibre])
|
98
|
-
assert_equal "
|
98
|
+
assert_equal "beer,cuba_libre", party.drinks.to_s
|
99
99
|
end
|
100
100
|
|
101
|
-
def
|
101
|
+
def test_should_accept_enum_class
|
102
102
|
Party.has_set :music, :enum_class => MusicStyles
|
103
103
|
|
104
104
|
party = Party.new(:location => "Penthouse", :music => [MusicStyles::Rock])
|
@@ -107,6 +107,15 @@ class HasSetTest < Test::Unit::TestCase
|
|
107
107
|
assert party.music_rock?, "Party should have Rock music."
|
108
108
|
end
|
109
109
|
|
110
|
+
def test_should_accept_class_name
|
111
|
+
Party.has_set :music, :class_name => MusicStyles
|
112
|
+
|
113
|
+
party = Party.new(:location => "Penthouse", :music => [MusicStyles::Rock])
|
114
|
+
assert party.save, "Party should save!"
|
115
|
+
party.reload
|
116
|
+
assert party.music_rock?, "Party should have Rock music."
|
117
|
+
end
|
118
|
+
|
110
119
|
def test_should_allow_unset_bitset
|
111
120
|
itunes = Itunes.new
|
112
121
|
assert_nil itunes.music, itunes.inspect
|
@@ -143,7 +152,8 @@ class HasSetTest < Test::Unit::TestCase
|
|
143
152
|
end
|
144
153
|
|
145
154
|
def test_should_list_all_available_enum_elements
|
146
|
-
assert_equal ["drink_beer", "
|
155
|
+
assert_equal ["drink_beer", "drink_wine", "drink_cuba_libre"], Party.new.available_drinks
|
156
|
+
assert_equal ["drink_beer", "drink_wine", "drink_cuba_libre"], Party.available_drinks
|
147
157
|
end
|
148
158
|
|
149
159
|
def test_should_extend_enum_with_fieldname_method
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: degu
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
+
- 1
|
8
9
|
- 0
|
9
|
-
|
10
|
-
version: 0.0.5
|
10
|
+
version: 0.1.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Florian Frank
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-12-
|
18
|
+
date: 2011-12-15 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: gem_hadar
|
@@ -90,9 +90,23 @@ dependencies:
|
|
90
90
|
type: :development
|
91
91
|
version_requirements: *id005
|
92
92
|
- !ruby/object:Gem::Dependency
|
93
|
-
name:
|
93
|
+
name: rcov
|
94
94
|
prerelease: false
|
95
95
|
requirement: &id006 !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
104
|
+
type: :development
|
105
|
+
version_requirements: *id006
|
106
|
+
- !ruby/object:Gem::Dependency
|
107
|
+
name: activerecord
|
108
|
+
prerelease: false
|
109
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
96
110
|
none: false
|
97
111
|
requirements:
|
98
112
|
- - ~>
|
@@ -103,7 +117,7 @@ dependencies:
|
|
103
117
|
- 0
|
104
118
|
version: "3.0"
|
105
119
|
type: :runtime
|
106
|
-
version_requirements: *
|
120
|
+
version_requirements: *id007
|
107
121
|
description: Library that includes enums, and rails support for enums and bitfield sets.
|
108
122
|
email: dev@pkw.de
|
109
123
|
executables: []
|