Commit 672bf83

Tyler Mercier <tylermercier@gmail.com>
2013-06-15 15:40:52
add code samples
1 parent 632b3f3
samples/add_indexes.rb
@@ -0,0 +1,6 @@
+class AddIndexesToCakes < ActiveRecord::Migration
+  def change
+    add_index :cakes, :updated_at
+    add_index :cakes, :category_id
+  end
+end
samples/loldba_output.txt
@@ -0,0 +1,11 @@
+λ rake db:find_indexes
+
+* TIP: if you have a problem with the index name('index name too long') you can solve with the :name option. Something like :name => 'my_index'.
+* run `rails g migration AddMissingIndexes` and add the following content:
+
+
+    class AddMissingIndexes < ActiveRecord::Migration
+      def change
+        add_index :cakes, :user_id
+      end
+    end
samples/n_plus_1.rb
@@ -0,0 +1,5 @@
+class CakesController < ApplicationController
+  def index
+    @cakes = Cake.all
+  end
+end
samples/n_plus_1_fixed.rb
@@ -0,0 +1,5 @@
+class CakesController < ApplicationController
+  def index
+    @cakes = Cake.all(include: :category)
+  end
+end
samples/n_plus_1_view.html.erb
@@ -0,0 +1,3 @@
+<% @cakes.each do |cake| %>
+  <p><%= cake.category.name %></p>
+<% end %>
samples/preoptimization.rb
@@ -0,0 +1,129 @@
+class CategoryList
+  include ActiveModel::Serialization
+
+  attr_accessor :categories,
+                :topic_users,
+                :uncategorized,
+                :draft,
+                :draft_key,
+                :draft_sequence
+
+  def initialize(guardian=nil)
+    @guardian = guardian || Guardian.new
+
+    find_relevant_topics
+    find_categories
+
+    prune_empty
+    add_uncategorized
+    find_user_data
+  end
+
+  private
+
+    # Retrieve a list of all the topics we'll need
+    def find_relevant_topics
+      @topics_by_category_id = {}
+      category_featured_topics = CategoryFeaturedTopic.select([:category_id, :topic_id]).order(:rank)
+      @topics_by_id = {}
+
+      @all_topics = Topic.where(id: category_featured_topics.map(&:topic_id))
+      @all_topics.each do |t|
+        @topics_by_id[t.id] = t
+      end
+
+      category_featured_topics.each do |cft|
+        @topics_by_category_id[cft.category_id] ||= []
+        @topics_by_category_id[cft.category_id] << cft.topic_id
+      end
+    end
+
+    # Find a list of all categories to associate the topics with
+    def find_categories
+      @categories = Category
+                      .includes(:featured_users)
+                      .secured(@guardian)
+                      .order('COALESCE(categories.topics_week, 0) DESC')
+                      .order('COALESCE(categories.topics_month, 0) DESC')
+                      .order('COALESCE(categories.topics_year, 0) DESC')
+
+      @categories = @categories.to_a
+      @categories.each do |c|
+        topics_in_cat = @topics_by_category_id[c.id]
+        if topics_in_cat.present?
+          c.displayable_topics = []
+          topics_in_cat.each do |topic_id|
+            topic = @topics_by_id[topic_id]
+            if topic.present?
+              topic.category = c
+              c.displayable_topics << topic
+            end
+          end
+        end
+      end
+    end
+
+    # Add the uncategorized "magic" category
+    def add_uncategorized
+      # Support for uncategorized topics
+      uncategorized_topics = Topic
+                        .listable_topics
+                        .where(category_id: nil)
+                        .topic_list_order
+                        .limit(SiteSetting.category_featured_topics)
+      if uncategorized_topics.present?
+
+        totals = Topic.exec_sql("SELECT SUM(CASE WHEN created_at >= (CURRENT_TIMESTAMP - INTERVAL '1 WEEK') THEN 1 ELSE 0 END) as topics_week,
+                                        SUM(CASE WHEN created_at >= (CURRENT_TIMESTAMP - INTERVAL '1 MONTH') THEN 1 ELSE 0 END) as topics_month,
+                                        SUM(CASE WHEN created_at >= (CURRENT_TIMESTAMP - INTERVAL '1 YEAR') THEN 1 ELSE 0 END) as topics_year,
+                                        COUNT(*) AS topic_count
+                                 FROM topics
+                                 WHERE topics.visible
+                                  AND topics.deleted_at IS NULL
+                                  AND topics.category_id IS NULL
+                                  AND topics.archetype <> '#{Archetype.private_message}'").first
+
+
+        uncategorized = Category.new({name: SiteSetting.uncategorized_name,
+                                      slug: Slug.for(SiteSetting.uncategorized_name),
+                                      color: SiteSetting.uncategorized_color,
+                                      text_color: SiteSetting.uncategorized_text_color,
+                                      featured_topics: uncategorized_topics}.merge(totals))
+
+        # Find the appropriate place to insert it:
+        insert_at = nil
+        @categories.each_with_index do |c, idx|
+          if (uncategorized.topics_week || 0) > (c.topics_week || 0)
+            insert_at = idx
+            break
+          end
+        end
+
+        @categories.insert(insert_at || @categories.size, uncategorized)
+      end
+
+      if @all_topics.present? && uncategorized.present?
+        uncategorized.displayable_topics = uncategorized_topics
+        @all_topics << uncategorized_topics
+        @all_topics.flatten!
+      end
+    end
+
+    # Remove any empty topics unless we can create them (so we can see the controls)
+    def prune_empty
+      unless @guardian.can_create?(Category)
+        # Remove categories with no featured topics unless we have the ability to edit one
+        @categories.delete_if { |c| c.displayable_topics.blank? }
+      end
+    end
+
+    # Get forum topic user records if appropriate
+    def find_user_data
+      if @guardian.current_user && @all_topics.present?
+        topic_lookup = TopicUser.lookup_for(@guardian.current_user, @all_topics)
+
+        # Attach some data for serialization to each topic
+        @all_topics.each { |ft| ft.user_data = topic_lookup[ft.id] }
+      end
+    end
+end