acts_as_bits 0.2.1
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/LICENSE +20 -0
- data/README +73 -0
- data/Rakefile +74 -0
- data/lib/acts_as_bits.rb +198 -0
- data/tasks/acts_as_bits_tasks.rake +4 -0
- data/test/acts_as_bits_test.rb +153 -0
- data/test/database.yml +22 -0
- data/test/dirty_spec.rb +25 -0
- data/test/fixtures/mixin.rb +10 -0
- data/test/fixtures/mixins.yml +20 -0
- data/test/prefix_test.rb +52 -0
- data/test/schema.rb +9 -0
- data/test/spec_helper.rb +14 -0
- data/test/test_helper.rb +25 -0
- metadata +69 -0
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008 [maiha@wota.jp]
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
ActsAsBits
|
2
|
+
==========
|
3
|
+
|
4
|
+
ActiveRecord plugin that maintains massive flags in one column
|
5
|
+
|
6
|
+
|
7
|
+
Table Definition
|
8
|
+
================
|
9
|
+
|
10
|
+
Add "string" column into your model table.
|
11
|
+
|
12
|
+
ALTER TABLE users ADD operations varchar(255);
|
13
|
+
|
14
|
+
|
15
|
+
Model Definition
|
16
|
+
================
|
17
|
+
|
18
|
+
class User < ActiveRecord::Base
|
19
|
+
acts_as_bits :operations, %w( create read update delete )
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
Usage
|
24
|
+
=====
|
25
|
+
|
26
|
+
user = User.new
|
27
|
+
user.create? # => false
|
28
|
+
user.create = true
|
29
|
+
user.delete = true
|
30
|
+
user.operations # => "1001"
|
31
|
+
user.create? # => true
|
32
|
+
|
33
|
+
User.create!(:update => true, :read=>false)
|
34
|
+
|
35
|
+
|
36
|
+
Search
|
37
|
+
======
|
38
|
+
|
39
|
+
Finding methods work only on PostgreSQL, MySQL and SQL Server because we use "substring" function
|
40
|
+
|
41
|
+
User.find(:all, :conditions=>{:read=>true})
|
42
|
+
|
43
|
+
|
44
|
+
Advanced
|
45
|
+
========
|
46
|
+
|
47
|
+
"(column_name)=" enables to fill up values with argument that is true/false.
|
48
|
+
This is useful for initial setting like all allow/deny.
|
49
|
+
|
50
|
+
user = User.new
|
51
|
+
user.operations # => "0000"
|
52
|
+
|
53
|
+
# set all green
|
54
|
+
user.operations = true
|
55
|
+
user.operations # => "1111"
|
56
|
+
|
57
|
+
# set all red
|
58
|
+
user.operations = false
|
59
|
+
user.operations # => "0000"
|
60
|
+
|
61
|
+
|
62
|
+
Environment
|
63
|
+
===========
|
64
|
+
|
65
|
+
tested on
|
66
|
+
|
67
|
+
* Rails 1.2.6-2.3.2
|
68
|
+
|
69
|
+
|
70
|
+
Author
|
71
|
+
======
|
72
|
+
|
73
|
+
moriq and maiha
|
data/Rakefile
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
desc 'Default: run unit tests.'
|
6
|
+
task :default => :test
|
7
|
+
|
8
|
+
desc 'Test the acts_as_bits plugin.'
|
9
|
+
Rake::TestTask.new(:test) do |t|
|
10
|
+
t.libs << 'lib'
|
11
|
+
t.pattern = 'test/**/*_test.rb'
|
12
|
+
t.verbose = true
|
13
|
+
end
|
14
|
+
|
15
|
+
desc 'Generate documentation for the acts_as_bits plugin.'
|
16
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
17
|
+
rdoc.rdoc_dir = 'rdoc'
|
18
|
+
rdoc.title = 'ActsAsBits'
|
19
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
20
|
+
rdoc.rdoc_files.include('README')
|
21
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
######################################################################
|
26
|
+
### for gem
|
27
|
+
|
28
|
+
require 'rubygems'
|
29
|
+
require 'rake/gempackagetask'
|
30
|
+
|
31
|
+
GEM_NAME = "acts_as_bits"
|
32
|
+
AUTHOR = "maiha"
|
33
|
+
EMAIL = "maiha@wota.jp"
|
34
|
+
HOMEPAGE = "http://github.com/maiha/acts_as_bits"
|
35
|
+
SUMMARY = "ActiveRecord plugin that maintains massive flags in one column"
|
36
|
+
GEM_VERSION = "0.2.1"
|
37
|
+
|
38
|
+
spec = Gem::Specification.new do |s|
|
39
|
+
# s.rubyforge_project = 'merb'
|
40
|
+
s.name = GEM_NAME
|
41
|
+
s.version = GEM_VERSION
|
42
|
+
s.platform = Gem::Platform::RUBY
|
43
|
+
s.has_rdoc = true
|
44
|
+
s.extra_rdoc_files = ["README", "LICENSE"]
|
45
|
+
s.summary = SUMMARY
|
46
|
+
s.description = s.summary
|
47
|
+
s.author = AUTHOR
|
48
|
+
s.email = EMAIL
|
49
|
+
s.homepage = HOMEPAGE
|
50
|
+
s.require_path = 'lib'
|
51
|
+
s.files = %w(LICENSE README Rakefile) + Dir.glob("{core_ext,lib,spec,tasks,test}/**/*")
|
52
|
+
end
|
53
|
+
|
54
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
55
|
+
pkg.gem_spec = spec
|
56
|
+
end
|
57
|
+
|
58
|
+
desc "Install the gem"
|
59
|
+
task :install do
|
60
|
+
Merb::RakeHelper.install(GEM_NAME, :version => GEM_VERSION)
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Uninstall the gem"
|
64
|
+
task :uninstall do
|
65
|
+
Merb::RakeHelper.uninstall(GEM_NAME, :version => GEM_VERSION)
|
66
|
+
end
|
67
|
+
|
68
|
+
desc "Create a gemspec file"
|
69
|
+
task :gemspec do
|
70
|
+
File.open("#{GEM_NAME}.gemspec", "w") do |file|
|
71
|
+
file.puts spec.to_ruby
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
data/lib/acts_as_bits.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
3
|
+
# ActsAsBits
|
4
|
+
module ActsAsBits
|
5
|
+
def self.rails2?
|
6
|
+
ActiveRecord::Base.respond_to?(:sanitize_sql_hash_for_conditions)
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.append_features(base)
|
10
|
+
base.extend ClassMethods
|
11
|
+
base.extend(rails2? ? Rails2x : Rails1x)
|
12
|
+
base.class_eval do
|
13
|
+
def self.sanitize_sql_hash(*args)
|
14
|
+
sanitize_sql_hash_with_aab(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.sanitize_sql_hash_for_conditions(*args)
|
18
|
+
sanitize_sql_hash_with_aab(*args)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module Rails1x
|
24
|
+
def sanitize_sql_hash_with_aab(attrs)
|
25
|
+
values = []
|
26
|
+
conditions = attrs.map do |attr, value|
|
27
|
+
if bit_column = bit_columns_hash[attr.to_s]
|
28
|
+
flag = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
|
29
|
+
"#{bit_column} %s '1'" % (flag ? '=' : '<>')
|
30
|
+
else
|
31
|
+
values << value
|
32
|
+
prefix = "#{table_name}." rescue ''
|
33
|
+
"#{prefix}#{connection.quote_column_name(attr)} #{attribute_condition(value)}"
|
34
|
+
end
|
35
|
+
end.join(' AND ')
|
36
|
+
replace_bind_variables(conditions, expand_range_bind_variables(values))
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
module Rails2x
|
41
|
+
def sanitize_sql_hash_with_aab(attrs)
|
42
|
+
values = []
|
43
|
+
conditions = attrs.keys.map do |key|
|
44
|
+
value = attrs[key]
|
45
|
+
attr = key.to_s
|
46
|
+
|
47
|
+
# Extract table name from qualified attribute names.
|
48
|
+
if attr.include?('.')
|
49
|
+
table_name, attr = attr.split('.', 2)
|
50
|
+
table_name = connection.quote_table_name(table_name)
|
51
|
+
else
|
52
|
+
table_name = quoted_table_name
|
53
|
+
end
|
54
|
+
|
55
|
+
if bit_column = bit_columns_hash[attr]
|
56
|
+
flag = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(value)
|
57
|
+
"#{bit_column} %s '1'" % (flag ? '=' : '<>')
|
58
|
+
else
|
59
|
+
values << value
|
60
|
+
case ActiveRecord::Base.method(:attribute_condition).arity
|
61
|
+
when 1 # Rails 2.0-2.2
|
62
|
+
"#{table_name}.#{connection.quote_column_name(attr)} #{attribute_condition(value)}"
|
63
|
+
when 2 # Rails 2.3-
|
64
|
+
attribute_condition("#{table_name}.#{connection.quote_column_name(attr)}", value)
|
65
|
+
else
|
66
|
+
raise NotImplementedError, "unknown AR::Base#attribute_condition type"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end.join(' AND ')
|
70
|
+
replace_bind_variables(conditions, expand_range_bind_variables(values))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
module ClassMethods
|
75
|
+
def bit_columns_hash
|
76
|
+
@bit_columns_hash ||= {}
|
77
|
+
end
|
78
|
+
|
79
|
+
def acts_as_bits(part_id, bit_names, options = {})
|
80
|
+
composed_name = part_id.id2name
|
81
|
+
singular_name = composed_name.singularize
|
82
|
+
|
83
|
+
delegate "#{singular_name}_names", :to=>"self.class"
|
84
|
+
|
85
|
+
if options[:prefix]
|
86
|
+
bit_names = bit_names.map do |(name, label)|
|
87
|
+
name = "%s_%s" % [singular_name, name]
|
88
|
+
[name, label]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# true/false fills all values by itself
|
93
|
+
module_eval <<-end_eval
|
94
|
+
def #{composed_name}=(value)
|
95
|
+
case value
|
96
|
+
when true then super("1"*#{singular_name}_names.size)
|
97
|
+
when false then super("0"*#{singular_name}_names.size)
|
98
|
+
else super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end_eval
|
102
|
+
|
103
|
+
bit_names.each_with_index do |(name, label), index|
|
104
|
+
next if name.blank?
|
105
|
+
|
106
|
+
# register bit column
|
107
|
+
column_name = "COALESCE(SUBSTRING(%s.%s,%d,1),'')" % [table_name, connection.quote_column_name(composed_name), index+1]
|
108
|
+
(@bit_columns_hash ||= {})[name.to_s] = column_name
|
109
|
+
|
110
|
+
module_eval <<-end_eval
|
111
|
+
def #{name}
|
112
|
+
#{name}?
|
113
|
+
end
|
114
|
+
|
115
|
+
unless label.blank?
|
116
|
+
def self.#{name}_label
|
117
|
+
#{label.inspect}
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def #{name}?
|
122
|
+
#{composed_name}.to_s[#{index}] == ?1
|
123
|
+
end
|
124
|
+
|
125
|
+
def #{name}=(v)
|
126
|
+
v = ActiveRecord::ConnectionAdapters::Column.value_to_boolean(v) ? ?1 : ?0
|
127
|
+
|
128
|
+
# expand target string automatically
|
129
|
+
if #{composed_name}.size < #{singular_name}_names.size
|
130
|
+
#{composed_name} << "0" * (#{singular_name}_names.size - #{composed_name}.size)
|
131
|
+
end
|
132
|
+
|
133
|
+
value = #{composed_name}.dup
|
134
|
+
value[#{index}] = v
|
135
|
+
write_attribute("#{composed_name}", value)
|
136
|
+
return v
|
137
|
+
end
|
138
|
+
end_eval
|
139
|
+
|
140
|
+
compacted_bit_names = bit_names.select{|(i,)| !i.blank?}
|
141
|
+
column_names = compacted_bit_names.map{|(i,)| i.to_s}
|
142
|
+
label_names = compacted_bit_names.map{|(n,i)| i.to_s}
|
143
|
+
|
144
|
+
module_eval <<-end_eval
|
145
|
+
def self.#{singular_name}_names
|
146
|
+
#{column_names.inspect}
|
147
|
+
end
|
148
|
+
|
149
|
+
if options[:prefix]
|
150
|
+
|
151
|
+
def #{singular_name}?(name = nil)
|
152
|
+
if name
|
153
|
+
__send__ "#{singular_name}_" + name.to_s
|
154
|
+
else
|
155
|
+
#{composed_name}.to_s.include?('1')
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
else
|
160
|
+
|
161
|
+
def #{singular_name}?(name = nil)
|
162
|
+
if name
|
163
|
+
__send__ name
|
164
|
+
else
|
165
|
+
#{composed_name}.to_s.include?('1')
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
def #{composed_name}
|
172
|
+
self.#{composed_name} = "0" * #{column_names.size} if super.blank?
|
173
|
+
super
|
174
|
+
end
|
175
|
+
|
176
|
+
def #{composed_name}_hash
|
177
|
+
HashWithIndifferentAccess[*#{singular_name}_names.map{|i| [i,__send__(i)]}.flatten]
|
178
|
+
end
|
179
|
+
end_eval
|
180
|
+
|
181
|
+
module_eval <<-end_eval
|
182
|
+
def self.#{singular_name}_labels
|
183
|
+
#{label_names.inspect}
|
184
|
+
end
|
185
|
+
|
186
|
+
def self.#{singular_name}_names_with_labels
|
187
|
+
#{bit_names.inspect}
|
188
|
+
end
|
189
|
+
end_eval
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end # ClassMethods
|
193
|
+
end
|
194
|
+
|
195
|
+
ActiveRecord::Base.class_eval do
|
196
|
+
include ActsAsBits
|
197
|
+
end
|
198
|
+
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class ActsAsBitsTest < Test::Unit::TestCase
|
4
|
+
fixtures :mixins
|
5
|
+
|
6
|
+
def test_respond
|
7
|
+
m = mixins(:bits_00)
|
8
|
+
|
9
|
+
assert_respond_to m, :admin
|
10
|
+
assert_respond_to m, :admin?
|
11
|
+
assert_respond_to m, :admin=
|
12
|
+
|
13
|
+
assert_respond_to m, :composer
|
14
|
+
assert_respond_to m, :composer?
|
15
|
+
assert_respond_to m, :composer=
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_reader_00
|
19
|
+
m = mixins(:bits_00)
|
20
|
+
|
21
|
+
assert ! m.admin?
|
22
|
+
assert ! m.composer?
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_writer_01
|
26
|
+
m = mixins(:bits_01)
|
27
|
+
|
28
|
+
m.admin = true
|
29
|
+
m.composer = false
|
30
|
+
|
31
|
+
# save?
|
32
|
+
|
33
|
+
assert m.admin?
|
34
|
+
assert ! m.composer?
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_reader_to_new_object
|
38
|
+
m = Mixin.new
|
39
|
+
|
40
|
+
assert_equal false, m.admin?
|
41
|
+
assert_equal false, m.composer?
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_names
|
45
|
+
assert_equal %w( top right bottom left ), Mixin.position_names
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_labels
|
49
|
+
assert_equal "TOP", Mixin.top_label
|
50
|
+
assert_equal "RIGHT", Mixin.right_label
|
51
|
+
assert_equal "BOTTOM", Mixin.bottom_label
|
52
|
+
assert_equal "LEFT", Mixin.left_label
|
53
|
+
|
54
|
+
assert_equal %w( TOP RIGHT BOTTOM LEFT ), Mixin.position_labels
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_names_with_labels
|
58
|
+
expected = [
|
59
|
+
[:top, "TOP"],
|
60
|
+
[:right, "RIGHT"],
|
61
|
+
[:bottom, "BOTTOM"],
|
62
|
+
[:left, "LEFT"],
|
63
|
+
]
|
64
|
+
assert_equal expected, Mixin.position_names_with_labels
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_nil_means_blank_column
|
68
|
+
assert_equal %w( flag1 flag3 ), Mixin.blank_flag_names
|
69
|
+
|
70
|
+
assert_equal false, mixins(:bits_00).flag1
|
71
|
+
assert_equal false, mixins(:bits_00).flag3
|
72
|
+
assert_equal true , mixins(:bits_10).flag1
|
73
|
+
assert_equal false, mixins(:bits_10).flag3
|
74
|
+
|
75
|
+
assert_equal "0000", Mixin.new.positions
|
76
|
+
|
77
|
+
assert_equal "00", Mixin.new.blank_flags
|
78
|
+
assert_equal false, Mixin.new.flag1
|
79
|
+
assert_equal false, Mixin.new.flag3
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_referer_to_out_of_index
|
83
|
+
Mixin.delete_all
|
84
|
+
mixin = Mixin.create!(:positions=>"11")
|
85
|
+
assert_equal true, mixin.top?
|
86
|
+
assert_equal true, mixin.right?
|
87
|
+
assert_equal false, mixin.bottom?
|
88
|
+
assert_equal false, mixin.left?
|
89
|
+
end
|
90
|
+
|
91
|
+
def test_subscribe_to_out_of_index
|
92
|
+
Mixin.delete_all
|
93
|
+
mixin = Mixin.create!(:positions=>"11")
|
94
|
+
|
95
|
+
assert_nothing_raised do
|
96
|
+
mixin.left = true
|
97
|
+
end
|
98
|
+
|
99
|
+
assert_equal true, mixin.left?
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_functional_accessor
|
103
|
+
mixin = Mixin.create!(:positions=>"1010")
|
104
|
+
assert_equal true, mixin.position?(:top)
|
105
|
+
assert_equal false, mixin.position?(:right)
|
106
|
+
assert_equal true, mixin.position?(:bottom)
|
107
|
+
assert_equal false, mixin.position?(:left)
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_functional_accessor_without_args
|
111
|
+
mixin = Mixin.create!(:positions=>"0001")
|
112
|
+
assert_equal true, mixin.position?
|
113
|
+
|
114
|
+
mixin = Mixin.create!(:positions=>"0000")
|
115
|
+
assert_equal false, mixin.position?
|
116
|
+
|
117
|
+
mixin = Mixin.create!(:positions=>"1111")
|
118
|
+
assert_equal true, mixin.position?
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_sanitize_sql_hash
|
122
|
+
expected = ["COALESCE(SUBSTRING(mixins.positions,1,1),'') = '1'", "COALESCE(SUBSTRING(mixins.positions,4,1),'') <> '1'"]
|
123
|
+
executed = Mixin.__send__(:sanitize_sql_hash, {:top => true, :left => false})
|
124
|
+
executed = executed.delete('`"').split(/ AND /).sort
|
125
|
+
|
126
|
+
assert_equal expected, executed
|
127
|
+
end
|
128
|
+
|
129
|
+
def test_search
|
130
|
+
conditions = {:top=>true}
|
131
|
+
assert_equal 1, Mixin.count(:conditions=>conditions)
|
132
|
+
assert_equal 1, Mixin.find(:all, :conditions=>conditions).size
|
133
|
+
|
134
|
+
conditions = {:top=>false, :right=>false, :bottom=>false, :left=>false}
|
135
|
+
assert_equal 2, Mixin.count(:conditions=>conditions)
|
136
|
+
assert_equal 2, Mixin.find(:all, :conditions=>conditions).size
|
137
|
+
|
138
|
+
conditions = {:top=>true, :right=>true, :bottom=>true, :left=>true}
|
139
|
+
assert_equal 1, Mixin.count(:conditions=>conditions)
|
140
|
+
assert_equal 1, Mixin.find(:all, :conditions=>conditions).size
|
141
|
+
end
|
142
|
+
|
143
|
+
def test_set_all
|
144
|
+
obj = Mixin.new
|
145
|
+
assert_equal "00", obj.flags
|
146
|
+
|
147
|
+
obj.flags = true
|
148
|
+
assert_equal "11", obj.flags
|
149
|
+
|
150
|
+
obj.flags = false
|
151
|
+
assert_equal "00", obj.flags
|
152
|
+
end
|
153
|
+
end
|
data/test/database.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
sqlite:
|
2
|
+
:adapter: sqlite
|
3
|
+
:dbfile: acts_as_bits_plugin_test.sqlite.db
|
4
|
+
|
5
|
+
sqlite3:
|
6
|
+
:adapter: sqlite3
|
7
|
+
:dbfile: acts_as_bits_plugin_test.sqlite3.db
|
8
|
+
|
9
|
+
postgresql:
|
10
|
+
:adapter: postgresql
|
11
|
+
:username: maiha
|
12
|
+
:password:
|
13
|
+
:database: test
|
14
|
+
:min_messages: ERROR
|
15
|
+
|
16
|
+
mysql:
|
17
|
+
:adapter: mysql
|
18
|
+
:host: localhost
|
19
|
+
:username: rails
|
20
|
+
:password:
|
21
|
+
:database: acts_as_bits_plugin_test
|
22
|
+
|
data/test/dirty_spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
2
|
+
|
3
|
+
describe ActsAsBits do
|
4
|
+
describe " should mark dirty" do
|
5
|
+
before(:each) do
|
6
|
+
@obj = Mixin.create!(:flags=>"00")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "when value is changed by setter" do
|
10
|
+
@obj.flags # create string object first
|
11
|
+
@obj.changed?.should == false
|
12
|
+
@obj.admin = true
|
13
|
+
@obj.changed?.should == true
|
14
|
+
@obj.changes.should == {"flags"=>["00", "10"]}
|
15
|
+
end
|
16
|
+
|
17
|
+
it "when massive assignment" do
|
18
|
+
@obj.flags # create string object first
|
19
|
+
@obj.changed?.should == false
|
20
|
+
@obj.attributes = {:admin => true}
|
21
|
+
@obj.changed?.should == true
|
22
|
+
@obj.changes.should == {"flags"=>["00", "10"]}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
bits_00:
|
2
|
+
id: 1
|
3
|
+
flags: "00"
|
4
|
+
positions: "0000"
|
5
|
+
blank_flags: "0 0"
|
6
|
+
bits_01:
|
7
|
+
id: 2
|
8
|
+
flags: "01"
|
9
|
+
positions: "1111"
|
10
|
+
blank_flags: "0 1"
|
11
|
+
bits_10:
|
12
|
+
id: 3
|
13
|
+
flags: "10"
|
14
|
+
positions: "0101"
|
15
|
+
blank_flags: "1 0"
|
16
|
+
bits_11:
|
17
|
+
id: 4
|
18
|
+
flags: "11"
|
19
|
+
positions: ""
|
20
|
+
blank_flags: "1 1"
|
data/test/prefix_test.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
class PrefixTest < Test::Unit::TestCase
|
4
|
+
class User < ActiveRecord::Base
|
5
|
+
set_table_name :mixins
|
6
|
+
acts_as_bits :flags, %w( login show ), :prefix=>true
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_not_respond_to_native_name
|
10
|
+
user = User.new
|
11
|
+
|
12
|
+
assert ! user.respond_to?(:login)
|
13
|
+
assert ! user.respond_to?(:show)
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_respond_to_prefixed_name
|
17
|
+
user = User.new
|
18
|
+
|
19
|
+
assert_respond_to user, :flag_login?
|
20
|
+
assert_respond_to user, :flag_login=
|
21
|
+
assert_respond_to user, :flag_login
|
22
|
+
assert_respond_to user, :flag_show?
|
23
|
+
assert_respond_to user, :flag_show=
|
24
|
+
assert_respond_to user, :flag_show
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_respond_to_prefix_method
|
28
|
+
user = User.new
|
29
|
+
assert_respond_to user, :flag?
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_setter
|
33
|
+
user = User.new
|
34
|
+
assert_equal false, user.flag_login?
|
35
|
+
user.flag_login = true
|
36
|
+
assert_equal true , user.flag_login?
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_prefix_method
|
40
|
+
user = User.new
|
41
|
+
assert_equal false, user.flag?(:login)
|
42
|
+
assert_equal false, user.flag?(:show)
|
43
|
+
assert_equal false, user.flag?("login")
|
44
|
+
assert_equal false, user.flag?("show")
|
45
|
+
|
46
|
+
user.flag_login = true
|
47
|
+
assert_equal true, user.flag?(:login)
|
48
|
+
assert_equal false, user.flag?(:show)
|
49
|
+
assert_equal true, user.flag?("login")
|
50
|
+
assert_equal false, user.flag?("show")
|
51
|
+
end
|
52
|
+
end
|
data/test/schema.rb
ADDED
data/test/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'spec'
|
3
|
+
require 'active_record'
|
4
|
+
|
5
|
+
__DIR__ = File.dirname(__FILE__)
|
6
|
+
config = YAML::load_file(__DIR__ + '/database.yml')
|
7
|
+
ActiveRecord::Base.configurations = config
|
8
|
+
ActiveRecord::Base.establish_connection(ENV['DB'] || 'postgresql')
|
9
|
+
load(__DIR__ + "/schema.rb")
|
10
|
+
|
11
|
+
$:.unshift __DIR__ + "/../lib"
|
12
|
+
require 'acts_as_bits'
|
13
|
+
|
14
|
+
require File.join(__DIR__, "fixtures/mixin")
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
def __DIR__; File.dirname(__FILE__); end
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'test/unit'
|
5
|
+
require 'active_support'
|
6
|
+
require 'active_record'
|
7
|
+
require 'active_record/fixtures'
|
8
|
+
|
9
|
+
config = YAML::load_file(__DIR__ + '/database.yml')
|
10
|
+
ActiveRecord::Base.logger = Logger.new(__DIR__ + "/debug.log")
|
11
|
+
ActiveRecord::Base.colorize_logging = false
|
12
|
+
ActiveRecord::Base.configurations = config
|
13
|
+
ActiveRecord::Base.establish_connection(ENV['DB'] || 'postgresql')
|
14
|
+
|
15
|
+
$:.unshift __DIR__ + '/../lib'
|
16
|
+
require __DIR__ + '/../init'
|
17
|
+
|
18
|
+
# create tables
|
19
|
+
load(__DIR__ + "/schema.rb")
|
20
|
+
|
21
|
+
# insert sample data to the tables from 'fixtures/*.yml'
|
22
|
+
Test::Unit::TestCase.fixture_path = __DIR__ + "/fixtures/"
|
23
|
+
$LOAD_PATH.unshift(Test::Unit::TestCase.fixture_path)
|
24
|
+
Test::Unit::TestCase.use_instantiated_fixtures = true
|
25
|
+
|
metadata
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: acts_as_bits
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- maiha
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-10-19 00:00:00 +09:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description: ActiveRecord plugin that maintains massive flags in one column
|
17
|
+
email: maiha@wota.jp
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
- LICENSE
|
25
|
+
files:
|
26
|
+
- LICENSE
|
27
|
+
- README
|
28
|
+
- Rakefile
|
29
|
+
- lib/acts_as_bits.rb
|
30
|
+
- tasks/acts_as_bits_tasks.rake
|
31
|
+
- test/database.yml
|
32
|
+
- test/fixtures/mixin.rb
|
33
|
+
- test/fixtures/mixins.yml
|
34
|
+
- test/schema.rb
|
35
|
+
- test/prefix_test.rb
|
36
|
+
- test/acts_as_bits_test.rb
|
37
|
+
- test/spec_helper.rb
|
38
|
+
- test/test_helper.rb
|
39
|
+
- test/dirty_spec.rb
|
40
|
+
has_rdoc: true
|
41
|
+
homepage: http://github.com/maiha/acts_as_bits
|
42
|
+
licenses: []
|
43
|
+
|
44
|
+
post_install_message:
|
45
|
+
rdoc_options: []
|
46
|
+
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: "0"
|
54
|
+
version:
|
55
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
requirements: []
|
62
|
+
|
63
|
+
rubyforge_project:
|
64
|
+
rubygems_version: 1.3.5
|
65
|
+
signing_key:
|
66
|
+
specification_version: 3
|
67
|
+
summary: ActiveRecord plugin that maintains massive flags in one column
|
68
|
+
test_files: []
|
69
|
+
|