Skip to content

Commit

Permalink
refactoring + specs
Browse files Browse the repository at this point in the history
  • Loading branch information
grosser committed Dec 28, 2008
1 parent 03aa7a7 commit b48b7c5
Show file tree
Hide file tree
Showing 6 changed files with 163 additions and 0 deletions.
26 changes: 26 additions & 0 deletions README.markdown
@@ -0,0 +1,26 @@
PROBLEM
=======
- database :order=>'random' is slow
- active record has no random build in

SOLUTION
========
- count all records
- grab x records from rand(offset)

INSTALL
=======
`script/plugin install git://github.com/grosser/random_records.git`

USAGE
=====

Model.random(3) == [Model(id:112),Model(id:113),Model(id:114)]
Model.random(1) == [Model(id:322)]
Model.random == Model(id:234)

AUTHOR
======
Michael Grosser
grosser.michael@gmail.com
Hereby placed under public domain, do what you want, just do not hold me accountable...
12 changes: 12 additions & 0 deletions Rakefile.rb
@@ -0,0 +1,12 @@
require 'rubygems'
require 'spec'

desc 'Default: run spec.'
task :default => :spec

desc "Run all specs in spec directory"
task :spec do |t|
options = "--colour --format progress --loadby --reverse"
files = FileList['spec/**/*_spec.rb']
system("spec #{options} #{files}")
end
13 changes: 13 additions & 0 deletions lib/random_records.rb
@@ -0,0 +1,13 @@
class ActiveRecord::Base
def self.random(num=nil,options={})
return_array = !num.nil?
num ||= 1
return [] if num.zero?
num_records = options.delete(:count) || count
highest_possible_offset = [0,num_records-num].max
offset = [rand(num_records),highest_possible_offset].min
limit = [num,num_records].min
all = find(:all, {:offset => offset, :limit=>limit}.merge(options))
return_array ? all : all[0]
end
end
55 changes: 55 additions & 0 deletions spec/random_records_spec.rb
@@ -0,0 +1,55 @@
require File.expand_path("spec_helper", File.dirname(__FILE__))

describe :random do
before :all do
10.times {|i| User.create!}
end

it "finds a record when called without parameters" do
User.random.class.should == User
end
it "finds a single random record" do
User.random(1).size.should == 1
User.random(1)[0].class.should == User
end
it "finds by offset from rand" do
User.expects(:rand).with(User.count).returns 3
User.random(1).should == [User.find(4)]
end
it "finds using the given count option" do
User.expects(:rand).with(3).returns 2
User.random(1,:count=>3).should == [User.find(3)]
end
it "finds the requested number" do
User.random(9).uniq.size.should == 9
end
it "finds sequentially from offset" do
users = User.random(9).map(&:id)
users.each_with_index do |id,index|
next if index.zero?
id.should == (users[index-1] + 1)
end
end
it "finds count records when requested >= count" do
User.random(20).size.should == User.count
end
it "returns empty array if number is 0" do
User.random(0).should == []
end
it "is chainable" do
User.first_5.random(9).size.should == 5
User.first_5.random(4).size.should == 4
end
end

describe 'when no records exist' do
before :all do
User.delete_all
end
it 'finds nil without parameters' do
User.random.should == nil
end
it "finds 0 for all calls" do
User.random(20).size.should == 0
end
end
15 changes: 15 additions & 0 deletions spec/setup_test_model.rb
@@ -0,0 +1,15 @@
require 'rubygems'
require 'active_record'

#create model table
ActiveRecord::Schema.define(:version => 1) do
create_table "users" do |t|
t.integer :age
t.timestamps
end
end

#create model
class User < ActiveRecord::Base
named_scope :first_5, :conditions=>"id < 6"
end
42 changes: 42 additions & 0 deletions spec/spec_helper.rb
@@ -0,0 +1,42 @@
# ---- requirements
require 'rubygems'
require 'spec'
require 'mocha'

$LOAD_PATH << File.expand_path("../lib", File.dirname(__FILE__))


# ---- rspec
Spec::Runner.configure do |config|
config.mock_with :mocha
end


# ---- bugfix
#`exit?': undefined method `run?' for Test::Unit:Module (NoMethodError)
#can be solved with require test/unit but this will result in extra test-output
module Test
module Unit
def self.run?
true
end
end
end

# ---- load active record
require 'active_record'


RAILS_ENV = "test"
ActiveRecord::Base.configurations = {"test" => {
:adapter => "sqlite3",
:database => ":memory:",
}.with_indifferent_access}

ActiveRecord::Base.logger = Logger.new(File.directory?("log") ? "log/#{RAILS_ENV}.log" : "/dev/null")
ActiveRecord::Base.establish_connection(:test)


# ---- setup environment/plugin
require File.expand_path("../init", File.dirname(__FILE__))
load File.expand_path("setup_test_model.rb", File.dirname(__FILE__))

0 comments on commit b48b7c5

Please sign in to comment.