Files
redux-scraper/app/models/domain/post.rb
2025-08-19 01:22:56 +00:00

233 lines
5.5 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 do
params(
user_klass: T.class_of(Domain::User),
fav_klass: T.class_of(Domain::UserPostFav),
).void
end
def self.has_faving_users!(user_klass, fav_klass = Domain::UserPostFav)
self.class_has_faving_users = user_klass
has_many :user_post_favs,
class_name: fav_klass.name,
inverse_of: :post,
dependent: :destroy
has_many :faving_users,
class_name: user_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