Module: MultiBitField::ClassMethods

Defined in:
lib/multi_bit_field.rb

Instance Method Summary collapse

Instance Method Details

#bitfield_max(column_name) ⇒ Object

Returns the size of the bitfield in number of bits

+bitfield_max :column

Examples:

user.bitfield_max :counter

Parameters:

  • column_name (Symbol)

    column name that stores the bitfield integer



49
50
51
# File 'lib/multi_bit_field.rb', line 49

def bitfield_max column_name
  @@bitfields[column_name].values.sum.max
end

#bitfields(column_name) ⇒ Object

Returns the field names for the bitfield column

+bitfields

Examples:

user.bitfields :counter

Parameters:

  • column_name (Symbol)

    column name that stores the bitfield integer



62
63
64
# File 'lib/multi_bit_field.rb', line 62

def bitfields column_name
  @@bitfields[column_name].keys
end

#count_by(column_name, field) ⇒ Object

Counts resources grouped by a bitfield

+count_by :column, :fields

Examples:

user.count_by :counter, :monthly

Parameters:

  • column (Symbol)

    name of the column these fields are in

  • field(s) (Symbol)

    name of the field(s) to reset



179
180
181
182
183
184
185
186
187
# File 'lib/multi_bit_field.rb', line 179

def count_by column_name, field
  inc = increment_mask_for column_name, field
  only = only_mask_for column_name, field
  # Create super-special-bitfield-grouping-query w/ AREL
  sql = arel_table.
    project("count(#{primary_key}) as #{field}_count, (#{column_name} & #{only})/#{inc} as #{field}").
    group(field).to_sql
  connection.send :select, sql, 'AREL' # Execute the query
end

#has_bit_field(column, fields) ⇒ Object

Assign bitfields to a column

+has_bit_field :column, :fields

Examples:

class User < ActiveRecord::Base
  has_bit_field :counter, :daily => 0..4, :weekly => 5..9, :monthly => 10..14
end

Parameters:

  • column (Symbol)

    Integer attribute to store bitfields

  • fields (Hash)

    Specify the bitfield name, and the columns of the bitstring assigned to it



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/multi_bit_field.rb', line 24

def has_bit_field column, fields
  bitfield_setup! column, fields
  
  fields.each do |field_name, filum|
    class_eval <<-EVAL
      def #{field_name}
        get_bits_for(:#{column}, :#{field_name})
      end

      def #{field_name}=(value)
        set_bits_for(:#{column}, :#{field_name}, value)
      end
    EVAL
  end
end

#increment_bitfields(column_name, *fields) ⇒ Object Also known as: increment_bitfield

Increases one or more bitfields by 1 value

+increment_bitfield :column, :fields

Examples:

user.increment_bitfield :column, :daily, :monthly

Parameters:

  • column (Symbol)

    name of the column these fields are in

  • field(s) (Symbol)

    name of the field(s) to reset



164
165
166
167
# File 'lib/multi_bit_field.rb', line 164

def increment_bitfields column_name, *fields
  mask = increment_mask_for column_name, *fields
  update_all "#{column_name} = #{column_name} + #{mask}"
end

#increment_mask_for(column_name, *fields) ⇒ Object

Returns an “increment mask” for a list of fields

+increment_mask_for :fields

Examples:

user.increment_mask_for :field

Parameters:

  • column (Symbol)

    name of the column these fields are in

  • field(s) (Symbol)

    name of the field(s) for the mask

Raises:

  • (ArgumentError)


103
104
105
106
107
108
109
110
111
# File 'lib/multi_bit_field.rb', line 103

def increment_mask_for column_name, *fields
  fields = bitfields if fields.empty?
  column = @@bitfields[column_name]
  raise ArgumentError, "Unknown column for bitfield: #{column_name}" if column.nil?
  fields.sum do |field_name|
    raise ArugmentError, "Unknown field: #{field_name} for column #{column_name}" if column[field_name].nil?
    2 ** (bitfield_max(column_name) - column[field_name].last)
  end
end

#only_mask_for(column_name, *fields) ⇒ Object

Returns an “only mask” for a list of fields

+only_mask_for :fields

Examples:

user.only_mask_for :field

Parameters:

  • column (Symbol)

    name of the column these fields are in

  • field(s) (Symbol)

    name of the field(s) for the mask

Raises:

  • (ArgumentError)


122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/multi_bit_field.rb', line 122

def only_mask_for column_name, *fields
  fields = bitfields if fields.empty?
  column = @@bitfields[column_name]
  max = bitfield_max(column_name)
  raise ArgumentError, "Unknown column for bitfield: #{column_name}" if column.nil?

  column.sum do |field_name, range|
    fields.include?(field_name) ? range.invert(max).sum{|i| 2 ** i} : 0
  end
  
  # fields.inject("0" * (bitfield_max(column_name) + 1)) do |mask, field_name|
  #   raise ArugmentError, "Unknown field: #{field_name} for column #{column_name}" if column[field_name].nil?
  #   range = column[field_name]
  #   mask[range] = "1" * range.count
  #   mask
  # end.to_i(2)
end

#range_for(column_name, field_name) ⇒ Object

Returns the column by name

+column_for

Parameters:

  • column_name (Symbol)

    column name that stores the bitfield integer

Raises:

  • (ArgumentError)


72
73
74
75
76
77
# File 'lib/multi_bit_field.rb', line 72

def range_for column_name, field_name
  column = @@bitfields[column_name]
  raise ArgumentError, "Unknown column for bitfield: #{column_name}" if column.nil?
  return column[field_name] if column[field_name]
  raise ArugmentError, "Unknown field: #{field_name} for column #{column_name}"
end

#reset_bitfields(column_name, *fields) ⇒ Object Also known as: reset_bitfield

Sets one or more bitfields to 0 within a column

+reset_bitfield :column, :fields

Examples:

User.reset_bitfield :column, :daily, :monthly

Parameters:

  • column (Symbol)

    name of the column these fields are in

  • field(s) (Symbol)

    name of the field(s) to reset



149
150
151
152
# File 'lib/multi_bit_field.rb', line 149

def reset_bitfields column_name, *fields
  mask = reset_mask_for column_name, *fields
  update_all "#{column_name} = #{column_name} & #{mask}"
end

#reset_mask_for(column_name, *fields) ⇒ Object

Returns a “reset mask” for a list of fields

+reset_mask_for :fields

Examples:

user.reset_mask_for :field

Parameters:

  • column (Symbol)

    name of the column these fields are in

  • field(s) (Symbol)

    name of the field(s) for the mask



88
89
90
91
92
# File 'lib/multi_bit_field.rb', line 88

def reset_mask_for column_name, *fields
  fields = bitfields if fields.empty?
  max = bitfield_max(column_name)
  (0..max).sum{|i| 2 ** i} - only_mask_for(column_name, *fields)
end