class Bisque::Report

Attributes

params[RW]
sql[RW]

Public Class Methods

new(params={}) click to toggle source
# File lib/bisque/report.rb, line 7
def initialize(params={})
  @params = self.class.defaults.merge params
  @params.each do |k,v|
    @params[k] = instance_eval(&v) if v.is_a?(Proc)
  end
  @sql = self.class.query.dup
  self.class.params.each do |param|
    value = @params[param]
    raise Bisque::MissingParameterException, "Missing parameter :#{param} for construction of #{self.class} - please provide a value for this parameter to the constructor or define a default." if value.nil? && !self.class.optional.include?(param.intern)
    @sql.gsub!(/(?<!:):#{param}/, sanitize_and_sqlize(value))
  end
  self.class.method_params.each do |param|
    raise Bisque::MissingParameterException, "Missing method :#{param} for construction of #{self.class} - please define a method for this parameter." unless respond_to?(param)
    @sql.gsub!(/(?<!:):##{param}/, sanitize_and_sqlize(send(param)))
  end
  @results = ActiveRecord::Base.connection.execute @sql
  extract_datatypes
  construct_converted
end

Protected Class Methods

default(key, val=nil, &block) click to toggle source
# File lib/bisque/report.rb, line 105
def default(key, val=nil, &block)
  @defaults ||= {}
  @defaults[key] = val || block
end
defaults(hash=nil) click to toggle source
# File lib/bisque/report.rb, line 110
def defaults(hash=nil)
  if hash
    @defaults ||= {}
    @defaults.merge! hash
  else
    @defaults || {}
  end
end
method_params() click to toggle source
# File lib/bisque/report.rb, line 162
def method_params
  @method_params || []
end
optional(*keys) click to toggle source
# File lib/bisque/report.rb, line 119
def optional(*keys)
  if keys
    @optionals ||= []
    @optionals = (@optionals + keys).uniq
  else
    @optionals || []
  end
end
params() click to toggle source
# File lib/bisque/report.rb, line 158
def params
  @params || []
end
query(qstr=nil) click to toggle source
# File lib/bisque/report.rb, line 128
def query(qstr=nil)
  if qstr
    @qstr = qstr.strip
    @params = qstr.scan(/(?<!:):\w+/).map { |p| p.gsub(/:/,'').intern }
    @method_params = qstr.scan(/(?<!:):#\w+/).map { |p| p.gsub(/:#/,'').intern }
  else
    raise Bisque::MissingQueryException, "Bisque Report #{self} missing query definition." if @qstr.nil?
    @qstr
  end
end
row_class() click to toggle source
# File lib/bisque/report.rb, line 150
def row_class
  return Bisque::ReportRow if @row_class.nil?
  names = @row_class.split('::')
  names.reduce(Object) do |mod, name|
    mod.const_defined?(name) ? mod.const_get(name) : mod.const_missing(name)
  end
end
rows(&block) click to toggle source
# File lib/bisque/report.rb, line 139
def rows(&block)
  if block_given?
    carray = self.to_s.split(/::/)
    carray.last << 'Row'
    @row_class = carray.join('::')
    c =  Class.new(Bisque::ReportRow)
    c.class_eval(&block)
    Object.const_set @row_class, c
  end
end

Public Instance Methods

[](index) click to toggle source
# File lib/bisque/report.rb, line 37
def [](index)
  @converted[index]
end
each() { |r| ... } click to toggle source
# File lib/bisque/report.rb, line 27
def each
  if block_given?
    @converted.each do |r|
      yield r
    end
  else
    Enumerator.new self, :each
  end
end
last() click to toggle source
# File lib/bisque/report.rb, line 41
def last
  @converted.last
end
to_s() click to toggle source
# File lib/bisque/report.rb, line 45
def to_s
  "#{self.class}: #{count} result#{'s' if count != 1}"
end

Protected Instance Methods

construct_converted() click to toggle source
# File lib/bisque/report.rb, line 71
def construct_converted
  @converted = []
  @results.to_a.each do |r|
    @converted << self.class.row_class.new( r.merge(r) { |k, v| convert_value(k,v) })
  end
end
convert_value(key, value) click to toggle source
# File lib/bisque/report.rb, line 78
def convert_value(key, value)
  return value if value.nil?
  case @types[key.intern]
  when /integer/
    value.to_i
  when /decimal/
    value.to_f
  when /float/
    value.to_f
  when /numeric/
    value.to_f
  when /precision/
    value.to_f
  when /boolean/
    value == 't'
  when /date/
    Date.parse value
  when /timestamp/
    Time.parse value
  when /bytea/
    ActiveRecord::Base.connection.unescape_bytea(value)
  else
    value.to_s
  end
end
extract_datatypes() click to toggle source
# File lib/bisque/report.rb, line 58
def extract_datatypes
  sql = "SELECT"
  @results.fields.each_with_index do |f, i|
    sql << " UNION SELECT" if i > 0
    sql << " format_type(#{@results.ftype(i)}, #{@results.fmod(i)}) AS type, #{ActiveRecord::Base.sanitize(f)} AS key"
  end
  typeresults = ActiveRecord::Base.connection.execute(sql)
  @types = {}
  typeresults.to_a.each do |typeresult|
    @types[typeresult['key'].intern] = typeresult['type']
  end
end
sanitize_and_sqlize(value) click to toggle source
# File lib/bisque/report.rb, line 50
def sanitize_and_sqlize(value)
  if value.is_a? Array
    "(#{value.map { |v| sanitize_and_sqlize(v) }.join(",")})"
  else
    ActiveRecord::Base.connection.quote(value)
  end
end