Commit 9afa74df42ee54e444c6f99227f069e52c1f566a

Authored by Antonio Terceiro
1 parent 4844d8a7

Smarter way of sorting profiles randomly

This fixes the problem where profiles are listed more than once in profile
listing blocks.

(ActionItem1682)
app/models/profile_list_block.rb
@@ -12,12 +12,16 @@ class ProfileListBlock < Block @@ -12,12 +12,16 @@ class ProfileListBlock < Block
12 end 12 end
13 13
14 def profile_list 14 def profile_list
15 - random = Noosfero::SQL.random_function 15 + random = randomizer
16 profiles.visible.all(:limit => limit, :select => 'DISTINCT profiles.*, ' + random, :order => random) 16 profiles.visible.all(:limit => limit, :select => 'DISTINCT profiles.*, ' + random, :order => random)
17 end 17 end
18 18
19 def profile_count 19 def profile_count
20 - profiles.visible.count 20 + profiles.visible.count('DISTINCT(profiles.id)')
  21 + end
  22 +
  23 + def randomizer
  24 + @randomizer ||= "(profiles.id % #{rand(profile_count)})"
21 end 25 end
22 26
23 # the title of the block. Probably will be overriden in subclasses. 27 # the title of the block. Probably will be overriden in subclasses.
lib/noosfero/sql.rb
@@ -1,15 +0,0 @@ @@ -1,15 +0,0 @@
1 -module Noosfero  
2 - module SQL  
3 - class << self  
4 -  
5 - def random_function()  
6 - default = 'random()'  
7 - adapter = ActiveRecord::Base.configurations[Rails.env]['adapter']  
8 - {  
9 - 'mysql' => 'rand()'  
10 - }[adapter] || default  
11 - end  
12 -  
13 - end  
14 - end  
15 -end  
test/unit/profile_list_block_test.rb
@@ -141,13 +141,20 @@ class ProfileListBlockTest &lt; Test::Unit::TestCase @@ -141,13 +141,20 @@ class ProfileListBlockTest &lt; Test::Unit::TestCase
141 p2 = fast_create(Person, :environment_id => env.id) 141 p2 = fast_create(Person, :environment_id => env.id)
142 p3 = fast_create(Person, :environment_id => env.id) 142 p3 = fast_create(Person, :environment_id => env.id)
143 143
144 - # force the "random" function to be something we know  
145 - Noosfero::SQL.stubs(:random_function).returns('-id')  
146 -  
147 block = ProfileListBlock.new 144 block = ProfileListBlock.new
148 block.stubs(:owner).returns(env) 145 block.stubs(:owner).returns(env)
149 146
  147 + # force the "random" function to return something we know
  148 + block.stubs(:randomizer).returns('-id')
  149 +
150 assert_equal [p3.id, p2.id, p1.id], block.profile_list.map(&:id) 150 assert_equal [p3.id, p2.id, p1.id], block.profile_list.map(&:id)
151 end 151 end
152 152
  153 + should 'randomize using modulo operator and random number' do
  154 + block = ProfileListBlock.new
  155 + block.expects(:profile_count).returns(10)
  156 + block.expects(:rand).with(10).returns(5)
  157 + assert_match /profiles.id % 5/, block.randomizer
  158 + end
  159 +
153 end 160 end