I recently found (and fixed) a major performance problem related to acts_as_list, which is a common Rails plugin that allows objects to be maintained in a list.
One type of object in EDU 2.0 is a Resource. There are several types of Resource, such as a File and a Folder. You can arrange resources as a list within a Folder, so in Resource I declare:
class Resource < ActiveRecord::Base
belongs_to :folder
acts_as_list :scope => :folder_id
...
end
and of course I have:
class Folder < Resource
has_many :resources, :order_by => 'position', :dependent => :destroy
end
So far, so good - basic Rails programming. The issue arises when you create a root Folder that does not belong to a parent folder and its folder_id is nil.
When I created a Folder with no parent, I noticed that acts_as_list executed the following SQL:
select * from resources where folder_id is NULL order by position DESC limit 1
In EDU 2.0 every class, section, user and group gets a root folder, so there are over 150,000 root folders with a folder_id equal to NULL. So every time I added a root folder, acts_as_list did a lookup and sort over a huge number of records. Similarly, when I deleted a root folder, it did a similar thing.
I think that acts_as_list should not attempt to add an item into a list if its scoping field is nil. So I made two minor changes to the acts_as_list module. First, I changed the scope_condition to return nil if the scoping field is nil:
def scope_condition
if #{configuration[:scope].to_s}.nil?
nil # USED TO BE "#{configuration[:scope].to_s} IS NULL"
else
"#{configuration[:scope].to_s} = \#{#{configuration[:scope].to_s}}"
end
end
Then I changed add_to_list_bottom to only add an item to the list if its scope condition is not nil:
def add_to_list_bottom
if scope_condition # NEW
self[position_column] = bottom_position_in_list.to_i + 1
end
end
The net result of this tiny change has been huge! I highly recommend making this tweak if you encounter a similar issue.
Recent Comments