pboling/an_axe

View on GitHub
app/models/an_axe/topic.rb

Summary

Maintainability
A
0 mins
Test Coverage
module AnAxe
  class Topic < ActiveRecord::Base
    validates_presence_of :forum, :user, :title
    validates_size_of :title, :maximum => 255

    before_create  :set_default_replied_at_and_sticky
    before_update  :check_for_changing_forums
    after_save     :update_forum_counter_cache
    before_destroy :update_post_user_counts
    after_destroy  :update_forum_counter_cache

    belongs_to :forum, :counter_cache => true
    belongs_to :last_post, :class_name => "Post", :foreign_key => 'last_post_id'
    has_many :monitorships

    has_many :posts,     :order => "#{Post.table_name}.created_at", :dependent => :delete_all
    has_one  :recent_post, :order => "#{Post.table_name}.created_at DESC", :class_name => 'Post'
    def user
      self.send(AnAxe::Config.user_relation)
    end


    attr_accessible :title

    # To help with the create form
    attr_accessor :body
    attr_accessor :body_list

    def hit!
      self.class.increment_counter :hits, id
    end

    def sticky?() sticky == 1 end

    def views() hits end

    def paged?() posts_count > Post.per_page end

    def last_page
      [(posts_count.to_f / Post.per_page).ceil.to_i, 1].max
    end

    def editable_by?(user)
      user && (user.id == user_id || user.admin? || user.moderator_of?(forum_id))
    end

    def update_cached_post_fields(post)
      # these fields are not accessible to mass assignment
      remaining_post = post.frozen? ? recent_post : post
      if remaining_post
        self.class.update_all(['replied_at = ?, replied_by = ?, last_post_id = ?, posts_count = ?',
          remaining_post.created_at, remaining_post.user_id, remaining_post.id, posts.count], ['id = ?', id])
      else
        self.destroy
      end
    end

    protected
      def set_default_replied_at_and_sticky
        self.replied_at = Time.now.utc
        self.sticky   ||= 0
      end

      def set_post_forum_id
        Post.update_all ['forum_id = ?', forum_id], ['topic_id = ?', id]
      end

      def check_for_changing_forums
        old = Topic.find(id)
        @old_forum_id = old.forum_id if old.forum_id != forum_id
        true
      end

      # using count isn't ideal but it gives us correct caches each time
      def update_forum_counter_cache
        forum_conditions = ['topics_count = ?', Topic.count(:id, :conditions => {:forum_id => forum_id})]
        # if the topic moved forums
        if !frozen? && @old_forum_id && @old_forum_id != forum_id
          set_post_forum_id
          Forum.update_all ['topics_count = ?, posts_count = ?',
            Topic.count(:id, :conditions => {:forum_id => @old_forum_id}),
            Post.count(:id,  :conditions => {:forum_id => @old_forum_id})], ['id = ?', @old_forum_id]
        end
        # if the topic moved forums or was deleted
        if frozen? || (@old_forum_id && @old_forum_id != forum_id)
          forum_conditions.first << ", posts_count = ?"
          forum_conditions       << Post.count(:id, :conditions => {:forum_id => forum_id})
        end
        # User doesn't have update_posts_count method in SB2, as reported by Ryan
        #@voices.each &:update_posts_count if @voices
        Forum.update_all forum_conditions, ['id = ?', forum_id]
        @old_forum_id = @voices = nil
      end

      def update_post_user_counts
        @voices = voices.to_a
      end
  end
end