Weighted Random

Weighted randomization extension for ActiveRecord.

Gives ability to get weighted random record from particular database relation.

Installation

Gem

gem 'weighted_random'

Model

Generate model with weight and cumulative_weight integer attributes:

rails g model your_model [your_attributes] weight:integer cumulative_weight:integer

Or add these two attributes into migration of existing model:

t.integer :weight
t.integer :cumulative_weight

Load weighted randomization stuff into desired model and set accessibillity of previous these attributes:

class YourModel < ActiveRecord::Base
  weighted_randomizable
  attr_accessible :weight, :cumulative_weight
end

Usage

Importing data

Just create records, each must contain weight value:

FirstName.create [
  {:name => "Smith",    :weight => 10},
  {:name => "Johnson",  :weight => 8},
  {:name => "Williams", :weight => 7},
  {:name => "Jones",    :weight => 6},
  {:name => "Brown",    :weight => 6},
  {:name => "Davis",    :weight => 5},
  {:name => "Miller",   :weight => 4},
  {:name => "Wilson",   :weight => 3}
]

It automatically sets cumulative_weight attribute for each record.

Here is an example of importing data from CSV file:

db/seeds/last_names.csv:

name,weight
Smith,10
Johnson,8
Williams,7
Jones,6
Brown,6
Davis,5
Miller,4
Wilson,3

db/seeds.rb:

LastName.create(
  CSV.table(File.expand_path("seeds/last_names.csv", File.dirname(__FILE__))).collect(&:to_hash)
)

Weighted randomization

To get weighed random record simply run:

LastName.weighted_rand

Demonstration:

10.times { puts LastName.weighted_rand.name }
Johnson
Brown
Johnson
Smith
Smith
Jones
Smith
Williams
Miller
Jones

Author

Szymon PrzybyƂ (github.com/apocalyptiq)