aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/examples/.gitignore1
-rwxr-xr-xactiverecord/examples/performance.rb162
-rw-r--r--activeresource/lib/active_resource/base.rb22
-rw-r--r--activeresource/test/cases/finder_test.rb38
4 files changed, 223 insertions, 0 deletions
diff --git a/activerecord/examples/.gitignore b/activerecord/examples/.gitignore
new file mode 100644
index 0000000000..0dfc1cb7fb
--- /dev/null
+++ b/activerecord/examples/.gitignore
@@ -0,0 +1 @@
+performance.sql
diff --git a/activerecord/examples/performance.rb b/activerecord/examples/performance.rb
new file mode 100755
index 0000000000..12153b490a
--- /dev/null
+++ b/activerecord/examples/performance.rb
@@ -0,0 +1,162 @@
+#!/usr/bin/env ruby -KU
+
+TIMES = (ENV['N'] || 10000).to_i
+
+require 'rubygems'
+gem 'addressable', '~>2.0'
+gem 'faker', '~>0.3.1'
+gem 'rbench', '~>0.2.3'
+require 'addressable/uri'
+require 'faker'
+require 'rbench'
+
+__DIR__ = File.dirname(__FILE__)
+$:.unshift "#{__DIR__}/../lib"
+require 'active_record'
+
+conn = { :adapter => 'mysql',
+ :database => 'activerecord_unittest',
+ :username => 'rails', :password => '',
+ :encoding => 'utf8' }
+
+conn[:socket] = Pathname.glob(%w[
+ /opt/local/var/run/mysql5/mysqld.sock
+ /tmp/mysqld.sock
+ /tmp/mysql.sock
+ /var/mysql/mysql.sock
+ /var/run/mysqld/mysqld.sock
+]).find { |path| path.socket? }
+
+ActiveRecord::Base.establish_connection(conn)
+
+class User < ActiveRecord::Base
+ connection.create_table :users, :force => true do |t|
+ t.string :name, :email
+ t.timestamps
+ end
+
+ has_many :exhibits
+end
+
+class Exhibit < ActiveRecord::Base
+ connection.create_table :exhibits, :force => true do |t|
+ t.belongs_to :user
+ t.string :name
+ t.text :notes
+ t.timestamps
+ end
+
+ belongs_to :user
+
+ def look; attributes end
+ def feel; look; user.name end
+
+ def self.look(exhibits) exhibits.each { |e| e.look } end
+ def self.feel(exhibits) exhibits.each { |e| e.feel } end
+end
+
+sqlfile = "#{__DIR__}/performance.sql"
+
+if File.exists?(sqlfile)
+ mysql_bin = %w[mysql mysql5].select { |bin| `which #{bin}`.length > 0 }
+ `#{mysql_bin} -u #{conn[:username]} #{"-p#{conn[:password]}" unless conn[:password].blank?} #{conn[:database]} < #{sqlfile}`
+else
+ puts 'Generating data...'
+
+ # pre-compute the insert statements and fake data compilation,
+ # so the benchmarks below show the actual runtime for the execute
+ # method, minus the setup steps
+
+ # Using the same paragraph for all exhibits because it is very slow
+ # to generate unique paragraphs for all exhibits.
+ notes = Faker::Lorem.paragraphs.join($/)
+ today = Date.today
+
+ puts 'Inserting 10,000 users and exhibits...'
+ 10_000.times do
+ user = User.create(
+ :created_on => today,
+ :name => Faker::Name.name,
+ :email => Faker::Internet.email
+ )
+
+ Exhibit.create(
+ :created_on => today,
+ :name => Faker::Company.name,
+ :user => user,
+ :notes => notes
+ )
+ end
+
+ mysqldump_bin = %w[mysqldump mysqldump5].select { |bin| `which #{bin}`.length > 0 }
+ `#{mysqldump_bin} -u #{conn[:username]} #{"-p#{conn[:password]}" unless conn[:password].blank?} #{conn[:database]} exhibits users > #{sqlfile}`
+end
+
+RBench.run(TIMES) do
+ column :times
+ column :ar
+
+ report 'Model#id', (TIMES * 100).ceil do
+ ar_obj = Exhibit.find(1)
+
+ ar { ar_obj.id }
+ end
+
+ report 'Model.new (instantiation)' do
+ ar { Exhibit.new }
+ end
+
+ report 'Model.new (setting attributes)' do
+ attrs = { :name => 'sam' }
+ ar { Exhibit.new(attrs) }
+ end
+
+ report 'Model.first' do
+ ar { Exhibit.first.look }
+ end
+
+ report 'Model.all limit(100)', (TIMES / 10).ceil do
+ ar { Exhibit.look Exhibit.all(:limit => 100) }
+ end
+
+ report 'Model.all limit(100) with relationship', (TIMES / 10).ceil do
+ ar { Exhibit.feel Exhibit.all(:limit => 100, :include => :user) }
+ end
+
+ report 'Model.all limit(10,000)', (TIMES / 1000).ceil do
+ ar { Exhibit.look Exhibit.all(:limit => 10000) }
+ end
+
+ exhibit = {
+ :name => Faker::Company.name,
+ :notes => Faker::Lorem.paragraphs.join($/),
+ :created_on => Date.today
+ }
+
+ report 'Model.create' do
+ ar { Exhibit.create(exhibit) }
+ end
+
+ report 'Resource#attributes=' do
+ attrs_first = { :name => 'sam' }
+ attrs_second = { :name => 'tom' }
+ ar { exhibit = Exhibit.new(attrs_first); exhibit.attributes = attrs_second }
+ end
+
+ report 'Resource#update' do
+ ar { Exhibit.first.update_attributes(:name => 'bob') }
+ end
+
+ report 'Resource#destroy' do
+ ar { Exhibit.first.destroy }
+ end
+
+ report 'Model.transaction' do
+ ar { Exhibit.transaction { Exhibit.new } }
+ end
+
+ summary 'Total'
+end
+
+ActiveRecord::Migration.drop_table "exhibits"
+ActiveRecord::Migration.drop_table "users"
diff --git a/activeresource/lib/active_resource/base.rb b/activeresource/lib/active_resource/base.rb
index f27febb7ef..e5b8589fb3 100644
--- a/activeresource/lib/active_resource/base.rb
+++ b/activeresource/lib/active_resource/base.rb
@@ -611,6 +611,28 @@ module ActiveResource
end
end
+
+ # A convenience wrapper for <tt>find(:first, *args)</tt>. You can pass
+ # in all the same arguments to this method as you can to
+ # <tt>find(:first)</tt>.
+ def first(*args)
+ find(:first, *args)
+ end
+
+ # A convenience wrapper for <tt>find(:last, *args)</tt>. You can pass
+ # in all the same arguments to this method as you can to
+ # <tt>find(:last)</tt>.
+ def last(*args)
+ find(:last, *args)
+ end
+
+ # This is an alias for find(:all). You can pass in all the same
+ # arguments to this method as you can to <tt>find(:all)</tt>
+ def all(*args)
+ find(:all, *args)
+ end
+
+
# Deletes the resources with the ID in the +id+ parameter.
#
# ==== Options
diff --git a/activeresource/test/cases/finder_test.rb b/activeresource/test/cases/finder_test.rb
index 38f7de96ac..535b6f4198 100644
--- a/activeresource/test/cases/finder_test.rb
+++ b/activeresource/test/cases/finder_test.rb
@@ -126,18 +126,56 @@ class FinderTest < Test::Unit::TestCase
assert_equal "David", all.last.name
end
+ def test_all
+ all = Person.all
+ assert_equal 2, all.size
+ assert_kind_of Person, all.first
+ assert_equal "Matz", all.first.name
+ assert_equal "David", all.last.name
+ end
+
+ def test_all_with_params
+ all = StreetAddress.all(:params => { :person_id => 1 })
+ assert_equal 1, all.size
+ assert_kind_of StreetAddress, all.first
+ end
+
def test_find_first
matz = Person.find(:first)
assert_kind_of Person, matz
assert_equal "Matz", matz.name
end
+ def test_first
+ matz = Person.first
+ assert_kind_of Person, matz
+ assert_equal "Matz", matz.name
+ end
+
+ def test_first_with_params
+ addy = StreetAddress.first(:params => { :person_id => 1 })
+ assert_kind_of StreetAddress, addy
+ assert_equal '12345 Street', addy.street
+ end
+
def test_find_last
david = Person.find(:last)
assert_kind_of Person, david
assert_equal 'David', david.name
end
+ def test_last
+ david = Person.last
+ assert_kind_of Person, david
+ assert_equal 'David', david.name
+ end
+
+ def test_last_with_params
+ addy = StreetAddress.last(:params => { :person_id => 1 })
+ assert_kind_of StreetAddress, addy
+ assert_equal '12345 Street', addy.street
+ end
+
def test_find_by_id_not_found
assert_raise(ActiveResource::ResourceNotFound) { Person.find(99) }
assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1) }