2014-03-26 11:09:39 +00:00
|
|
|
|
# == Schema Information
|
|
|
|
|
#
|
|
|
|
|
# Table name: articles
|
|
|
|
|
#
|
|
|
|
|
# id :integer not null, primary key
|
|
|
|
|
# status :integer not null
|
2015-05-14 16:29:16 +00:00
|
|
|
|
# text :text(16777215)
|
2020-03-31 17:27:34 +00:00
|
|
|
|
# text_coding :integer default(0), not null
|
2020-03-18 03:38:17 +00:00
|
|
|
|
# text_parsed :text(16777215)
|
|
|
|
|
# title :string(255)
|
|
|
|
|
# version :integer
|
2014-03-26 11:09:39 +00:00
|
|
|
|
# created_at :datetime
|
|
|
|
|
# updated_at :datetime
|
2020-03-18 03:38:17 +00:00
|
|
|
|
# category_id :integer
|
|
|
|
|
# user_id :integer
|
|
|
|
|
#
|
|
|
|
|
# Indexes
|
|
|
|
|
#
|
|
|
|
|
# index_articles_on_category_id (category_id)
|
|
|
|
|
# index_articles_on_created_at (created_at)
|
|
|
|
|
# index_articles_on_created_at_and_status (created_at,status)
|
|
|
|
|
# index_articles_on_user_id (user_id)
|
2014-03-26 11:09:39 +00:00
|
|
|
|
#
|
|
|
|
|
|
2014-03-23 00:22:25 +00:00
|
|
|
|
class Article < ActiveRecord::Base
|
|
|
|
|
include Exceptions
|
|
|
|
|
include Extra
|
|
|
|
|
|
|
|
|
|
STATUS_PUBLISHED = 0
|
|
|
|
|
STATUS_DRAFT = 1
|
|
|
|
|
|
2017-10-30 12:26:51 +00:00
|
|
|
|
RULES = 1044
|
2014-03-23 00:22:25 +00:00
|
|
|
|
HISTORY = 401
|
|
|
|
|
HOF = 402
|
|
|
|
|
SPONSORS = 403
|
|
|
|
|
LINKS = 404
|
|
|
|
|
COMPETITIVE = 405
|
|
|
|
|
PLUGIN = 426
|
|
|
|
|
EXTRA = 428
|
|
|
|
|
SB_RULES = 450
|
|
|
|
|
G_RULES = 464
|
2017-01-14 19:16:26 +00:00
|
|
|
|
COMPMOD = 998
|
2014-03-23 00:22:25 +00:00
|
|
|
|
|
2020-03-18 21:50:26 +00:00
|
|
|
|
attribute :text_coding, :integer, default: CODING_HTML
|
|
|
|
|
attribute :status, :integer, default: STATUS_DRAFT
|
|
|
|
|
|
2019-06-01 10:56:09 +00:00
|
|
|
|
scope :recent, -> { order('created_at DESC').limit(8) }
|
|
|
|
|
scope :with_comments, -> {
|
|
|
|
|
select("articles.*, COUNT(C.id) AS comment_num").
|
|
|
|
|
joins("LEFT JOIN comments C ON C.commentable_type = 'Article' AND C.commentable_id = articles.id").
|
|
|
|
|
group("articles.id") }
|
|
|
|
|
scope :ordered, -> { order('articles.created_at DESC') }
|
|
|
|
|
scope :limited, -> { limit(5) }
|
|
|
|
|
scope :nodrafts, -> { where(status: STATUS_PUBLISHED) }
|
|
|
|
|
scope :drafts, -> { where(status: STATUS_DRAFT) }
|
|
|
|
|
scope :articles, -> { where(["category_id IN (SELECT id FROM categories WHERE domain = ?)", Category::DOMAIN_ARTICLES]) }
|
2020-03-25 02:30:37 +00:00
|
|
|
|
# FIXME: shorter
|
|
|
|
|
scope :onlynews, -> { where(category_id: Category.select(:id).where(domain: Category::DOMAIN_NEWS)) }
|
2019-06-01 10:56:09 +00:00
|
|
|
|
scope :category, -> (cat) { where(category_id: cat) }
|
|
|
|
|
scope :domain, -> (domain) { includes(:category).where("categories.domain = '?'", domain) }
|
|
|
|
|
#scope :nospecial, -> { where("category_id != ?", Category::SPECIAL)Â }
|
|
|
|
|
scope :interviews, -> { where(category_id: Category::INTERVIEWS) }
|
2014-03-23 00:22:25 +00:00
|
|
|
|
|
2020-03-26 02:26:30 +00:00
|
|
|
|
belongs_to :user, :optional => true
|
|
|
|
|
belongs_to :category, :optional => true
|
2019-06-01 10:56:09 +00:00
|
|
|
|
has_many :comments, as: :commentable, dependent: :destroy
|
|
|
|
|
has_many :files, class_name: 'DataFile', dependent: :destroy
|
2014-03-23 00:22:25 +00:00
|
|
|
|
|
|
|
|
|
validates_length_of :title, :in => 1..50
|
2014-03-30 19:50:52 +00:00
|
|
|
|
validates_length_of :text, :in => 1..16000000
|
|
|
|
|
|
2014-03-23 00:22:25 +00:00
|
|
|
|
validates_presence_of :user, :category
|
|
|
|
|
validate :validate_status
|
|
|
|
|
|
|
|
|
|
before_validation :init_variables, :if => Proc.new{ |model| model.new_record? }
|
|
|
|
|
before_save :format_text
|
|
|
|
|
after_save :send_notifications
|
|
|
|
|
|
|
|
|
|
has_view_count
|
2020-03-15 20:59:08 +00:00
|
|
|
|
acts_as_readable
|
2014-03-23 00:22:25 +00:00
|
|
|
|
acts_as_versioned
|
|
|
|
|
|
|
|
|
|
non_versioned_columns << 'category_id'
|
|
|
|
|
non_versioned_columns << 'status'
|
|
|
|
|
non_versioned_columns << 'user_id'
|
|
|
|
|
|
|
|
|
|
def to_s
|
|
|
|
|
title
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def previous_article
|
2020-04-01 02:40:17 +00:00
|
|
|
|
category.articles.nodrafts.where("id < ?", self.id).order("id DESC").first
|
2014-03-23 00:22:25 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def next_article
|
2020-04-01 02:40:17 +00:00
|
|
|
|
category.articles.nodrafts.where("id > ?", self.id).order("id ASC").first
|
2014-03-23 00:22:25 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def statuses
|
|
|
|
|
{STATUS_PUBLISHED => "Published", STATUS_DRAFT => "Draft"}
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def validate_status
|
|
|
|
|
errors.add :status, I18n.t(:invalid_status) unless statuses.include? status
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def init_variables
|
2020-03-18 21:50:26 +00:00
|
|
|
|
self.status = STATUS_DRAFT unless user&.admin?
|
|
|
|
|
self.text_coding = CODING_BBCODE if (!user&.admin? and text_coding == CODING_HTML)
|
2014-03-23 00:22:25 +00:00
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def format_text
|
|
|
|
|
if text_coding == CODING_BBCODE
|
2014-03-30 19:50:52 +00:00
|
|
|
|
self.text_parsed = bbcode_to_html(text)
|
2014-03-23 00:22:25 +00:00
|
|
|
|
elsif text_coding == CODING_MARKDOWN
|
|
|
|
|
self.text_parsed = BlueCloth.new(text).to_html
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def send_notifications
|
|
|
|
|
if (new_record? or status_changed?) and status == STATUS_PUBLISHED
|
|
|
|
|
case category.domain
|
|
|
|
|
when Category::DOMAIN_NEWS
|
2020-04-02 02:51:37 +00:00
|
|
|
|
Profile.includes(:user).where("notify_news = 1").each do |p|
|
2014-03-23 00:22:25 +00:00
|
|
|
|
Notifications.news p.user, self if p.user
|
|
|
|
|
end
|
|
|
|
|
when Category::DOMAIN_ARTICLES
|
2020-04-02 02:51:37 +00:00
|
|
|
|
Profile.includes(:user).where("notify_articles = 1").each do |p|
|
2014-03-23 00:22:25 +00:00
|
|
|
|
Notifications.article p.user, self if p.user
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
end
|
|
|
|
|
|
2020-03-16 01:08:21 +00:00
|
|
|
|
# FIXME
|
2014-03-23 00:22:25 +00:00
|
|
|
|
def remove_readings
|
|
|
|
|
Reading.delete_all ["readable_type = 'Category' AND readable_id = ?", category_id]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def can_show? cuser
|
|
|
|
|
status != STATUS_DRAFT or (cuser and (user == cuser or cuser.admin?))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def can_create? cuser
|
|
|
|
|
cuser and !cuser.banned?(Ban::TYPE_MUTE)
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def can_update? cuser, params = {}
|
|
|
|
|
cuser and !cuser.banned?(Ban::TYPE_MUTE) and (cuser.admin? or (user == cuser and !params.keys.include? "status"))
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
def can_destroy? cuser
|
|
|
|
|
cuser and cuser.admin?
|
|
|
|
|
end
|
2020-03-17 19:31:57 +00:00
|
|
|
|
|
|
|
|
|
def self.article_params params, cuser
|
|
|
|
|
p = [:title, :category_id, :text, :text_coding]
|
|
|
|
|
p << :status if cuser.admin?
|
|
|
|
|
params.require(:article).permit(*p)
|
|
|
|
|
end
|
2014-03-23 00:22:25 +00:00
|
|
|
|
end
|