class Randumb::Syntax

Public Class Methods

random_order_clause(opts={}) click to toggle source

builds the order clause to be appended in where clause

# File lib/randumb/syntax.rb, line 6
def random_order_clause(opts={})
  random_for(opts)
end
random_weighted_order_clause(ranking_column, opts={}) click to toggle source

builds the order clause to be appended in where clause

# File lib/randumb/syntax.rb, line 11
def random_weighted_order_clause(ranking_column, opts={})
  connection = opts[:connection]

  if connection.adapter_name =~ /sqlite/i
    # computer multiplication is faster than division I was once taught...so translate here
    max_int = 9223372036854775807.0
    multiplier = 1.0 / max_int
    "(#{ranking_column} * ABS(#{random_for(opts)} * #{multiplier}) ) DESC"
  else
    "(#{ranking_column} * #{random_for(opts)}) DESC"
  end
end

Private Class Methods

random_for(opts) click to toggle source

sligtly different for each DB

# File lib/randumb/syntax.rb, line 27
def random_for(opts)
  connection = opts[:connection]
  adapter_name = connection.adapter_name
  if adapter_name =~ /(sqlite)/i
    random_for_sqlite(opts)
  elsif adapter_name =~ /(postgres|postgis)/i
    random_for_postgres(opts)
  elsif adapter_name =~ /mysql/i
    random_for_mysql(opts)
  else
    raise Exception, "ActiveRecord adapter: '#{adapter_name}' not supported by randumb.  Send a pull request or open a ticket: https://github.com/spilliton/randumb"
  end
end
random_for_mysql(opts) click to toggle source
# File lib/randumb/syntax.rb, line 72
def random_for_mysql(opts)
  if seed = opts[:seed]
    "RAND(#{seed.to_i})"
  else
    "RAND()"
  end
end
random_for_postgres(opts) click to toggle source
# File lib/randumb/syntax.rb, line 56
def random_for_postgres(opts)
  # Postgres random seeding requires executing an extra "SELECT SETSEED(value)" on the connection.
  # See http://www.postgresql.org/docs/8.3/static/sql-set.html:
  #
  #     Sets the internal seed for the random number generator (the
  #     function random). Allowed values are floating-point numbers
  #     between 0 and 1, which are then multiplied by 2^(31)-1.
  #
  if seed = opts[:seed]
    connection = opts[:connection]
    seed_value = Random.new(seed.to_i).rand # map integer seed to a value: 0 <= value < 1
    connection.execute "SELECT SETSEED(#{seed_value})"
  end
  "RANDOM()"
end
random_for_sqlite(opts) click to toggle source
# File lib/randumb/syntax.rb, line 41
def random_for_sqlite(opts)
  if seed = opts[:seed]
    table_name = opts[:table_name]
    # SQLLite does not support a random seed.  However, pseudo-randomness
    # can be achieved by sorting on a hash of the id field (generated by
    # multiplying the id by the random seed and ignoring everything before
    # the decimal).
    # See http://stackoverflow.com/questions/2171578/seeding-sqlite-random
    seed_value = Random.new(seed.to_i).rand
    "(SUBSTR(#{table_name}.id * #{seed_value}, LENGTH(#{table_name}.id) + 2))"
  else
    "RANDOM()"
  end
end