222 lines
5.3 KiB
Ruby
222 lines
5.3 KiB
Ruby
# typed: strict
|
|
class Domain::Post < ReduxApplicationRecord
|
|
extend T::Helpers
|
|
include HasAuxTable
|
|
include HasCompositeToParam
|
|
include HasViewPrefix
|
|
include AttrJsonRecordAliases
|
|
include HasDescriptionHtmlForView
|
|
include HasDomainType
|
|
|
|
self.table_name = "domain_posts"
|
|
abstract!
|
|
|
|
class_attribute :class_has_creators,
|
|
:class_belongs_to_groups,
|
|
:class_has_faving_users
|
|
|
|
sig { returns(T::Boolean) }
|
|
def self.has_creators?
|
|
!!class_has_creators
|
|
end
|
|
|
|
sig { returns(T::Boolean) }
|
|
def self.belongs_to_groups?
|
|
!!class_belongs_to_groups
|
|
end
|
|
|
|
sig { returns(T::Boolean) }
|
|
def self.has_faving_users?
|
|
!!class_has_faving_users
|
|
end
|
|
|
|
# so sorbet knows this is a string
|
|
sig { returns(String) }
|
|
def type
|
|
super
|
|
end
|
|
|
|
sig { params(value: String).returns(String) }
|
|
def type=(value)
|
|
super
|
|
end
|
|
|
|
attr_json :last_submission_log_entry_id, :integer
|
|
belongs_to :last_submission_log_entry,
|
|
class_name: "::HttpLogEntry",
|
|
optional: true
|
|
|
|
has_many :files,
|
|
class_name: "::Domain::PostFile",
|
|
dependent: :destroy,
|
|
inverse_of: :post,
|
|
foreign_key: :post_id
|
|
|
|
sig { params(klass: T.class_of(Domain::PostFile)).void }
|
|
def self.has_single_file!(klass = Domain::PostFile)
|
|
has_one :file,
|
|
-> { order(created_at: :desc) },
|
|
class_name: klass.name,
|
|
foreign_key: :post_id
|
|
end
|
|
|
|
sig { params(klass: T.class_of(Domain::PostFile)).void }
|
|
def self.has_multiple_files!(klass = Domain::PostFile)
|
|
has_many :files,
|
|
class_name: klass.name,
|
|
foreign_key: :post_id,
|
|
inverse_of: :post
|
|
end
|
|
|
|
sig { params(klass: T.class_of(Domain::User)).void }
|
|
def self.has_single_creator!(klass)
|
|
self.class_has_creators = klass
|
|
has_one :primary_user_post_creation,
|
|
class_name: "::Domain::UserPostCreation",
|
|
inverse_of: :post,
|
|
dependent: :destroy
|
|
has_one :creator,
|
|
class_name: klass.name,
|
|
through: :primary_user_post_creation,
|
|
source: :user,
|
|
inverse_of: :posts
|
|
end
|
|
|
|
has_many :user_post_creations,
|
|
class_name: "::Domain::UserPostCreation",
|
|
inverse_of: :post,
|
|
dependent: :destroy
|
|
|
|
sig { params(klass: T.class_of(Domain::User)).void }
|
|
def self.has_multiple_creators!(klass)
|
|
# multiple creators association
|
|
self.class_has_creators = klass
|
|
has_many :creators,
|
|
class_name: klass.name,
|
|
through: :user_post_creations,
|
|
source: :user
|
|
end
|
|
|
|
has_many :user_post_favs,
|
|
class_name: "::Domain::UserPostFav",
|
|
inverse_of: :post,
|
|
dependent: :destroy
|
|
|
|
sig { params(klass: T.class_of(Domain::User)).void }
|
|
def self.has_faving_users!(klass)
|
|
self.class_has_faving_users = klass
|
|
has_many :faving_users,
|
|
class_name: klass.name,
|
|
through: :user_post_favs,
|
|
source: :user
|
|
end
|
|
|
|
sig do
|
|
params(
|
|
group_assoc_name: Symbol,
|
|
group_klass: T.class_of(Domain::PostGroup),
|
|
join_klass: T.class_of(Domain::PostGroupJoin),
|
|
).void
|
|
end
|
|
def self.belongs_to_groups!(group_assoc_name, group_klass, join_klass)
|
|
has_many :post_group_joins,
|
|
class_name: join_klass.name,
|
|
inverse_of: :post,
|
|
dependent: :destroy
|
|
|
|
has_many group_assoc_name,
|
|
through: :post_group_joins,
|
|
source: :group,
|
|
class_name: group_klass.name
|
|
end
|
|
|
|
sig { overridable.returns(Symbol) }
|
|
def self.post_order_attribute
|
|
:posted_at
|
|
end
|
|
|
|
sig { overridable.returns(T::Boolean) }
|
|
def pending_scan?
|
|
false
|
|
end
|
|
|
|
sig { abstract.returns(T.nilable(String)) }
|
|
def title
|
|
end
|
|
|
|
sig { abstract.returns(Integer) }
|
|
def num_post_files_for_view
|
|
end
|
|
|
|
sig { overridable.returns(String) }
|
|
def title_for_view
|
|
title || "(unknown)"
|
|
end
|
|
|
|
sig { abstract.returns(T.nilable(T.any(String, Integer))) }
|
|
def domain_id_for_view
|
|
end
|
|
|
|
sig { abstract.returns(T.nilable(Addressable::URI)) }
|
|
def external_url_for_view
|
|
end
|
|
|
|
sig { abstract.returns(T.nilable(Domain::PostFile)) }
|
|
def primary_file_for_view
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(Domain::User)) }
|
|
def primary_creator_for_view
|
|
nil
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(HttpLogEntry)) }
|
|
def scanned_post_log_entry_for_view
|
|
nil
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(ActiveSupport::TimeWithZone)) }
|
|
def file_downloaded_at
|
|
nil
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(String)) }
|
|
def description_for_view
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(HttpLogEntry)) }
|
|
def guess_last_submission_log_entry
|
|
nil
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(Integer)) }
|
|
def num_favorites_for_view
|
|
nil
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(String)) }
|
|
def primary_creator_name_fallback_for_view
|
|
nil
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(Domain::User)) }
|
|
def primary_fallback_creator_for_view
|
|
nil
|
|
end
|
|
|
|
class TagForView < T::Struct
|
|
const :category, Symbol
|
|
const :value, String
|
|
end
|
|
|
|
sig { overridable.returns(T.nilable(T::Array[TagForView])) }
|
|
def tags_for_view
|
|
nil
|
|
end
|
|
end
|
|
|
|
# eager load all subclasses
|
|
Dir[Rails.root.join("app/models/domain/post/**/*.rb")].each do |file|
|
|
require_dependency file
|
|
end
|