Skip to content
This repository has been archived by the owner on Jun 16, 2020. It is now read-only.

Commit

Permalink
add :zero option and tests
Browse files Browse the repository at this point in the history
  • Loading branch information
spemmons committed Apr 16, 2012
1 parent 10be48b commit 2ec24c8
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 11 deletions.
2 changes: 1 addition & 1 deletion lib/bitmask_attributes.rb
Expand Up @@ -9,7 +9,7 @@ def bitmask(attribute, options={}, &extension)
unless options[:as] && options[:as].kind_of?(Array)
raise ArgumentError, "Must provide an Array :as option"
end
bitmask_definitions[attribute] = Definition.new(attribute, options[:as].to_a,options[:null].nil? || options[:null], &extension)
bitmask_definitions[attribute] = Definition.new(attribute, options[:as].to_a,options[:null].nil? || options[:null],options[:zero],&extension)
bitmask_definitions[attribute].install_on(self)
end

Expand Down
20 changes: 12 additions & 8 deletions lib/bitmask_attributes/definition.rb
@@ -1,12 +1,13 @@
module BitmaskAttributes
class Definition
attr_reader :attribute, :values, :allow_null, :extension
attr_reader :attribute, :values, :allow_null, :zero_value, :extension

def initialize(attribute, values=[],allow_null = true, &extension)
def initialize(attribute, values=[],allow_null = true,zero_value = nil, &extension)
@attribute = attribute
@values = values
@extension = extension
@allow_null = allow_null
@zero_value = zero_value
end

def install_on(model)
Expand Down Expand Up @@ -57,7 +58,7 @@ def override_setter_on(model)
model.class_eval %(
def #{attribute}=(raw_value)
values = raw_value.kind_of?(Array) ? raw_value : [raw_value]
self.#{attribute}.replace(values.reject(&:blank?))
self.#{attribute}.replace(values.reject{|value| #{eval_string_for_zero('value')}})
end
)
end
Expand All @@ -75,7 +76,9 @@ def create_convenience_class_method_on(model)
model.class_eval %(
def self.bitmask_for_#{attribute}(*values)
values.inject(0) do |bitmask, value|
unless (bit = bitmasks[:#{attribute}][value])
if #{eval_string_for_zero('value')}
bit = 0
elsif (bit = bitmasks[:#{attribute}][value]).nil?
raise ArgumentError, "Unsupported value for #{attribute}: \#{value.inspect}"
end
bitmask | bit
Expand Down Expand Up @@ -106,10 +109,7 @@ def #{attribute}?(*values)
end

def create_scopes_on(model)
if allow_null
or_is_null_condition = " OR #{attribute} IS NULL"
or_is_not_null_condition = " OR #{attribute} IS NOT NULL"
end
or_is_null_condition = " OR #{attribute} IS NULL" if allow_null

model.class_eval %(
scope :with_#{attribute},
Expand Down Expand Up @@ -160,5 +160,9 @@ def create_scopes_on(model)
)
end
end

def eval_string_for_zero(value_string)
zero_value ? "#{value_string}.blank? || #{value_string} == :#{zero_value}" : "#{value_string}.blank?"
end
end
end
18 changes: 18 additions & 0 deletions test/bitmask_attributes_test.rb
Expand Up @@ -105,6 +105,7 @@ def self.context_with_classes(label,campaign_class,company_class)
end

should "ignore blanks fed as values" do
assert_equal 0b11,@campaign_class.bitmask_for_medium(:web, :print, '')
campaign = @campaign_class.new(:medium => [:web, :print, ''])
assert_stored campaign, :web, :print
end
Expand Down Expand Up @@ -232,6 +233,23 @@ def self.context_with_classes(label,campaign_class,company_class)
assert_equal [campaign], @campaign_class.no_medium
end

should "allow zero in values without changing result" do
assert_equal 0,@campaign_class.bitmask_for_allow_zero(:none)
assert_equal 0b111,@campaign_class.bitmask_for_allow_zero(:one,:two,:three,:none)

campaign = @campaign_class.new(:allow_zero => :none)
assert campaign.save
assert_equal [],campaign.allow_zero

campaign.allow_zero = :none
assert campaign.save
assert_equal [],campaign.allow_zero

campaign.allow_zero = [:one,:none]
assert campaign.save
assert_equal [:one],campaign.allow_zero
end


private

Expand Down
6 changes: 4 additions & 2 deletions test/support/models.rb
@@ -1,14 +1,14 @@
ActiveRecord::Schema.define do
create_table :campaign_with_nulls do |t|
t.integer :company_id
t.integer :medium, :misc, :Legacy
t.integer :medium, :allow_zero, :misc, :Legacy
end
create_table :company_with_nulls do |t|
t.string :name
end
create_table :campaign_without_nulls do |t|
t.integer :company_id
t.integer :medium, :misc, :Legacy, :null => false, :default => 0
t.integer :medium, :allow_zero, :misc, :Legacy, :null => false, :default => 0
end
create_table :company_without_nulls do |t|
t.string :name
Expand All @@ -24,6 +24,7 @@ class CompanyWithNull < ActiveRecord::Base
class CampaignWithNull < ActiveRecord::Base
belongs_to :company,:class_name => 'CompanyWithNull'
bitmask :medium, :as => [:web, :print, :email, :phone]
bitmask :allow_zero, :as => [:one, :two, :three], :zero => :none
bitmask :misc, :as => %w(some useless values) do
def worked?
true
Expand All @@ -39,6 +40,7 @@ class CompanyWithoutNull < ActiveRecord::Base
class CampaignWithoutNull < ActiveRecord::Base
belongs_to :company,:class_name => 'CompanyWithoutNull'
bitmask :medium, :as => [:web, :print, :email, :phone], :null => false
bitmask :allow_zero, :as => [:one, :two, :three], :zero => :none, :null => false
bitmask :misc, :as => %w(some useless values), :null => false do
def worked?
true
Expand Down

0 comments on commit 2ec24c8

Please sign in to comment.