<commit_before>class Gws::Circular::Post
  include SS::Document
  include Gws::Referenceable
  include Gws::Reference::User
  include Gws::Reference::Site
  include Gws::Circular::See
  include Gws::Circular::Sort
  include Gws::Circular::Commentable
  include SS::Addon::Markdown
  include Gws::Addon::File
  include Gws::Addon::Member
  include Gws::Addon::ReadableSetting
  include Gws::Addon::GroupPermission
  include Gws::Addon::History
  include Gws::Addon::Circular::Category
  include Gws::Addon::Reminder

  seqid :id

  field :name, type: String
  field :due_date, type: DateTime
  field :deleted, type: DateTime

  permit_params :name, :due_date, :deleted

  validates :name, presence: true
  validates :due_date, presence: true
  validates :deleted, datetime: true

  alias reminder_date due_date
  alias reminder_user_ids member_ids

  # indexing to elasticsearch via companion object
  around_save ::Gws::Elasticsearch::Indexer::CircularPostJob.callback
  around_destroy ::Gws::Elasticsearch::Indexer::CircularPostJob.callback

  scope :search, ->(params) {
    criteria = where({})
    return criteria if params.blank?

    if sort_num = params[:sort].to_i
      criteria = criteria.order_by(new.sort_hash(sort_num))
    end

    if params[:keyword].present?
      criteria = criteria.keyword_in params[:keyword], :name, :text
    end

    if params[:category_id].present?
      criteria = criteria.in(category_ids: params[:category_id])
    end

    criteria
  }

  scope :without_deleted, ->(date = Time.zone.now) {
    where('$and' => [
      { '$or' => [{ deleted: nil }, { :deleted.gt => date }] }
    ])
  }

  scope :deleted, -> {
    where(:deleted.exists => true)
  }

  scope :expired, ->(date = Time.zone.now) {
    where('$or' => [
      { :deleted.exists => true , :deleted.lt => date }
    ])
  }

  def active?
    return true unless deleted.present? && deleted < Time.zone.now
    false
  end

  def active
    update_attributes(deleted: nil)
  end

  def disable
    update_attributes(deleted: Time.zone.now) if deleted.blank? || deleted > Time.zone.now
  end

  def custom_group_member?(user)
    custom_groups.where(member_ids: user.id).exists?
  end

  def user?(user)
    self.user.id == user.id
  end

  def allowed?(action, user, opts = {})
    return true if super(action, user, opts)
    return true if action =~ /read/ && readable_group_ids.blank? && readable_member_ids.blank? && readable_custom_group_ids.blank?
    return true if action =~ /read/ && readable_group_ids.any? { |m| user.group_ids.include?(m) }
    return true if action =~ /read/ && readable_member_ids.include?(user.id)
    return true if action =~ /read/ && readable_custom_groups.any? { |m| m.member_ids.include?(user.id) }<commit_msg>[fix] add readable? method<commit_after>class Gws::Circular::Post
  include SS::Document
  include Gws::Referenceable
  include Gws::Reference::User
  include Gws::Reference::Site
  include Gws::Circular::See
  include Gws::Circular::Sort
  include Gws::Circular::Commentable
  include SS::Addon::Markdown
  include Gws::Addon::File
  include Gws::Addon::Member
  include Gws::Addon::ReadableSetting
  include Gws::Addon::GroupPermission
  include Gws::Addon::History
  include Gws::Addon::Circular::Category
  include Gws::Addon::Reminder

  seqid :id

  field :name, type: String
  field :due_date, type: DateTime
  field :deleted, type: DateTime

  permit_params :name, :due_date, :deleted

  validates :name, presence: true
  validates :due_date, presence: true
  validates :deleted, datetime: true

  alias reminder_date due_date
  alias reminder_user_ids member_ids

  # indexing to elasticsearch via companion object
  around_save ::Gws::Elasticsearch::Indexer::CircularPostJob.callback
  around_destroy ::Gws::Elasticsearch::Indexer::CircularPostJob.callback

  scope :search, ->(params) {
    criteria = where({})
    return criteria if params.blank?

    if sort_num = params[:sort].to_i
      criteria = criteria.order_by(new.sort_hash(sort_num))
    end

    if params[:keyword].present?
      criteria = criteria.keyword_in params[:keyword], :name, :text
    end

    if params[:category_id].present?
      criteria = criteria.in(category_ids: params[:category_id])
    end

    criteria
  }

  scope :without_deleted, ->(date = Time.zone.now) {
    where('$and' => [
      { '$or' => [{ deleted: nil }, { :deleted.gt => date }] }
    ])
  }

  scope :deleted, -> {
    where(:deleted.exists => true)
  }

  scope :expired, ->(date = Time.zone.now) {
    where('$or' => [
      { :deleted.exists => true , :deleted.lt => date }
    ])
  }

  def active?
    return true unless deleted.present? && deleted < Time.zone.now
    false
  end

  def active
    update_attributes(deleted: nil)
  end

  def disable
    update_attributes(deleted: Time.zone.now) if deleted.blank? || deleted > Time.zone.now
  end

  def custom_group_member?(user)
    custom_groups.where(member_ids: user.id).exists?
  end

  def user?(user)
    self.user.id == user.id
  end

  def readable?(user, opts = {})
    readable_group_ids.blank? && readable_member_ids.blank? && readable_custom_group_ids.blank? ||
      readable_group_ids.any? { |m| user.group_ids.include?(m) } ||
      readable_member_ids.include?(user.id) ||
      readable_custom_groups.any? { |m| m.member_ids.include?(user.id) }
  end

  def allowed?(action, user, opts = {})
    return true if super(action, user, opts)
    return true if action =~ /read/ && readable?(user)
{'fraction_non_alphanumeric': 0.1312283263369228, 'fraction_numerical': 0.0, 'mean_word_length': 3.866785079928952, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5425916', 'n_tokens_mistral': 1801, 'n_tokens_neox': 1796, 'n_words': 403}