Created
January 21, 2010 18:24
-
-
Save brianjlandau/283033 to your computer and use it in GitHub Desktop.
acts_as_flagable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module ActiveRecord | |
module Acts | |
module AsFlagable | |
def self.included(base) | |
base.extend ClassMethods | |
end | |
module ClassMethods | |
def acts_as_flagable(options, flagable_column = 'flags') | |
unless flagable? | |
cattr_accessor :flag_column_name | |
self.flag_column_name = flagable_column | |
cattr_accessor :flag_values | |
self.flag_values = options | |
cattr_accessor :flag_names | |
self.flag_names = options.keys.map(&:to_s) | |
before_validation :set_flag_mask | |
attr_accessor *options.keys | |
options.each_key do |flag| | |
define_method "#{flag}?" do | |
@attributes[flag_column_name.to_s] ||= 0 # Hack because shoulda in some cases sets this to nil causing tests to fail. | |
(self.send(flag_column_name.to_sym) & flag_values[flag]) == flag_values[flag] | |
end | |
end | |
include InstanceMethods | |
end | |
end | |
def flagable? | |
self.included_modules.include?(InstanceMethods) | |
end | |
end | |
module InstanceMethods | |
def after_initialize | |
# Make sure we correctly set the flags when we retrieve a record. | |
unless new_record? | |
flag_values.each_key do |flag| | |
if self.send("#{flag}?".to_sym) | |
self.send("#{flag}=".to_sym, true) | |
else | |
self.send("#{flag}=".to_sym, false) | |
end | |
end | |
end | |
end | |
private | |
def set_flag_mask | |
# correctly transfer all flags to the bitmask | |
self.send("#{flag_column_name}=".to_sym, 0) | |
flag_values.each do |flag, value| | |
if ConnectionAdapters::Column.value_to_boolean(self.send(flag)) | |
self.send("#{flag_column_name}=".to_sym, (self.send(flag_column_name.to_sym) | value)) | |
end | |
end | |
end | |
end | |
end | |
end | |
end | |
ActiveRecord::Base.send(:include, ActiveRecord::Acts::AsFlagable) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ActiveSupport::TestCase | |
def self.should_be_flagable(flags, flag_column = "flags") | |
should_have_instance_methods flag_column, "#{flag_column}=" | |
should 'have a flag column' do | |
assert self.class.described_type.column_names.include?(flag_column.to_s) | |
end | |
should 'have a flag_values class method' do | |
assert_equal flags, self.class.described_type.flag_values | |
end | |
should 'have a flag_names class method with all flag names' do | |
assert_same_elements flags.keys.map(&:to_s), self.class.described_type.flag_names | |
end | |
should 'be flagable?' do | |
assert self.class.described_type.flagable? | |
end | |
flags.each do|flag, value| | |
should_have_instance_methods "#{flag}", "#{flag}=", "#{flag}?" | |
should "correctly set the #{flag} instance variable to true on initiation" do | |
subject.send("#{flag}=", "1") | |
subject.save! | |
found_record = self.class.described_type.find(subject.id) | |
assert found_record.send(flag.to_sym) | |
end | |
should "correctly set the #{flag} instance variable to false on initiation" do | |
subject.send("#{flag}=", "0") | |
subject.save! | |
found_record = self.class.described_type.find(subject.id) | |
assert !found_record.send(flag.to_sym) | |
end | |
should "correctly return true for #{flag}?" do | |
subject.send("#{flag}=", "1") | |
subject.save! | |
found_record = self.class.described_type.find(subject.id) | |
assert found_record.send("#{flag}?".to_sym) | |
end | |
should "correctly return false for #{flag}?" do | |
subject.send("#{flag}=", "0") | |
subject.save! | |
found_record = self.class.described_type.find(subject.id) | |
assert !found_record.send("#{flag}?".to_sym) | |
end | |
should "correctly return true for #{flag}? after save using update attributes" do | |
subject.update_attributes(flag => "1") | |
subject.save! | |
assert subject.send("#{flag}?".to_sym) | |
end | |
should "correctly return false for #{flag}? after save using update attributes" do | |
subject.update_attributes(flag => "0") | |
subject.save! | |
assert !subject.send("#{flag}?".to_sym) | |
end | |
should "correctly return true for #{flag}? after failed save on new record" do | |
new_record = self.class.described_type.new(flag => "1") | |
new_record.save | |
assert new_record.send("#{flag}?".to_sym) | |
end | |
should "correctly return false for #{flag}? after failed save on new record" do | |
new_record = self.class.described_type.new(flag => "0") | |
new_record.save | |
assert !new_record.send("#{flag}?".to_sym) | |
end | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment