app/models/crowdblog/post.rb
module Crowdblog
class Post < ActiveRecord::Base
belongs_to :author, :class_name => Crowdblog.author_user_class_name
belongs_to :publisher, :class_name => Crowdblog.publisher_user_class_name
has_many :assets
has_many :status_change_records
delegate :name, to: :author, prefix: true, allow_nil: true
delegate :email, to: :author, prefix: true, allow_nil: true
delegate :gravatar_url, to: :author
delegate :year, to: :published_at
attr_accessor :transition
LEGACY_TITLE_REGEXP = /(\d+-\d+-\d+)-(.*)/
state_machine initial: :drafted do
state :drafted
state :finished
state :reviewed
state :published
event :finish do
transition drafted: :finished
end
event :draft do
transition finished: :drafted
end
end
state_machine :publisher, attribute: :state, initial: :drafted, namespace: :as_publisher do
state :drafted
state :finished
state :reviewed
state :published
before_transition on: :publish do |post, transition|
post.published_at ||= Time.now
end
before_transition on: :draft do |post, transition|
post.published_at = nil
end
event :draft do
transition published: :drafted
end
event :finish do
transition drafted: :finished
end
event :review do
transition finished: :reviewed
end
event :publish do
transition all => :published
end
end
# CLASS METHODS
class << self
def all_posts_json
includes(:author).
order_by_publish_date.to_json only: [:id, :title, :state, :published_at, :ready_for_review],
methods: [:author_email, :published?]
end
def by_author(author_id)
published_and_ordered.where(author_id: author_id)
end
def last_published(number)
published_and_ordered.limit(number)
end
def order_by_publish_date
order('published_at DESC, created_at DESC, id DESC')
end
def published
where(state: 'published')
end
def published_and_ordered
published.order_by_publish_date
end
def scoped_for(user)
user.is_publisher? ? all : user.authored_posts
end
def for_admin_index
ordered_by_state.order_by_publish_date
end
def ordered_by_state
order(:state)
end
end
# Must be after Class methods (otherwise a missing method error will raise)
scope :for_index, -> { last_published(3) }
scope :for_history, -> { last_published(13) }
scope :all_for_feed, -> { last_published(15) }
# INSTANCE METHODS
def allowed_to_update_permalink?
!self.published?
end
def day
"%02d" % published_at.day
end
def formatted_published_date
published_at.strftime("%b %d, %Y")
end
def html_body
@@renderer ||= Redcarpet::Markdown.new(Redcarpet::Render::HTML,
:autolink => true,
:fenced_code_blocks => true,
:space_after_headers => false,
:tables => true)
@@renderer.render(self.body).html_safe
end
def month
"%02d" % published_at.month
end
def publish_if_allowed(transition, user)
if user.is_publisher?
self.publisher = user
self.send(transition)
end
end
def regenerate_permalink
self.permalink = title.parameterize
end
#
# Use this methods to generate the post url
# always use with the splat
# operator
#
# Example:
# post_url(*post.url_params)
#
def url_params
[self.year, self.month, self.day, self.permalink, 'html']
end
end
end