bitmask-attribute 1.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/.document +5 -0
- data/.gitignore +5 -0
- data/LICENSE +20 -0
- data/README.markdown +47 -0
- data/Rakefile +57 -0
- data/VERSION.yml +4 -0
- data/bitmask-attribute.gemspec +50 -0
- data/lib/bitmask-attribute.rb +2 -0
- data/lib/bitmask_attribute/value_proxy.rb +72 -0
- data/lib/bitmask_attribute.rb +100 -0
- data/rails/init.rb +3 -0
- data/test/bitmask_attribute_test.rb +104 -0
- data/test/test_helper.rb +55 -0
- metadata +78 -0
data/.document
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2007-2009 Bruce Williams
|
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.markdown
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# bitmask-attribute
|
2
|
+
|
3
|
+
Transparent manipulation of bitmask attributes.
|
4
|
+
|
5
|
+
## Example
|
6
|
+
|
7
|
+
Simply declare an existing integer column as a bitmask with its possible
|
8
|
+
values.
|
9
|
+
|
10
|
+
class User < ActiveRecord::Base
|
11
|
+
bitmask :roles, :as => [:writer, :publisher, :editor]
|
12
|
+
end
|
13
|
+
|
14
|
+
You can then modify the column using the declared values without resorting
|
15
|
+
to manual bitmasks.
|
16
|
+
|
17
|
+
user = User.create(:name => "Bruce", :roles => [:publisher, :editor])
|
18
|
+
user.roles
|
19
|
+
# => [:publisher, :editor]
|
20
|
+
user.roles << :writer
|
21
|
+
user.roles
|
22
|
+
# => [:publisher, :editor, :writer]
|
23
|
+
|
24
|
+
For the moment, querying for bitmasks is left as an exercise to the reader,
|
25
|
+
but here's how to grab the bitmask for a specific possible value for use in
|
26
|
+
your SQL query:
|
27
|
+
|
28
|
+
bitmask = User.bitmasks[:roles][:editor]
|
29
|
+
# Use `bitmask` as needed
|
30
|
+
|
31
|
+
## Modifying possible values
|
32
|
+
|
33
|
+
Once you have data using a bitmask, don't change the order of the values,
|
34
|
+
remove any values, or insert any new values in the array anywhere except at
|
35
|
+
the end.
|
36
|
+
|
37
|
+
## Contributing and reporting issues
|
38
|
+
|
39
|
+
Please feel free to fork & contribute fixes via GitHub pull requests.
|
40
|
+
The official repository for this project is
|
41
|
+
http://github.com/bruce/bitmask-attribute
|
42
|
+
|
43
|
+
Issues can be reported at http://github.com/bruce/bitmask-attribute/issues
|
44
|
+
|
45
|
+
## Copyright
|
46
|
+
|
47
|
+
Copyright (c) 2007-2009 Bruce Williams. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "bitmask-attribute"
|
8
|
+
gem.summary = %Q{Simple bitmask attribute support for ActiveRecord}
|
9
|
+
gem.email = "bruce@codefluency.com"
|
10
|
+
gem.homepage = "http://github.com/bruce/bitmask-attribute"
|
11
|
+
gem.authors = ["Bruce Williams"]
|
12
|
+
gem.add_dependency 'activerecord'
|
13
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
14
|
+
end
|
15
|
+
Jeweler::GemcutterTasks.new
|
16
|
+
rescue LoadError
|
17
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'rake/testtask'
|
21
|
+
Rake::TestTask.new(:test) do |test|
|
22
|
+
test.libs << 'lib' << 'test'
|
23
|
+
test.pattern = 'test/**/*_test.rb'
|
24
|
+
test.verbose = true
|
25
|
+
end
|
26
|
+
|
27
|
+
begin
|
28
|
+
require 'rcov/rcovtask'
|
29
|
+
Rcov::RcovTask.new do |test|
|
30
|
+
test.libs << 'test'
|
31
|
+
test.pattern = 'test/**/*_test.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
rescue LoadError
|
35
|
+
task :rcov do
|
36
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
task :default => :test
|
42
|
+
|
43
|
+
require 'rake/rdoctask'
|
44
|
+
Rake::RDocTask.new do |rdoc|
|
45
|
+
if File.exist?('VERSION.yml')
|
46
|
+
config = YAML.load(File.read('VERSION.yml'))
|
47
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
48
|
+
else
|
49
|
+
version = ""
|
50
|
+
end
|
51
|
+
|
52
|
+
rdoc.rdoc_dir = 'rdoc'
|
53
|
+
rdoc.title = "bitmask-attribute #{version}"
|
54
|
+
rdoc.rdoc_files.include('README*')
|
55
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
56
|
+
end
|
57
|
+
|
data/VERSION.yml
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{bitmask-attribute}
|
5
|
+
s.version = "1.0.0"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["Bruce Williams"]
|
9
|
+
s.date = %q{2009-05-18}
|
10
|
+
s.email = %q{bruce@codefluency.com}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"LICENSE",
|
13
|
+
"README.markdown"
|
14
|
+
]
|
15
|
+
s.files = [
|
16
|
+
"LICENSE",
|
17
|
+
"README.markdown",
|
18
|
+
"Rakefile",
|
19
|
+
"VERSION.yml",
|
20
|
+
"lib/bitmask-attribute.rb",
|
21
|
+
"lib/bitmask_attribute.rb",
|
22
|
+
"lib/bitmask_attribute/value_proxy.rb",
|
23
|
+
"rails/init.rb",
|
24
|
+
"test/bitmask_attribute_test.rb",
|
25
|
+
"test/test_helper.rb"
|
26
|
+
]
|
27
|
+
s.has_rdoc = true
|
28
|
+
s.homepage = %q{http://github.com/bruce/bitmask-attribute}
|
29
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
30
|
+
s.require_paths = ["lib"]
|
31
|
+
s.rubygems_version = %q{1.3.2}
|
32
|
+
s.summary = %q{Simple bitmask attribute support for ActiveRecord}
|
33
|
+
s.test_files = [
|
34
|
+
"test/bitmask_attribute_test.rb",
|
35
|
+
"test/test_helper.rb"
|
36
|
+
]
|
37
|
+
|
38
|
+
if s.respond_to? :specification_version then
|
39
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
40
|
+
s.specification_version = 3
|
41
|
+
|
42
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
43
|
+
s.add_runtime_dependency(%q<activerecord>, [">= 0"])
|
44
|
+
else
|
45
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
46
|
+
end
|
47
|
+
else
|
48
|
+
s.add_dependency(%q<activerecord>, [">= 0"])
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module BitmaskAttribute
|
2
|
+
|
3
|
+
class ValueProxy < Array
|
4
|
+
|
5
|
+
def initialize(record, attribute, &extension)
|
6
|
+
@record = record
|
7
|
+
@attribute = attribute
|
8
|
+
find_mapping
|
9
|
+
instance_eval(&extension) if extension
|
10
|
+
super(extract_values)
|
11
|
+
end
|
12
|
+
|
13
|
+
# =========================
|
14
|
+
# = OVERRIDE TO SERIALIZE =
|
15
|
+
# =========================
|
16
|
+
|
17
|
+
%w(push << delete replace reject! select!).each do |override|
|
18
|
+
class_eval(<<-EOEVAL)
|
19
|
+
def #{override}(*args)
|
20
|
+
returning(super) do
|
21
|
+
updated!
|
22
|
+
end
|
23
|
+
end
|
24
|
+
EOEVAL
|
25
|
+
end
|
26
|
+
|
27
|
+
def to_i
|
28
|
+
inject(0) { |memo, value| memo | @mapping[value] }
|
29
|
+
end
|
30
|
+
|
31
|
+
#######
|
32
|
+
private
|
33
|
+
#######
|
34
|
+
|
35
|
+
def validate!
|
36
|
+
each do |value|
|
37
|
+
if @mapping.key? value
|
38
|
+
true
|
39
|
+
else
|
40
|
+
raise ArgumentError, "Unsupported value for `#{@attribute}': #{value.inspect}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def updated!
|
46
|
+
validate!
|
47
|
+
uniq!
|
48
|
+
serialize!
|
49
|
+
end
|
50
|
+
|
51
|
+
def serialize!
|
52
|
+
@record.send(:write_attribute, @attribute, to_i)
|
53
|
+
end
|
54
|
+
|
55
|
+
def extract_values
|
56
|
+
stored = @record.send(:read_attribute, @attribute) || 0
|
57
|
+
@mapping.inject([]) do |values, (value, bitmask)|
|
58
|
+
returning values do
|
59
|
+
values << value.to_sym if (stored & bitmask > 0)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def find_mapping
|
65
|
+
unless (@mapping = @record.class.bitmasks[@attribute])
|
66
|
+
raise ArgumentError, "Could not find mapping for bitmask attribute :#{@attribute}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'bitmask_attribute/value_proxy'
|
2
|
+
|
3
|
+
module BitmaskAttribute
|
4
|
+
|
5
|
+
class Definition
|
6
|
+
|
7
|
+
attr_reader :attribute, :values, :extension
|
8
|
+
def initialize(attribute, values=[], &extension)
|
9
|
+
@attribute = attribute
|
10
|
+
@values = values
|
11
|
+
@extension = extension
|
12
|
+
end
|
13
|
+
|
14
|
+
def install_on(model)
|
15
|
+
validate_for model
|
16
|
+
generate_bitmasks_on model
|
17
|
+
override model
|
18
|
+
create_convenience_method_on model
|
19
|
+
end
|
20
|
+
|
21
|
+
#######
|
22
|
+
private
|
23
|
+
#######
|
24
|
+
|
25
|
+
def validate_for(model)
|
26
|
+
unless model.columns.detect { |col| col.name == attribute.to_s && col.type == :integer }
|
27
|
+
raise ArgumentError, "`#{attribute}' is not an integer column of `#{model}'"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def generate_bitmasks_on(model)
|
32
|
+
model.bitmasks[attribute] = returning HashWithIndifferentAccess.new do |mapping|
|
33
|
+
values.each_with_index do |value, index|
|
34
|
+
mapping[value] = 0b1 << index
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def override(model)
|
40
|
+
override_getter_on(model)
|
41
|
+
override_setter_on(model)
|
42
|
+
end
|
43
|
+
|
44
|
+
def override_getter_on(model)
|
45
|
+
model.class_eval %(
|
46
|
+
def #{attribute}
|
47
|
+
@#{attribute} ||= BitmaskAttribute::ValueProxy.new(self, :#{attribute}, &self.class.bitmask_definitions[:#{attribute}].extension)
|
48
|
+
end
|
49
|
+
)
|
50
|
+
end
|
51
|
+
|
52
|
+
def override_setter_on(model)
|
53
|
+
model.class_eval %(
|
54
|
+
def #{attribute}=(raw_value)
|
55
|
+
values = raw_value.kind_of?(Array) ? raw_value : [raw_value]
|
56
|
+
#{attribute}.replace(values)
|
57
|
+
end
|
58
|
+
)
|
59
|
+
end
|
60
|
+
|
61
|
+
def create_convenience_method_on(model)
|
62
|
+
model.class_eval %(
|
63
|
+
def self.bitmask_for_#{attribute}(*values)
|
64
|
+
values.inject(0) do |bitmask, value|
|
65
|
+
unless (bit = bitmasks[:#{attribute}][value])
|
66
|
+
raise ArgumentError, "Unsupported value for #{attribute}: \#{value.inspect}"
|
67
|
+
end
|
68
|
+
bitmask | bit
|
69
|
+
end
|
70
|
+
end
|
71
|
+
)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.included(model)
|
77
|
+
model.extend ClassMethods
|
78
|
+
end
|
79
|
+
|
80
|
+
module ClassMethods
|
81
|
+
|
82
|
+
def bitmask(attribute, options={}, &extension)
|
83
|
+
unless options[:as] && options[:as].kind_of?(Array)
|
84
|
+
raise ArgumentError, "Must provide an Array :as option"
|
85
|
+
end
|
86
|
+
bitmask_definitions[attribute] = BitmaskAttribute::Definition.new(attribute, options[:as].to_a, &extension)
|
87
|
+
bitmask_definitions[attribute].install_on(self)
|
88
|
+
end
|
89
|
+
|
90
|
+
def bitmask_definitions
|
91
|
+
@bitmask_definitions ||= {}
|
92
|
+
end
|
93
|
+
|
94
|
+
def bitmasks
|
95
|
+
@bitmasks ||= {}
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
data/rails/init.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class BitmaskAttributeTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "Campaign" do
|
6
|
+
|
7
|
+
should "can assign single value to bitmask" do
|
8
|
+
assert_stored Campaign.new(:medium => :web), :web
|
9
|
+
end
|
10
|
+
|
11
|
+
should "can assign multiple values to bitmask" do
|
12
|
+
assert_stored Campaign.new(:medium => [:web, :print]), :web, :print
|
13
|
+
end
|
14
|
+
|
15
|
+
should "can add single value to bitmask" do
|
16
|
+
campaign = Campaign.new(:medium => [:web, :print])
|
17
|
+
assert_stored campaign, :web, :print
|
18
|
+
campaign.medium << :phone
|
19
|
+
assert_stored campaign, :web, :print, :phone
|
20
|
+
end
|
21
|
+
|
22
|
+
should "ignores duplicate values added to bitmask" do
|
23
|
+
campaign = Campaign.new(:medium => [:web, :print])
|
24
|
+
assert_stored campaign, :web, :print
|
25
|
+
campaign.medium << :phone
|
26
|
+
assert_stored campaign, :web, :print, :phone
|
27
|
+
campaign.medium << :phone
|
28
|
+
assert_stored campaign, :web, :print, :phone
|
29
|
+
assert_equal 1, campaign.medium.select { |value| value == :phone }.size
|
30
|
+
end
|
31
|
+
|
32
|
+
should "can assign new values at once to bitmask" do
|
33
|
+
campaign = Campaign.new(:medium => [:web, :print])
|
34
|
+
assert_stored campaign, :web, :print
|
35
|
+
campaign.medium = [:phone, :email]
|
36
|
+
assert_stored campaign, :phone, :email
|
37
|
+
end
|
38
|
+
|
39
|
+
should "can save bitmask to db and retrieve values transparently" do
|
40
|
+
campaign = Campaign.new(:medium => [:web, :print])
|
41
|
+
assert_stored campaign, :web, :print
|
42
|
+
assert campaign.save
|
43
|
+
assert_stored Campaign.find(campaign.id), :web, :print
|
44
|
+
end
|
45
|
+
|
46
|
+
should "can add custom behavor to value proxies during bitmask definition" do
|
47
|
+
campaign = Campaign.new(:medium => [:web, :print])
|
48
|
+
assert_raises NoMethodError do
|
49
|
+
campaign.medium.worked?
|
50
|
+
end
|
51
|
+
assert_nothing_raised do
|
52
|
+
campaign.misc.worked?
|
53
|
+
end
|
54
|
+
assert campaign.misc.worked?
|
55
|
+
end
|
56
|
+
|
57
|
+
should "cannot use unsupported values" do
|
58
|
+
assert_unsupported { Campaign.new(:medium => [:web, :print, :this_will_fail]) }
|
59
|
+
campaign = Campaign.new(:medium => :web)
|
60
|
+
assert_unsupported { campaign.medium << :this_will_fail_also }
|
61
|
+
assert_unsupported { campaign.medium = [:so_will_this] }
|
62
|
+
end
|
63
|
+
|
64
|
+
should "can determine bitmasks using convenience method" do
|
65
|
+
assert Campaign.bitmask_for_medium(:web, :print)
|
66
|
+
assert_equal(
|
67
|
+
Campaign.bitmasks[:medium][:web] | Campaign.bitmasks[:medium][:print],
|
68
|
+
Campaign.bitmask_for_medium(:web, :print)
|
69
|
+
)
|
70
|
+
end
|
71
|
+
|
72
|
+
should "assert use of unknown value in convenience method will result in exception" do
|
73
|
+
assert_unsupported { Campaign.bitmask_for_medium(:web, :and_this_isnt_valid) }
|
74
|
+
end
|
75
|
+
|
76
|
+
should "hash of values is with indifferent access" do
|
77
|
+
string_bit = nil
|
78
|
+
assert_nothing_raised do
|
79
|
+
assert (string_bit = Campaign.bitmask_for_medium('web', 'print'))
|
80
|
+
end
|
81
|
+
assert_equal Campaign.bitmask_for_medium(:web, :print), string_bit
|
82
|
+
end
|
83
|
+
|
84
|
+
#######
|
85
|
+
private
|
86
|
+
#######
|
87
|
+
|
88
|
+
def assert_unsupported(&block)
|
89
|
+
assert_raises(ArgumentError, &block)
|
90
|
+
end
|
91
|
+
|
92
|
+
def assert_stored(record, *values)
|
93
|
+
values.each do |value|
|
94
|
+
assert record.medium.any? { |v| v.to_s == value.to_s }, "Values #{record.medium.inspect} does not include #{value.inspect}"
|
95
|
+
end
|
96
|
+
full_mask = values.inject(0) do |mask, value|
|
97
|
+
mask | Campaign.bitmasks[:medium][value]
|
98
|
+
end
|
99
|
+
assert_equal full_mask, record.medium.to_i
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
|
104
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'shoulda'
|
4
|
+
begin
|
5
|
+
require 'redgreen'
|
6
|
+
rescue LoadError
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'active_support'
|
10
|
+
require 'active_record'
|
11
|
+
|
12
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
13
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
14
|
+
require 'bitmask-attribute'
|
15
|
+
require File.dirname(__FILE__) + '/../rails/init'
|
16
|
+
|
17
|
+
ActiveRecord::Base.establish_connection(
|
18
|
+
:adapter => 'sqlite3',
|
19
|
+
:database => ':memory:'
|
20
|
+
)
|
21
|
+
|
22
|
+
ActiveRecord::Schema.define do
|
23
|
+
create_table :campaigns do |table|
|
24
|
+
table.column :medium, :integer
|
25
|
+
table.column :misc, :integer
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Pseudo model for testing purposes
|
30
|
+
class Campaign < ActiveRecord::Base
|
31
|
+
bitmask :medium, :as => [:web, :print, :email, :phone]
|
32
|
+
bitmask :misc, :as => %w(some useless values) do
|
33
|
+
def worked?
|
34
|
+
true
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Test::Unit::TestCase
|
40
|
+
|
41
|
+
def assert_unsupported(&block)
|
42
|
+
assert_raises(ArgumentError, &block)
|
43
|
+
end
|
44
|
+
|
45
|
+
def assert_stored(record, *values)
|
46
|
+
values.each do |value|
|
47
|
+
assert record.medium.any? { |v| v.to_s == value.to_s }, "Values #{record.medium.inspect} does not include #{value.inspect}"
|
48
|
+
end
|
49
|
+
full_mask = values.inject(0) do |mask, value|
|
50
|
+
mask | Campaign.bitmasks[:medium][value]
|
51
|
+
end
|
52
|
+
assert_equal full_mask, record.medium.to_i
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: bitmask-attribute
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Bruce Williams
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-14 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: activerecord
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
description:
|
26
|
+
email: bruce@codefluency.com
|
27
|
+
executables: []
|
28
|
+
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- LICENSE
|
33
|
+
- README.markdown
|
34
|
+
files:
|
35
|
+
- .document
|
36
|
+
- .gitignore
|
37
|
+
- LICENSE
|
38
|
+
- README.markdown
|
39
|
+
- Rakefile
|
40
|
+
- VERSION.yml
|
41
|
+
- bitmask-attribute.gemspec
|
42
|
+
- lib/bitmask-attribute.rb
|
43
|
+
- lib/bitmask_attribute.rb
|
44
|
+
- lib/bitmask_attribute/value_proxy.rb
|
45
|
+
- rails/init.rb
|
46
|
+
- test/bitmask_attribute_test.rb
|
47
|
+
- test/test_helper.rb
|
48
|
+
has_rdoc: true
|
49
|
+
homepage: http://github.com/bruce/bitmask-attribute
|
50
|
+
licenses: []
|
51
|
+
|
52
|
+
post_install_message:
|
53
|
+
rdoc_options:
|
54
|
+
- --charset=UTF-8
|
55
|
+
require_paths:
|
56
|
+
- lib
|
57
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: "0"
|
62
|
+
version:
|
63
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
version:
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.3.5
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Simple bitmask attribute support for ActiveRecord
|
76
|
+
test_files:
|
77
|
+
- test/bitmask_attribute_test.rb
|
78
|
+
- test/test_helper.rb
|