Skip to content

Commit

Permalink
refactored and tested AvatarLookup
Browse files Browse the repository at this point in the history
less array copying

Avoid N queries
  • Loading branch information
victor-cruz committed May 30, 2013
1 parent c2e597c commit 5d2a6e3
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 25 deletions.
39 changes: 14 additions & 25 deletions lib/avatar_lookup.rb
Original file line number Diff line number Diff line change
@@ -1,35 +1,24 @@
class AvatarLookup
attr_accessor :user_ids, :users

def initialize(user_ids)
@user_ids = user_ids

@user_ids.flatten!
@user_ids.compact! if @user_ids.present?
@user_ids.uniq! if @user_ids.present?

@loaded = false
def initialize(user_ids=[])
self.user_ids = AvatarLookup.filtered_users(user_ids)
end

# Lookup a user by id
def [](user_id)
ensure_loaded!
@users_hashed[user_id]
self.users = AvatarLookup.hashed_users(user_ids) if self.users.nil?
self.users[user_id]
end

private
def self.filtered_users(user_ids=[])
user_ids.flatten.tap(&:compact!).tap(&:uniq!)
end

protected

def ensure_loaded!
return if @loaded

@users_hashed = {}
# need email for hash
User.where(id: @user_ids).select([:id, :email, :email, :username]).each do |u|
@users_hashed[u.id] = u
end

@loaded = true
end


def self.hashed_users(user_ids=[])
users = User.where(:id => user_ids).select([:id, :email, :username])
users_with_ids = users.collect {|x| [x.id, x] }.flatten
Hash[*users_with_ids]
end
end
78 changes: 78 additions & 0 deletions spec/components/avatar_lookup_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# encoding: utf-8

require 'spec_helper'
require 'avatar_lookup'

describe AvatarLookup do
let!(:user){ Fabricate(:user) }
user_ids = [1, 2]

describe '#new' do
before do
AvatarLookup.stubs(:filtered_users).once.returns(user_ids)
@avatar_lookup = AvatarLookup.new
end

it 'init with cleaned user ids' do
@avatar_lookup.user_ids.should eq(user_ids)
end

it 'init users hash' do
@avatar_lookup.users.should eq(nil)
end
end

describe '#[]' do
before do
@avatar_lookup = AvatarLookup.new([user.id])
end

it 'returns nil if user_id does not exists' do
@avatar_lookup[0].should be_nil
end

it 'returns nil if user_id is nil' do
@avatar_lookup[nil].should be_nil
end

it 'returns user if user_id exists' do
@avatar_lookup[user.id].should eq(user)
end
end

describe '.filtered_users' do
it 'returns empty array if no params' do
AvatarLookup.filtered_users.should eq([])
end

it 'returns empty array' do
AvatarLookup.filtered_users([]).should eq([])
end

it 'returns filtered ids' do
AvatarLookup.filtered_users(user_ids).should eq(user_ids)
end

it 'returns flatten filtered ids' do
AvatarLookup.filtered_users([1, [2]]).should eq(user_ids)
end

it 'returns compact filtered ids' do
AvatarLookup.filtered_users([1, 2, nil]).should eq(user_ids)
end

it 'returns uniq filtered ids' do
AvatarLookup.filtered_users([1, 2, 2]).should eq(user_ids)
end
end

describe '.hashed_users' do
it 'returns empty hash if no params' do
AvatarLookup.hashed_users.should eq({})
end

it 'returns hashed users by id' do
AvatarLookup.hashed_users([user.id]).should eq({user.id => user})
end
end
end

0 comments on commit 5d2a6e3

Please sign in to comment.