alvarobp-inverse_sortable 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ benchmark/benchmark.rb
2
+ benchmark/schema.rb
3
+ init.rb
4
+ lib/inverse_sortable.rb
5
+ Manifest
6
+ Rakefile
7
+ README.rdoc
8
+ test/inverse_sortable_test.rb
9
+ test/schema.rb
10
+ test/test_helper.rb
11
+ TODO
@@ -0,0 +1,33 @@
1
+ = inverse_sortable
2
+
3
+ Sets negative timestamps on Active Record models for efficiently sort in reverse order.
4
+
5
+ == Install
6
+
7
+ sudo gem install alvarobp-inverse_sortable --source http://gems.github.com
8
+
9
+ Add to environment.rb:
10
+
11
+ config.gem "alvarobp-inverse_sortable", :lib => "inverse_sortable"
12
+
13
+ == Usage
14
+
15
+ As a very simple plugin, using it is simple. Just add an integer attribute called "created_at_inverse" to your model. Afterwards you can make that model inverse sortable, for example:
16
+
17
+ class Film < ActiveRecord::Base
18
+ acts_as_inverse_sortable
19
+ end
20
+
21
+ Therefore, you can get an inverse sorted array of Films with Film.find(:all, :order => 'created_at_inverse') working on an efficient way.
22
+
23
+ == Test
24
+
25
+ Just do
26
+
27
+ rake test
28
+
29
+ == Benchmarks
30
+
31
+ I ran some benchmarks to see how efficient is this method. Well, most of the times benchmarks showed that this method is more efficient than "ORDER BY created_at DESC" as the table grows.
32
+
33
+ Just in case you want to run these benchmarks, you will need a mysql database (maybe other engines as well) and configure it at the top of benchmark/benchmark.rb file.
@@ -0,0 +1,12 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'echoe'
4
+
5
+ Echoe.new('inverse_sortable', '0.1.0') do |p|
6
+ p.description = "Sets negative timestamps on Active Record models for efficiently sort in reverse order."
7
+ p.url = "http://github.com/alvarobp/inverse_sortable"
8
+ p.author = "Alvaro Bautista Pino"
9
+ p.email = "alvarobp@gmail.com"
10
+ p.ignore_pattern = ["tmp/*", "script/*"]
11
+ p.development_dependencies = []
12
+ end
data/TODO ADDED
@@ -0,0 +1 @@
1
+ - Go deep in the fact that in Rails 2.3 on before_create record attributes information is not available.
@@ -0,0 +1,65 @@
1
+ require 'test/unit'
2
+
3
+ require 'rubygems'
4
+ require 'active_record'
5
+
6
+ ActiveRecord::Base.establish_connection({
7
+ :adapter => "mysql",
8
+ :database => "testing_dates",
9
+ :username => "root",
10
+ :password => "",
11
+ :host => "localhost"
12
+ })
13
+
14
+ load(File.dirname(__FILE__) + "/schema.rb")
15
+
16
+ class WithCreatedModel < ActiveRecord::Base
17
+ end
18
+
19
+ def add_rows(ntimes)
20
+ tdate = Time.now-100.days
21
+ ntimes.times do |n|
22
+ wcm = WithCreatedModel.create(:something => "Model #{n}")
23
+ tdate += (rand(5)+1).days
24
+ wcm.update_attribute(:created_at, tdate)
25
+ end
26
+ end
27
+
28
+ def do_benchmark
29
+ Benchmark.bm(10) do |x|
30
+ x.report("normal") {WithCreatedModel.find(:all, :order => "created_at DESC")}
31
+ x.report("inverse") {WithCreatedModel.find(:all, :order => "created_at_inverse")}
32
+ end
33
+ end
34
+
35
+ puts
36
+ puts
37
+ puts "-- Benchmark for 5000 rows --"
38
+ puts
39
+
40
+ add_rows(5000)
41
+ do_benchmark
42
+
43
+ puts
44
+ puts
45
+ puts "-- Benchmark for 10000 rows --"
46
+ puts
47
+
48
+ add_rows(5000)
49
+ do_benchmark
50
+
51
+ puts
52
+ puts
53
+ puts "-- Benchmark for 15000 rows --"
54
+ puts
55
+
56
+ add_rows(5000)
57
+ do_benchmark
58
+
59
+ puts
60
+ puts
61
+ puts "-- Benchmark for 20000 rows --"
62
+ puts
63
+
64
+ add_rows(5000)
65
+ do_benchmark
@@ -0,0 +1,13 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ begin
3
+ drop_table :with_created_models
4
+ rescue
5
+ end
6
+
7
+ create_table :with_created_models, :force => true do |t|
8
+ t.column :something, :string
9
+ t.column :created_at, :datetime
10
+ t.column :updated_at, :datetime
11
+ t.column :created_at_inverse, :integer
12
+ end
13
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'inverse_sortable'
@@ -0,0 +1,34 @@
1
+ module InverseSortable
2
+ def self.included(base)
3
+ super
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+ def acts_as_inverse_sortable
9
+ include InverseSortable::InstanceMethods
10
+ end
11
+ end
12
+
13
+ module InstanceMethods
14
+ def set_created_at_inverse
15
+ self.update_attribute(:created_at_inverse, -self.created_at.to_i)
16
+ end
17
+
18
+ def set_updated_at_inverse
19
+ self.updated_at_inverse = -Time.now.to_i
20
+ end
21
+
22
+ def after_create
23
+ set_created_at_inverse if self.respond_to?(:created_at_inverse)
24
+ super
25
+ end
26
+
27
+ def before_save
28
+ set_updated_at_inverse if self.respond_to?(:updated_at_inverse)
29
+ super
30
+ end
31
+ end
32
+ end
33
+
34
+ ActiveRecord::Base.send :include, InverseSortable
@@ -0,0 +1,40 @@
1
+ require File.join(File.dirname(__FILE__), 'test_helper')
2
+
3
+ class WithCreatedModel
4
+ acts_as_inverse_sortable
5
+ end
6
+
7
+ class WithUpdatedModel
8
+ acts_as_inverse_sortable
9
+ end
10
+
11
+ class WithBothModel
12
+ acts_as_inverse_sortable
13
+ end
14
+
15
+ class ActsAsInverseSortableTest < Test::Unit::TestCase
16
+ context "A model that acts as an inverse sortable" do
17
+ should "have the inverse of its created_at time when is created if created_at_inverse is available" do
18
+ with_created = WithCreatedModel.create(:something => "Testing")
19
+
20
+ assert_not_nil with_created.created_at_inverse
21
+ assert_equal -with_created.created_at.to_i, with_created.created_at_inverse
22
+ end
23
+
24
+ should "have the inverse of its updated_at time when is created if updated_at_inverse is available" do
25
+ with_updated = WithUpdatedModel.create(:something => "Testing")
26
+
27
+ assert_not_nil with_updated.updated_at_inverse
28
+ assert_equal -with_updated.updated_at.to_i, with_updated.updated_at_inverse
29
+ end
30
+
31
+ should "update its updated_at_inverse value at update" do
32
+ with_updated = WithUpdatedModel.create(:something => "Testing")
33
+ before_updated = with_updated.updated_at_inverse
34
+ sleep 1
35
+ with_updated.update_attribute(:something, "Testing update")
36
+
37
+ assert with_updated.updated_at_inverse < before_updated
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,25 @@
1
+ ActiveRecord::Schema.define(:version => 0) do
2
+ create_table :with_created_models, :force => true do |t|
3
+ t.column :something, :string
4
+ t.column :created_at, :datetime
5
+ t.column :updated_at, :datetime
6
+ t.column :created_at_inverse, :integer
7
+ end
8
+
9
+ add_index :with_created_models, :created_at_inverse
10
+
11
+ create_table :with_updated_models, :force => true do |t|
12
+ t.column :something, :string
13
+ t.column :created_at, :datetime
14
+ t.column :updated_at, :datetime
15
+ t.column :updated_at_inverse, :integer
16
+ end
17
+
18
+ create_table :with_both_models, :force => true do |t|
19
+ t.column :something, :string
20
+ t.column :created_at, :datetime
21
+ t.column :updated_at, :datetime
22
+ t.column :created_at_inverse, :integer
23
+ t.column :updated_at_inverse, :integer
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ #$:.unshift(File.dirname(__FILE__) + '/../lib')
2
+
3
+ require 'test/unit'
4
+
5
+ require 'rubygems'
6
+ require 'active_record'
7
+ require 'shoulda'
8
+
9
+ require File.dirname(__FILE__) + '/../lib/inverse_sortable'
10
+
11
+ ActiveRecord::Base.establish_connection({
12
+ :adapter => "sqlite3",
13
+ :dbfile => "test/test.db"
14
+ })
15
+
16
+ class WithCreatedModel < ActiveRecord::Base
17
+ end
18
+
19
+ class WithUpdatedModel < ActiveRecord::Base
20
+ end
21
+
22
+ class WithBothModel < ActiveRecord::Base
23
+ end
24
+
25
+ load(File.dirname(__FILE__) + "/schema.rb")
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: alvarobp-inverse_sortable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Alvaro Bautista Pino
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-03-19 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: Sets negative timestamps on Active Record models for efficiently sort in reverse order.
17
+ email: alvarobp@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - lib/inverse_sortable.rb
24
+ - README.rdoc
25
+ - TODO
26
+ files:
27
+ - benchmark/benchmark.rb
28
+ - benchmark/schema.rb
29
+ - init.rb
30
+ - lib/inverse_sortable.rb
31
+ - Manifest
32
+ - Rakefile
33
+ - README.rdoc
34
+ - test/inverse_sortable_test.rb
35
+ - test/schema.rb
36
+ - test/test_helper.rb
37
+ - TODO
38
+ has_rdoc: true
39
+ homepage: http://github.com/alvarobp/inverse_sortable
40
+ post_install_message:
41
+ rdoc_options: []
42
+
43
+ require_paths:
44
+ - lib
45
+ required_ruby_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - ">="
48
+ - !ruby/object:Gem::Version
49
+ version: "0"
50
+ version:
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "1.2"
56
+ version:
57
+ requirements: []
58
+
59
+ rubyforge_project: inverse_sortable
60
+ rubygems_version: 1.2.0
61
+ signing_key:
62
+ specification_version: 2
63
+ summary: Sets negative timestamps on Active Record models for efficiently sort in reverse order.
64
+ test_files:
65
+ - test/inverse_sortable_test.rb
66
+ - test/test_helper.rb