class ActiveRecord::Base
Public Class Methods
binary_attributes(attributes, flags_attribute = :flags)
click to toggle source
Allows you to conserve space by storing several boolean attributes to one integer attribute.
class Building < ActiveRecord::Base flag_attributes( "overdriven" => 0b00000001, "with_points" => 0b00000010 ) end
or something shorter
class Building < ActiveRecord::Base binary_attributes :overdriven, :with_points end b = Building.new b.overdriven = true b.overdriven? => true b.with_points? => false b.with_points = true b.flags => 3
# File lib/ar_binary_flag_attributes.rb, line 31 def self.binary_attributes(attributes, flags_attribute = :flags) hash_attr = Hash.new attributes.each_with_index do |key, i| hash_attr[key] = 2 ** i end flag_attributes(hash_attr, flags_attribute) end
flag_attributes(attributes, flags_attribute = :flags)
click to toggle source
# File lib/ar_binary_flag_attributes.rb, line 40 def self.flag_attributes(attributes, flags_attribute = :flags) # Calculate the full mask to be able to unset bits. full_mask = attributes.inject(0) { |full_mask, (_, mask)| full_mask | mask } get_flags = flags_attribute.to_sym set_flags = :"#{flags_attribute}=" attributes.each do |method_name, mask| get_method = :"#{method_name}?" set_method = :"#{method_name}=" # Check if bit is set in mask. define_method(get_method) { send(get_flags) & mask == mask } alias_method method_name, get_method # Set bit value. define_method(set_method) do |value| # rails fix if value and not value.to_s == '0' # Set bit in flags. This is done using or operation: # # 0b010101 | 0b010101 | # 0b001000 = 0b010000 = # 0b011101 0b010101 send(set_flags, send(get_flags) | mask) else # Unset bit in flags. First we invert the full mask: # # 0b111111 ^ # 0b000100 = # 0b111011 # # Then we clear the bit: # # 0b010101 & # 0b111011 = # 0b010001 send(set_flags, send(get_flags) & (full_mask ^ mask)) end self end end end