gabrielhase-bitmask-attribute 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.markdown
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
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,117 @@
1
+ bitmask-attribute
2
+ =================
3
+
4
+ Transparent manipulation of bitmask attributes.
5
+
6
+ About this Fork
7
+ ---------------
8
+ This Fork is just a little tweak to bruce/bitmask_attribute in order to replace the depreciated Kernel#returning function.
9
+
10
+ Example
11
+ -------
12
+
13
+ Simply declare an existing integer column as a bitmask with its possible
14
+ values.
15
+
16
+ class User < ActiveRecord::Base
17
+ bitmask :roles, :as => [:writer, :publisher, :editor, :proofreader]
18
+ end
19
+
20
+ You can then modify the column using the declared values without resorting
21
+ to manual bitmasks.
22
+
23
+ user = User.create(:name => "Bruce", :roles => [:publisher, :editor])
24
+ user.roles
25
+ # => [:publisher, :editor]
26
+ user.roles << :writer
27
+ user.roles
28
+ # => [:publisher, :editor, :writer]
29
+
30
+ It's easy to find out if a record has a given value:
31
+
32
+ user.roles?(:editor)
33
+ # => true
34
+
35
+ You can check for multiple values (uses an `and` boolean):
36
+
37
+ user.roles?(:editor, :publisher)
38
+ # => true
39
+ user.roles?(:editor, :proofreader)
40
+ # => false
41
+
42
+ Or, just check if any values are present:
43
+
44
+ user.roles?
45
+ # => true
46
+
47
+ Named Scopes
48
+ ------------
49
+
50
+ A couple useful named scopes are also generated when you use
51
+ `bitmask`:
52
+
53
+ User.with_roles
54
+ # => (all users with roles)
55
+ User.with_roles(:editor)
56
+ # => (all editors)
57
+ User.with_roles(:editor, :writer)
58
+ # => (all users who are BOTH editors and writers)
59
+
60
+ Later we'll support an `or` boolean; for now, do something like:
61
+
62
+ User.with_roles(:editor) + User.with_roles(:writer)
63
+ # => (all users who are EITHER editors and writers)
64
+
65
+ Find records without any bitmask set:
66
+
67
+ User.without_roles
68
+ # => (all users without a role)
69
+
70
+ Later we'll support finding records without a specific bitmask.
71
+
72
+ Adding Methods
73
+ --------------
74
+
75
+ You can add your own methods to the bitmasked attributes (similar to
76
+ named scopes):
77
+
78
+ bitmask :other_attribute, :as => [:value1, :value2] do
79
+ def worked?
80
+ true
81
+ end
82
+ end
83
+
84
+ user = User.first
85
+ user.other_attribute.worked?
86
+ # => true
87
+
88
+
89
+ Warning: Modifying possible values
90
+ ----------------------------------
91
+
92
+ IMPORTANT: Once you have data using a bitmask, don't change the order
93
+ of the values, remove any values, or insert any new values in the `:as`
94
+ array anywhere except at the end. You won't like the results.
95
+
96
+ Contributing and reporting issues
97
+ ---------------------------------
98
+
99
+ Please feel free to fork & contribute fixes via GitHub pull requests.
100
+ The official repository for this project is
101
+ http://github.com/bruce/bitmask-attribute
102
+
103
+ Issues can be reported at
104
+ http://github.com/bruce/bitmask-attribute/issues
105
+
106
+ Credits
107
+ -------
108
+
109
+ Thanks to the following contributors:
110
+
111
+ * [Jason L Perry](http://github.com/ambethia)
112
+ * [Nicolas Fouché](http://github.com/nfo)
113
+
114
+ Copyright
115
+ ---------
116
+
117
+ 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 = "gabrielhase-bitmask-attribute"
8
+ gem.summary = %Q{Simple bitmask attribute support for ActiveRecord. Forked from bruce/bitmask_attribute for Rails 2.3.11 support.}
9
+ gem.email = "gabriel.hase@gmail.com"
10
+ gem.homepage = "http://github.com/gabrielhase/bitmask-attribute"
11
+ gem.authors = ["Bruce Williams, Gabriel Hase"]
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 ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
@@ -0,0 +1,2 @@
1
+ # Stub for dash-style requires
2
+ require File.dirname(__FILE__) << "/bitmask_attribute"
@@ -0,0 +1,154 @@
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_class_method_on(model)
19
+ create_convenience_instance_methods_on(model)
20
+ create_named_scopes_on(model)
21
+ end
22
+
23
+ #######
24
+ private
25
+ #######
26
+
27
+ def validate_for(model)
28
+ # The model cannot be validated if it is preloaded and the attribute/column is not in the
29
+ # database (the migration has not been run). This usually
30
+ # occurs in the 'test' and 'production' environments.
31
+ return if defined?(Rails) && Rails.configuration.cache_classes
32
+
33
+ unless model.columns.detect { |col| col.name == attribute.to_s }
34
+ raise ArgumentError, "`#{attribute}' is not an attribute of `#{model}'"
35
+ end
36
+ end
37
+
38
+ def generate_bitmasks_on(model)
39
+ model.bitmasks[attribute] = HashWithIndifferentAccess.new.tap do |mapping|
40
+ values.each_with_index do |value, index|
41
+ mapping[value] = 0b1 << index
42
+ end
43
+ end
44
+ end
45
+
46
+ def override(model)
47
+ override_getter_on(model)
48
+ override_setter_on(model)
49
+ end
50
+
51
+ def override_getter_on(model)
52
+ model.class_eval %(
53
+ def #{attribute}
54
+ @#{attribute} ||= BitmaskAttribute::ValueProxy.new(self, :#{attribute}, &self.class.bitmask_definitions[:#{attribute}].extension)
55
+ end
56
+ )
57
+ end
58
+
59
+ def override_setter_on(model)
60
+ model.class_eval %(
61
+ def #{attribute}=(raw_value)
62
+ values = raw_value.kind_of?(Array) ? raw_value : [raw_value]
63
+ self.#{attribute}.replace(values.reject(&:blank?))
64
+ end
65
+ )
66
+ end
67
+
68
+ def create_convenience_class_method_on(model)
69
+ model.class_eval %(
70
+ def self.bitmask_for_#{attribute}(*values)
71
+ values.inject(0) do |bitmask, value|
72
+ unless (bit = bitmasks[:#{attribute}][value])
73
+ raise ArgumentError, "Unsupported value for #{attribute}: \#{value.inspect}"
74
+ end
75
+ bitmask | bit
76
+ end
77
+ end
78
+ )
79
+ end
80
+
81
+
82
+ def create_convenience_instance_methods_on(model)
83
+ values.each do |value|
84
+ model.class_eval %(
85
+ def #{attribute}_for_#{value}?
86
+ self.#{attribute}?(:#{value})
87
+ end
88
+ )
89
+ end
90
+ model.class_eval %(
91
+ def #{attribute}?(*values)
92
+ if !values.blank?
93
+ values.all? do |value|
94
+ self.#{attribute}.include?(value)
95
+ end
96
+ else
97
+ self.#{attribute}.present?
98
+ end
99
+ end
100
+ )
101
+ end
102
+
103
+ def create_named_scopes_on(model)
104
+ model.class_eval %(
105
+ named_scope :with_#{attribute},
106
+ proc { |*values|
107
+ if values.blank?
108
+ {:conditions => '#{attribute} > 0 OR #{attribute} IS NOT NULL'}
109
+ else
110
+ sets = values.map do |value|
111
+ mask = #{model}.bitmask_for_#{attribute}(value)
112
+ "#{attribute} & \#{mask} <> 0"
113
+ end
114
+ {:conditions => sets.join(' AND ')}
115
+ end
116
+ }
117
+ named_scope :without_#{attribute}, :conditions => "#{attribute} == 0 OR #{attribute} IS NULL"
118
+ named_scope :no_#{attribute}, :conditions => "#{attribute} == 0 OR #{attribute} IS NULL"
119
+ )
120
+ values.each do |value|
121
+ model.class_eval %(
122
+ named_scope :#{attribute}_for_#{value},
123
+ :conditions => ['#{attribute} & ? <> 0', #{model}.bitmask_for_#{attribute}(:#{value})]
124
+ )
125
+ end
126
+ end
127
+
128
+ end
129
+
130
+ def self.included(model)
131
+ model.extend ClassMethods
132
+ end
133
+
134
+ module ClassMethods
135
+
136
+ def bitmask(attribute, options={}, &extension)
137
+ unless options[:as] && options[:as].kind_of?(Array)
138
+ raise ArgumentError, "Must provide an Array :as option"
139
+ end
140
+ bitmask_definitions[attribute] = BitmaskAttribute::Definition.new(attribute, options[:as].to_a, &extension)
141
+ bitmask_definitions[attribute].install_on(self)
142
+ end
143
+
144
+ def bitmask_definitions
145
+ @bitmask_definitions ||= {}
146
+ end
147
+
148
+ def bitmasks
149
+ @bitmasks ||= {}
150
+ end
151
+
152
+ end
153
+
154
+ 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
+ (super).tap 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, 0].max
57
+ @mapping.inject([]) do |values, (value, bitmask)|
58
+ values.tap 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
data/rails/init.rb ADDED
@@ -0,0 +1,3 @@
1
+ ActiveRecord::Base.instance_eval do
2
+ include BitmaskAttribute
3
+ end
@@ -0,0 +1,216 @@
1
+ require 'test_helper'
2
+
3
+ class BitmaskAttributeTest < Test::Unit::TestCase
4
+
5
+ context "Campaign" do
6
+
7
+ teardown do
8
+ Company.destroy_all
9
+ Campaign.destroy_all
10
+ end
11
+
12
+ should "can assign single value to bitmask" do
13
+ assert_stored Campaign.new(:medium => :web), :web
14
+ end
15
+
16
+ should "can assign multiple values to bitmask" do
17
+ assert_stored Campaign.new(:medium => [:web, :print]), :web, :print
18
+ end
19
+
20
+ should "can add single value to bitmask" do
21
+ campaign = Campaign.new(:medium => [:web, :print])
22
+ assert_stored campaign, :web, :print
23
+ campaign.medium << :phone
24
+ assert_stored campaign, :web, :print, :phone
25
+ end
26
+
27
+ should "ignores duplicate values added to bitmask" do
28
+ campaign = Campaign.new(:medium => [:web, :print])
29
+ assert_stored campaign, :web, :print
30
+ campaign.medium << :phone
31
+ assert_stored campaign, :web, :print, :phone
32
+ campaign.medium << :phone
33
+ assert_stored campaign, :web, :print, :phone
34
+ assert_equal 1, campaign.medium.select { |value| value == :phone }.size
35
+ end
36
+
37
+ should "can assign new values at once to bitmask" do
38
+ campaign = Campaign.new(:medium => [:web, :print])
39
+ assert_stored campaign, :web, :print
40
+ campaign.medium = [:phone, :email]
41
+ assert_stored campaign, :phone, :email
42
+ end
43
+
44
+ should "can save bitmask to db and retrieve values transparently" do
45
+ campaign = Campaign.new(:medium => [:web, :print])
46
+ assert_stored campaign, :web, :print
47
+ assert campaign.save
48
+ assert_stored Campaign.find(campaign.id), :web, :print
49
+ end
50
+
51
+ should "can add custom behavor to value proxies during bitmask definition" do
52
+ campaign = Campaign.new(:medium => [:web, :print])
53
+ assert_raises NoMethodError do
54
+ campaign.medium.worked?
55
+ end
56
+ assert_nothing_raised do
57
+ campaign.misc.worked?
58
+ end
59
+ assert campaign.misc.worked?
60
+ end
61
+
62
+ should "cannot use unsupported values" do
63
+ assert_unsupported { Campaign.new(:medium => [:web, :print, :this_will_fail]) }
64
+ campaign = Campaign.new(:medium => :web)
65
+ assert_unsupported { campaign.medium << :this_will_fail_also }
66
+ assert_unsupported { campaign.medium = [:so_will_this] }
67
+ end
68
+
69
+ should "can determine bitmasks using convenience method" do
70
+ assert Campaign.bitmask_for_medium(:web, :print)
71
+ assert_equal(
72
+ Campaign.bitmasks[:medium][:web] | Campaign.bitmasks[:medium][:print],
73
+ Campaign.bitmask_for_medium(:web, :print)
74
+ )
75
+ end
76
+
77
+ should "assert use of unknown value in convenience method will result in exception" do
78
+ assert_unsupported { Campaign.bitmask_for_medium(:web, :and_this_isnt_valid) }
79
+ end
80
+
81
+ should "hash of values is with indifferent access" do
82
+ string_bit = nil
83
+ assert_nothing_raised do
84
+ assert (string_bit = Campaign.bitmask_for_medium('web', 'print'))
85
+ end
86
+ assert_equal Campaign.bitmask_for_medium(:web, :print), string_bit
87
+ end
88
+
89
+ should "save bitmask with non-standard attribute names" do
90
+ campaign = Campaign.new(:Legacy => [:upper, :case])
91
+ assert campaign.save
92
+ assert_equal [:upper, :case], Campaign.find(campaign.id).Legacy
93
+ end
94
+
95
+ should "ignore blanks fed as values" do
96
+ campaign = Campaign.new(:medium => [:web, :print, ''])
97
+ assert_stored campaign, :web, :print
98
+ end
99
+
100
+ context "checking" do
101
+
102
+ setup { @campaign = Campaign.new(:medium => [:web, :print]) }
103
+
104
+ context "for a single value" do
105
+
106
+ should "be supported by an attribute_for_value convenience method" do
107
+ assert @campaign.medium_for_web?
108
+ assert @campaign.medium_for_print?
109
+ assert !@campaign.medium_for_email?
110
+ end
111
+
112
+ should "be supported by the simple predicate method" do
113
+ assert @campaign.medium?(:web)
114
+ assert @campaign.medium?(:print)
115
+ assert !@campaign.medium?(:email)
116
+ end
117
+
118
+ end
119
+
120
+ context "for multiple values" do
121
+
122
+ should "be supported by the simple predicate method" do
123
+ assert @campaign.medium?(:web, :print)
124
+ assert !@campaign.medium?(:web, :email)
125
+ end
126
+
127
+ end
128
+
129
+ end
130
+
131
+ context "named scopes" do
132
+
133
+ setup do
134
+ @company = Company.create(:name => "Test Co, Intl.")
135
+ @campaign1 = @company.campaigns.create :medium => [:web, :print]
136
+ @campaign2 = @company.campaigns.create
137
+ @campaign3 = @company.campaigns.create :medium => [:web, :email]
138
+ end
139
+
140
+ should "support retrieval by any value" do
141
+ assert_equal [@campaign1, @campaign3], @company.campaigns.with_medium
142
+ end
143
+
144
+ should "support retrieval by one matching value" do
145
+ assert_equal [@campaign1], @company.campaigns.with_medium(:print)
146
+ end
147
+
148
+ should "support retrieval by all matching values" do
149
+ assert_equal [@campaign1], @company.campaigns.with_medium(:web, :print)
150
+ assert_equal [@campaign3], @company.campaigns.with_medium(:web, :email)
151
+ end
152
+
153
+ should "support retrieval for no values" do
154
+ assert_equal [@campaign2], @company.campaigns.without_medium
155
+ end
156
+
157
+ end
158
+
159
+ should "can check if at least one value is set" do
160
+ campaign = Campaign.new(:medium => [:web, :print])
161
+
162
+ assert campaign.medium?
163
+
164
+ campaign = Campaign.new
165
+
166
+ assert !campaign.medium?
167
+ end
168
+
169
+ should "find by bitmask values" do
170
+ campaign = Campaign.new(:medium => [:web, :print])
171
+ assert campaign.save
172
+
173
+ assert_equal(
174
+ Campaign.find(:all, :conditions => ['medium & ? <> 0', Campaign.bitmask_for_medium(:print)]),
175
+ Campaign.medium_for_print
176
+ )
177
+
178
+ assert_equal Campaign.medium_for_print, Campaign.medium_for_print.medium_for_web
179
+
180
+ assert_equal [], Campaign.medium_for_email
181
+ assert_equal [], Campaign.medium_for_web.medium_for_email
182
+ end
183
+
184
+ should "find no values" do
185
+ campaign = Campaign.create(:medium => [:web, :print])
186
+ assert campaign.save
187
+
188
+ assert_equal [], Campaign.no_medium
189
+
190
+ campaign.medium = []
191
+ assert campaign.save
192
+
193
+ assert_equal [campaign], Campaign.no_medium
194
+ end
195
+
196
+ #######
197
+ private
198
+ #######
199
+
200
+ def assert_unsupported(&block)
201
+ assert_raises(ArgumentError, &block)
202
+ end
203
+
204
+ def assert_stored(record, *values)
205
+ values.each do |value|
206
+ assert record.medium.any? { |v| v.to_s == value.to_s }, "Values #{record.medium.inspect} does not include #{value.inspect}"
207
+ end
208
+ full_mask = values.inject(0) do |mask, value|
209
+ mask | Campaign.bitmasks[:medium][value]
210
+ end
211
+ assert_equal full_mask, record.medium.to_i
212
+ end
213
+
214
+ end
215
+
216
+ end
@@ -0,0 +1,66 @@
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.logger = Logger.new(STDOUT)
18
+
19
+ ActiveRecord::Base.establish_connection(
20
+ :adapter => 'sqlite3',
21
+ :database => ':memory:'
22
+ )
23
+
24
+ ActiveRecord::Schema.define do
25
+ create_table :campaigns do |t|
26
+ t.integer :company_id
27
+ t.integer :medium, :misc, :Legacy
28
+ end
29
+ create_table :companies do |t|
30
+ t.string :name
31
+ end
32
+ end
33
+
34
+ class Company < ActiveRecord::Base
35
+ has_many :campaigns
36
+ end
37
+
38
+ # Pseudo model for testing purposes
39
+ class Campaign < ActiveRecord::Base
40
+ belongs_to :company
41
+ bitmask :medium, :as => [:web, :print, :email, :phone]
42
+ bitmask :misc, :as => %w(some useless values) do
43
+ def worked?
44
+ true
45
+ end
46
+ end
47
+ bitmask :Legacy, :as => [:upper, :case]
48
+ end
49
+
50
+ class Test::Unit::TestCase
51
+
52
+ def assert_unsupported(&block)
53
+ assert_raises(ArgumentError, &block)
54
+ end
55
+
56
+ def assert_stored(record, *values)
57
+ values.each do |value|
58
+ assert record.medium.any? { |v| v.to_s == value.to_s }, "Values #{record.medium.inspect} does not include #{value.inspect}"
59
+ end
60
+ full_mask = values.inject(0) do |mask, value|
61
+ mask | Campaign.bitmasks[:medium][value]
62
+ end
63
+ assert_equal full_mask, record.medium.to_i
64
+ end
65
+
66
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gabrielhase-bitmask-attribute
3
+ version: !ruby/object:Gem::Version
4
+ hash: 31
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 0
10
+ version: 0.0.0
11
+ platform: ruby
12
+ authors:
13
+ - Bruce Williams, Gabriel Hase
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-05-17 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activerecord
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ description:
35
+ email: gabriel.hase@gmail.com
36
+ executables: []
37
+
38
+ extensions: []
39
+
40
+ extra_rdoc_files:
41
+ - LICENSE
42
+ - README.markdown
43
+ files:
44
+ - .document
45
+ - LICENSE
46
+ - README.markdown
47
+ - Rakefile
48
+ - VERSION
49
+ - lib/bitmask-attribute.rb
50
+ - lib/bitmask_attribute.rb
51
+ - lib/bitmask_attribute/value_proxy.rb
52
+ - rails/init.rb
53
+ - test/bitmask_attribute_test.rb
54
+ - test/test_helper.rb
55
+ homepage: http://github.com/gabrielhase/bitmask-attribute
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project:
84
+ rubygems_version: 1.7.2
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Simple bitmask attribute support for ActiveRecord. Forked from bruce/bitmask_attribute for Rails 2.3.11 support.
88
+ test_files:
89
+ - test/bitmask_attribute_test.rb
90
+ - test/test_helper.rb