Commit 8169e3ca4de771d494eafd1403cc9809516bd547

Authored by AntonioTerceiro
1 parent bd787d26

ActionItem43: reformulating ProfileListBlock logic. Finder now is responsible for everything.


git-svn-id: https://svn.colivre.coop.br/svn/noosfero/trunk@1367 3f533792-8f58-4932-b0fe-aaf55b0a4547
app/models/members_block.rb
... ... @@ -15,20 +15,33 @@ class MembersBlock < ProfileListBlock
15 15 end
16 16 end
17 17  
18   - class Finder
  18 + def profile_finder
  19 + @profile_finder ||= MembersBlock::Finder.new(self)
  20 + end
19 21  
20   - def initialize(members)
21   - @members = members
  22 + # Finds random members, up to the limit.
  23 + class Finder
  24 + def initialize(block)
  25 + @block = block
  26 + end
  27 + attr_reader :block
  28 +
  29 + def find
  30 + ids = block.owner.members.map(&:id)
  31 + result = []
  32 + [block.limit, ids.size].min.times do
  33 + i = pick_random(ids.size)
  34 + result << Profile.find(ids[i])
  35 + ids.delete_at(i)
  36 + end
  37 + result
22 38 end
23 39  
24   - # FIXME optimize this !!!
25   - def find(options)
26   - Profile.find(:all, options.merge(:conditions => { :id => @members.map(&:id) }))
  40 + def pick_random(top)
  41 + rand(top)
27 42 end
28   - end
29 43  
30   - def profile_finder
31   - @profile_finder ||= Finder.new(owner.members)
32 44 end
33 45  
  46 +
34 47 end
... ...
app/models/profile_list_block.rb
... ... @@ -19,22 +19,22 @@ class ProfileListBlock &lt; Block
19 19 # have a <tt>find</tt> method that accepts the same interface as the
20 20 # ActiveRecord::Base's find method .
21 21 def profile_finder
22   - Profile
  22 + @profile_finder ||= ProfileListBlock::Finder.new(self)
23 23 end
24 24  
25   - def profiles
26   - # FIXME pick random people instead
27   - finder = profile_finder
28   - options = { :limit => self.limit, :order => 'created_at desc' }
29   - if finder.is_a?(Class)
30   - finder.find(:all, options)
31   - else
32   - finder.find(options)
  25 + # Default finder. Finds the most recently added profiles.
  26 + class Finder
  27 + def initialize(block)
  28 + @block = block
  29 + end
  30 + attr_reader :block
  31 + def find
  32 + Profile.find(:all, :limit => block.limit, :order => 'created_at desc')
33 33 end
34 34 end
35 35  
36   - def random(top)
37   - Kernel.rand(top)
  36 + def profiles
  37 + profile_finder.find
38 38 end
39 39  
40 40 # the title of the block. Probably will be overriden in subclasses.
... ...
test/unit/members_block_test.rb
... ... @@ -22,13 +22,30 @@ class MembersBlockTest &lt; Test::Unit::TestCase
22 22 assert_equal 'link-to-members', instance_eval(&block.footer)
23 23 end
24 24  
25   - should 'pick only members' do
  25 + should 'pick random members' do
  26 +
26 27 profile = create_user('mytestuser').person
27 28 block = MembersBlock.new
28 29 block.box = profile.boxes.first
  30 + block.limit = 2
29 31 block.save!
30 32  
31   - assert_equal profile.members, block.profiles
  33 + owner = mock
  34 + block.expects(:owner).returns(owner)
  35 +
  36 + member1 = mock; member1.stubs(:id).returns(1)
  37 + member2 = mock; member2.stubs(:id).returns(2)
  38 + member3 = mock; member3.stubs(:id).returns(3)
  39 +
  40 + owner.expects(:members).returns([member1, member2, member3])
  41 +
  42 + block.profile_finder.expects(:pick_random).with(3).returns(2)
  43 + block.profile_finder.expects(:pick_random).with(2).returns(0)
  44 +
  45 + Profile.expects(:find).with(3).returns(member3)
  46 + Profile.expects(:find).with(1).returns(member1)
  47 +
  48 + assert_equal [member3, member1], block.profiles
32 49 end
33 50  
34 51 end
... ...
test/unit/profile_list_block_test.rb
... ... @@ -39,31 +39,21 @@ class ProfileListBlockTest &lt; Test::Unit::TestCase
39 39 assert_kind_of String, instance_eval(&block.content)
40 40 end
41 41  
42   - should 'find in Profile by default' do
43   - assert_equal Profile, ProfileListBlock.new.profile_finder
44   - end
  42 + should 'pick most recently-added profiles by default' do
  43 + Profile.expects(:find).with(:all, { :limit => 10, :order => 'created_at desc'})
45 44  
46   - should 'ask profile finder for profiles' do
47 45 block = ProfileListBlock.new
48   - block.expects(:profile_finder).returns(Profile).once
49   - Profile.expects(:find).with(:all, is_a(Hash)).returns([])
  46 + block.limit = 10
50 47 block.profiles
51 48 end
52 49  
53   - should 'support non-class finders' do
  50 + should 'use finders to find profiles to be listed' do
54 51 block = ProfileListBlock.new
55 52 finder = mock
56 53 block.expects(:profile_finder).returns(finder).once
57   - finder.expects(:find).with(is_a(Hash)).once
  54 + finder.expects(:find)
58 55 block.profiles
59 56 end
60 57  
61   - should 'pick random people'
62   -
63   - should 'use Kernel.rand to generate random numbers' do
64   - Kernel.expects(:rand).with(77).once
65   - ProfileListBlock.new.random(77)
66   - end
67   -
68 58  
69 59 end
... ...