Skip to content

Instantly share code, notes, and snippets.

@fdutey fdutey/gist:1613585
Created Jan 15, 2012

Embed
What would you like to do?
module Formol
class Post < ActiveRecord::Base
#Security
attr_protected :topic_id, :user_id, :created_by_topic
#Virtual attributes
attr_accessor :created_by_topic, :quote_id, :register_user_as_subscriber
#Default values
default_value_for :created_by_topic, false
default_value_for :display_signature do |p|
p.user ? p.user.preference.use_signature : true
end
#Associations
belongs_to :topic, :touch => true,
:counter_cache => true
belongs_to :user, :class_name => Formol.config.user_class,
:counter_cache => :formol_posts_count
has_one :forum, :through => :topic
#Validations
validates :topic, :presence => true
validates :user, :presence => true
#Length is set with a minimum of 2 to allow posts with simple "ok" answer
#Length is set with a maximum of 50 000 because 50Kb is enough for a non
#binary forum
validates :content, :presence => true,
:length => { :in => 2..50_000,
:allow_blank => true }
validate :validates_topic_not_locked
#Normalization
normalize_attribute :content, :with => [:strip, :blank]
#Callbacks
after_initialize :feed_content_with_quote
after_save :register_author_as_subscriber
after_create :increment_forum_counter_cache,
:register_as_last_post_on_topic,
:register_as_last_post_on_forum
after_destroy :decrement_forum_counter_cache,
:unregister_as_last_post_on_topic,
:unregister_as_last_post_on_forum
#Scopes
class << self
# scope for ordering posts conveniently for listing views
# order by id (no order is random with mysql)
def ordered_for_listing
order('formol_posts.id ASC')
end
# scope to get posts conveniently prepared for listing
def ready_for_listing
ordered_for_listing.includes(:topic, { :user => :preference })
end
# scope to get last five posts with reverse ordering
# usefull to have a little history when replying to a topic
def last_fives
order('formol_posts.id DESC').limit(5).includes(:user)
end
end
#Business methods
# Read accessor for 'register_user_as_subscriber'
def register_user_as_subscriber(force_recompute = false)
if @register_user_as_subscriber.nil? || force_recompute
@register_user_as_subscriber = compute_register_subscribing
end
@register_user_as_subscriber
end
private
# Convert 'register_user_as_subscriber' to boolean
def register_user_as_subscriber?
[true, '1', 'true'].include?(register_user_as_subscriber)
end
#Callback methods
# Registers author as subscriber if he's not already
def register_author_as_subscriber
if register_user_as_subscriber?
topic.register_subscriber(user) unless topic.subscriber?(user)
else
topic.unregister_subscriber(user) if topic.subscriber?(user)
end
end
# Validates topic is not locked
# If topic is locked, it will add an error on base (not on topic)
# This validation does not trigger on first post
def validates_topic_not_locked
errors.add(:base, :topic_locked) if topic.locked? && !created_by_topic
end
# Holds counter cache on Forum till AR does not support it on has_one
def increment_forum_counter_cache
Formol::Forum.increment_counter(:posts_count, forum.id) if forum.present?
end
# Holds counter cache on Forum till AR does not support it on has_one
def decrement_forum_counter_cache
Formol::Forum.decrement_counter(:posts_count, forum.id) if forum.present?
end
# Feed content with quote's content
# If you're trying to pass quote_id in a POST, your content will be wiped
# Too bad!
def feed_content_with_quote
return true if quote_id.blank?
q = topic.posts.find(quote_id)
formatter = Formol.config.formatter.new
# Extract and agnostize it
content_with_quote = "> **#{q.user.display_name} #{I18n.t('.wrote')}:**\n>\n"
content_with_quote << formatter.quote(q.content)
self.content = content_with_quote
self.content << "\n\n" #use '<<' to skip normalize_attribute
self.content
end
# Register current post being the last of its topic
def register_as_last_post_on_topic
topic.register_last_post(self)
end
# Unregister current post being the last of its topic
def unregister_as_last_post_on_topic
topic.unregister_last_post if topic.last_post == self
end
# Register current post being the last post of its forum
def register_as_last_post_on_forum
forum.register_last_post(self)
end
# Unregister current post being the last of its forum
def unregister_as_last_post_on_forum
forum.unregister_last_post if forum.last_post == self
end
# Computes 'register_user_as_subscriber
def compute_register_subscribing
if topic && user
topic.subscriber?(user)
else
false
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.