basic indexes fixed, migration script
This commit is contained in:
10
Rakefile
10
Rakefile
@@ -92,3 +92,13 @@ task :reverse_csv do
|
||||
in_csv.reverse_each { |row| out_csv << row.map(&:second) }
|
||||
out_csv.close
|
||||
end
|
||||
|
||||
task migrate_domain: :environment do
|
||||
Domain::MigrateToDomain.new.migrate_e621_users
|
||||
Domain::MigrateToDomain.new.migrate_e621_posts
|
||||
Domain::MigrateToDomain.new.migrate_fa_users
|
||||
Domain::MigrateToDomain.new.migrate_fa_posts
|
||||
Domain::MigrateToDomain.new.migrate_e621_users_favs
|
||||
Domain::MigrateToDomain.new.migrate_fa_users_favs
|
||||
Domain::MigrateToDomain.new.migrate_fa_users_followers
|
||||
end
|
||||
|
||||
281
app/lib/domain/migrate_to_domain.rb
Normal file
281
app/lib/domain/migrate_to_domain.rb
Normal file
@@ -0,0 +1,281 @@
|
||||
# typed: strict
|
||||
class Domain::MigrateToDomain
|
||||
extend T::Sig
|
||||
include HasColorLogger
|
||||
|
||||
sig { void }
|
||||
def migrate_e621_users
|
||||
Domain::E621::User
|
||||
.joins(
|
||||
"LEFT JOIN domain_users ON domain_e621_users.e621_user_id =
|
||||
(domain_users.json_attributes->>'e621_id')::integer
|
||||
AND domain_users.type = 'Domain::User::E621User'",
|
||||
)
|
||||
.where("domain_users.id IS NULL")
|
||||
.find_in_batches do |batch|
|
||||
ReduxApplicationRecord.transaction do
|
||||
batch.each { |user| migrate_e621_user(user) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_e621_posts
|
||||
Domain::E621::Post
|
||||
.joins(
|
||||
"LEFT JOIN domain_posts ON domain_e621_posts.e621_id =
|
||||
(domain_posts.json_attributes->>'e621_id')::integer
|
||||
AND domain_posts.type = 'Domain::Post::E621Post'",
|
||||
)
|
||||
.where("domain_posts.id IS NULL")
|
||||
.find_in_batches do |batch|
|
||||
ReduxApplicationRecord.transaction do
|
||||
batch.each { |post| migrate_e621_post(post) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_fa_users
|
||||
Domain::Fa::User
|
||||
.joins(
|
||||
"LEFT JOIN domain_users ON domain_fa_users.url_name =
|
||||
domain_users.json_attributes->>'url_name'
|
||||
AND domain_users.type = 'Domain::User::FaUser'",
|
||||
)
|
||||
.where("domain_users.id IS NULL")
|
||||
.find_in_batches do |batch|
|
||||
ReduxApplicationRecord.transaction do
|
||||
batch.each { |user| migrate_fa_user(user) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_fa_posts
|
||||
Domain::Fa::Post
|
||||
.joins(
|
||||
"LEFT JOIN domain_posts ON domain_fa_posts.fa_id =
|
||||
(domain_posts.json_attributes->>'fa_id')::integer
|
||||
AND domain_posts.type = 'Domain::Post::FaPost'",
|
||||
)
|
||||
.where("domain_posts.id IS NULL")
|
||||
.includes(:creator, :file)
|
||||
.find_in_batches do |batch|
|
||||
ReduxApplicationRecord.transaction do
|
||||
batch.each { |post| migrate_fa_post(post) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(user: Domain::Fa::User).void }
|
||||
def migrate_fa_user(user)
|
||||
user =
|
||||
Domain::User::FaUser.find_or_initialize_by(
|
||||
url_name: user.url_name,
|
||||
) { |new_user| new_user.name = user.name }
|
||||
|
||||
if user.new_record?
|
||||
logger.info("migrated fa user #{user.url_name}")
|
||||
user.save!
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(post: Domain::Fa::Post).void }
|
||||
def migrate_fa_post(post)
|
||||
post =
|
||||
Domain::Post::FaPost.find_or_initialize_by(
|
||||
fa_id: post.fa_id,
|
||||
) do |new_post|
|
||||
new_post.state = post.state
|
||||
new_post.title = post.title
|
||||
new_post.fa_id = post.fa_id
|
||||
new_post.category = post.category
|
||||
new_post.theme = post.theme
|
||||
new_post.species = post.species
|
||||
new_post.gender = post.gender
|
||||
new_post.description = post.description
|
||||
new_post.keywords = post.keywords
|
||||
new_post.num_favorites = post.num_favorites
|
||||
new_post.num_comments = post.num_comments
|
||||
new_post.num_views = post.num_views
|
||||
new_post.posted_at = post.posted_at
|
||||
new_post.scanned_at = post.scanned_at
|
||||
new_post.scan_file_error = post.scan_file_error
|
||||
new_post.last_user_page_id = post.last_user_page_id
|
||||
new_post.last_submission_page_id = post.last_submission_page_id
|
||||
new_post.first_browse_page_id = post.first_browse_page_id
|
||||
new_post.first_gallery_page_id = post.first_gallery_page_id
|
||||
new_post.first_seen_entry_id = post.first_seen_entry_id
|
||||
new_post.created_at = post.created_at
|
||||
|
||||
if post.creator.present?
|
||||
new_post.creator =
|
||||
Domain::User::FaUser.find_by!(url_name: post.creator&.url_name)
|
||||
end
|
||||
|
||||
if post.file.present?
|
||||
new_post.file =
|
||||
Domain::PostFile.find_or_create_by(
|
||||
log_entry: post.file,
|
||||
) do |new_file|
|
||||
new_file.log_entry = post.file
|
||||
new_file.url_str = post.file_url_str
|
||||
new_file.state = post.state
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if post.new_record?
|
||||
logger.info("migrated fa post #{post.fa_id}")
|
||||
post.save!
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(user: Domain::E621::User).void }
|
||||
def migrate_e621_user(user)
|
||||
user =
|
||||
Domain::User::E621User.find_or_initialize_by(
|
||||
e621_id: user.e621_user_id,
|
||||
) do |new_user|
|
||||
new_user.name = user.name
|
||||
new_user.favs_are_hidden = user.favs_are_hidden
|
||||
new_user.num_other_favs_cached = user.num_other_favs_cached
|
||||
new_user.scanned_favs_status = user.scanned_favs_status
|
||||
new_user.scanned_favs_at = user.scanned_favs_at
|
||||
end
|
||||
|
||||
if user.new_record?
|
||||
logger.info("migrated e621 user #{user.name}")
|
||||
user.save!
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(post: Domain::E621::Post).void }
|
||||
def migrate_e621_post(post)
|
||||
post =
|
||||
Domain::Post::E621Post.find_or_initialize_by(
|
||||
e621_id: post.e621_id,
|
||||
) do |new_post|
|
||||
new_post.state = post.state
|
||||
new_post.e621_id = post.e621_id
|
||||
new_post.scanned_post_favs_at = post.scanned_post_favs_at
|
||||
new_post.rating = post.rating
|
||||
new_post.tags_array = post.tags_array
|
||||
new_post.flags_array = post.flags_array
|
||||
new_post.pools_array = post.pools_array
|
||||
new_post.sources_array = post.sources_array
|
||||
new_post.artists_array = post.artists_array
|
||||
new_post.e621_updated_at = post.e621_updated_at
|
||||
new_post.last_index_page_id = post.last_index_page_id
|
||||
new_post.caused_by_entry_id = post.caused_by_entry_id
|
||||
new_post.scan_log_entry_id = post.scan_log_entry_id
|
||||
new_post.index_page_ids = post.index_page_ids
|
||||
new_post.prev_md5s = post.prev_md5s
|
||||
new_post.scan_error = post.scan_error
|
||||
new_post.file_error = post.file_error
|
||||
new_post.created_at = post.created_at
|
||||
|
||||
# TODO - migrate parent posts
|
||||
end
|
||||
|
||||
if post.new_record?
|
||||
logger.info("migrated e621 post #{post.e621_id}")
|
||||
post.save!
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_e621_users_favs
|
||||
Domain::User::E621User
|
||||
.where_migrated_user_favs_at("is null")
|
||||
.find_each { |user| migrate_e621_user_favs(user) }
|
||||
end
|
||||
|
||||
sig { params(user: Domain::User::E621User).void }
|
||||
def migrate_e621_user_favs(user)
|
||||
user_e621_id = user.e621_id
|
||||
old_user = Domain::E621::User.find_by!(e621_user_id: user_e621_id)
|
||||
old_post_e621_ids = old_user.faved_posts.pluck(:e621_id)
|
||||
new_post_ids =
|
||||
Domain::Post::E621Post.where(e621_id: old_post_e621_ids).pluck(:id)
|
||||
|
||||
Domain::UserPostFav.upsert_all(
|
||||
new_post_ids.map { |post_id| { user_id: user.id, post_id: } },
|
||||
unique_by: %i[user_id post_id],
|
||||
)
|
||||
|
||||
if user.faved_posts.count != old_user.faved_posts.count
|
||||
logger.error(
|
||||
"favs mismatch for #{user.name}: (#{user.faved_posts.count} != #{old_user.faved_posts.count})",
|
||||
)
|
||||
else
|
||||
user.migrated_user_favs_at = Time.current
|
||||
user.save!
|
||||
logger.info("migrated e621 user favs #{user.name} (#{new_post_ids.size})")
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_fa_users_favs
|
||||
Domain::User::FaUser
|
||||
.where_migrated_user_favs_at("is null")
|
||||
.find_each { |user| migrate_fa_user_favs(user) }
|
||||
end
|
||||
|
||||
sig { params(user: Domain::User::FaUser).void }
|
||||
def migrate_fa_user_favs(user)
|
||||
user_url_name = user.url_name
|
||||
old_user = Domain::Fa::User.find_by!(url_name: user_url_name)
|
||||
old_post_fa_ids = old_user.fav_posts.pluck(:fa_id)
|
||||
new_post_ids = Domain::Post::FaPost.where(fa_id: old_post_fa_ids).pluck(:id)
|
||||
|
||||
Domain::UserPostFav.upsert_all(
|
||||
new_post_ids.map { |post_id| { user_id: user.id, post_id: } },
|
||||
unique_by: %i[user_id post_id],
|
||||
)
|
||||
|
||||
if user.faved_posts.count != old_user.fav_posts.count
|
||||
logger.error(
|
||||
"favs mismatch for #{user.name}: (#{user.faved_posts.count} != #{old_user.fav_posts.count})",
|
||||
)
|
||||
else
|
||||
user.migrated_user_favs_at = Time.current
|
||||
user.save!
|
||||
logger.info("migrated fa user favs #{user.name} (#{new_post_ids.size})")
|
||||
end
|
||||
end
|
||||
|
||||
sig { void }
|
||||
def migrate_fa_users_followers
|
||||
Domain::User::FaUser
|
||||
.where_migrated_followers_at("is null")
|
||||
.find_each { |user| migrate_fa_user_followers(user) }
|
||||
end
|
||||
|
||||
sig { params(user: Domain::User::FaUser).void }
|
||||
def migrate_fa_user_followers(user)
|
||||
user_url_name = user.url_name
|
||||
old_user = Domain::Fa::User.find_by!(url_name: user_url_name)
|
||||
followed_user_url_names = old_user.follows.pluck(:url_name)
|
||||
new_user_ids =
|
||||
Domain::User::FaUser.where(url_name: followed_user_url_names).pluck(:id)
|
||||
|
||||
Domain::UserUserFollow.upsert_all(
|
||||
new_user_ids.map { |user_id| { from_id: user.id, to_id: user_id } },
|
||||
unique_by: %i[from_id to_id],
|
||||
)
|
||||
|
||||
if user.following_users.count != old_user.follows.count
|
||||
logger.error(
|
||||
"followers mismatch for #{user.name}: (#{user.following_users.count} != #{old_user.follows.count})",
|
||||
)
|
||||
else
|
||||
user.migrated_followers_at = Time.current
|
||||
user.save!
|
||||
logger.info(
|
||||
"migrated fa user followers #{user.name} (#{new_user_ids.size})",
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -3,29 +3,40 @@
|
||||
require "arel/visitors/to_sql"
|
||||
class Arel::Visitors::ToSql
|
||||
extend T::Sig
|
||||
|
||||
class UnquotedArelSqlLiteral < Arel::Nodes::SqlLiteral
|
||||
extend T::Sig
|
||||
sig { params(name_in_to_s: String, name_in_to_sql: String).void }
|
||||
def initialize(name_in_to_s, name_in_to_sql)
|
||||
super(name_in_to_s)
|
||||
@name_in_to_sql = name_in_to_sql
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def in_sql
|
||||
@name_in_to_sql
|
||||
end
|
||||
end
|
||||
|
||||
prepend(
|
||||
Module.new do
|
||||
extend T::Sig
|
||||
sig { params(o: T.untyped, collector: T.untyped).returns(T.untyped) }
|
||||
def visit_Arel_Attributes_Attribute(o, collector)
|
||||
join_name = o.relation.table_alias || o.relation.name
|
||||
ar_table = o.relation.instance_variable_get("@klass")
|
||||
if ar_table && ar_table < AttrJsonRecordAliases
|
||||
registry =
|
||||
T.cast(
|
||||
T.unsafe(ar_table).attr_json_registry,
|
||||
AttrJson::AttributeDefinition::Registry,
|
||||
)
|
||||
attribute_def =
|
||||
T.cast(
|
||||
registry[o.name.to_sym],
|
||||
T.nilable(AttrJson::AttributeDefinition),
|
||||
)
|
||||
if attribute_def
|
||||
attr_type =
|
||||
T.cast(
|
||||
attribute_def.type.type,
|
||||
T.any(Symbol, ActiveModel::Type::Value),
|
||||
)
|
||||
attr_type_cast = ar_table.json_attribute_type_cast(attr_type)
|
||||
column = "json_attributes->>'#{o.name}'"
|
||||
str =
|
||||
"((#{quote_table_name(join_name)}.#{column})#{attr_type_cast})"
|
||||
return collector << str
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(value: T.untyped).returns(String) }
|
||||
def quote_column_name(value)
|
||||
return value.in_sql if UnquotedArelSqlLiteral === value
|
||||
super(value)
|
||||
collector << quote_table_name(join_name) << "." <<
|
||||
quote_column_name(o.name)
|
||||
end
|
||||
end,
|
||||
)
|
||||
@@ -77,11 +88,42 @@ module AttrJsonRecordAliases
|
||||
extend T::Helpers
|
||||
requires_ancestor { T.class_of(ActiveRecord::Base) }
|
||||
|
||||
sig { params(attr_name: Symbol).void }
|
||||
def json_attributes_scope(attr_name)
|
||||
sig do
|
||||
params(type: T.any(Symbol, ActiveModel::Type::Value)).returns(String)
|
||||
end
|
||||
def json_attribute_type_cast(type)
|
||||
case type
|
||||
when :integer
|
||||
"::integer"
|
||||
when :string
|
||||
"::text"
|
||||
else
|
||||
""
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attr_name: Symbol,
|
||||
type: T.any(Symbol, ActiveModel::Type::Value),
|
||||
).returns(String)
|
||||
end
|
||||
def json_attribute_expression(attr_name, type)
|
||||
"json_attributes->>'#{attr_name}'"
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attr_name: Symbol,
|
||||
type: T.any(Symbol, ActiveModel::Type::Value),
|
||||
).void
|
||||
end
|
||||
def json_attributes_scope(attr_name, type)
|
||||
attribute_expression = json_attribute_expression(attr_name, type)
|
||||
db_type = json_attribute_type_cast(type)
|
||||
scope :"where_#{attr_name}",
|
||||
->(expr, *binds) do
|
||||
where("json_attributes->>'#{attr_name}' #{expr}", binds)
|
||||
where("(#{attribute_expression}#{db_type}) #{expr}", binds)
|
||||
end
|
||||
|
||||
scope :"order_#{attr_name}",
|
||||
@@ -89,28 +131,20 @@ module AttrJsonRecordAliases
|
||||
unless [:asc, :desc, nil].include?(dir)
|
||||
raise("invalid direction: #{dir}")
|
||||
end
|
||||
order(Arel.sql "json_attributes->>'#{attr_name}' #{dir}")
|
||||
order(Arel.sql("#{attribute_expression} #{dir}"))
|
||||
end
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
name: Symbol,
|
||||
attr_name: Symbol,
|
||||
type: T.any(Symbol, ActiveModel::Type::Value),
|
||||
options: T.untyped,
|
||||
).void
|
||||
end
|
||||
def attr_json(name, type, options)
|
||||
super(name, type, options)
|
||||
json_attributes_scope(name)
|
||||
self.attribute_aliases =
|
||||
self.attribute_aliases.merge(
|
||||
name.to_s =>
|
||||
Arel::Visitors::ToSql::UnquotedArelSqlLiteral.new(
|
||||
name.to_s,
|
||||
"json_attributes->>'#{name}'",
|
||||
),
|
||||
)
|
||||
def attr_json_scoped(attr_name, type, **options)
|
||||
T.unsafe(self).attr_json(attr_name, type, **options)
|
||||
json_attributes_scope(attr_name, type)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -87,18 +87,6 @@ class Domain::E621::Post < ReduxApplicationRecord
|
||||
ta.is_a?(Hash) ? ta : { "general" => ta }
|
||||
end
|
||||
|
||||
# sig { returns(T.nilable(HttpLogEntry)) }
|
||||
# def index_page_http_log_entry
|
||||
# if state_detail["last_index_page_id"].present?
|
||||
# HttpLogEntry.find_by(id: state_detail["last_index_page_id"])
|
||||
# end
|
||||
# end
|
||||
|
||||
# sig { returns(T.nilable(HttpLogEntry)) }
|
||||
# def index_page_http_log_entry
|
||||
# HttpLogEntry.find_by(id: last_index_page_id) if last_index_page_id.present?
|
||||
# end
|
||||
|
||||
sig { returns(T.nilable(Addressable::URI)) }
|
||||
def file_uri
|
||||
Addressable::URI.parse(self.file_url_str) if self.file_url_str.present?
|
||||
|
||||
@@ -4,23 +4,23 @@ class Domain::E621::User < ReduxApplicationRecord
|
||||
include AttrJsonRecordAliases
|
||||
include AttrJson::Record::QueryScopes
|
||||
|
||||
json_attributes_scope :scanned_favs_at
|
||||
json_attributes_scope :scanned_favs_status
|
||||
json_attributes_scope :num_other_favs_cached
|
||||
|
||||
validates_inclusion_of :scanned_favs_status,
|
||||
in: %w[ok error],
|
||||
if: :scanned_favs_status?
|
||||
|
||||
has_many :favs, class_name: "Domain::E621::Fav", inverse_of: :user
|
||||
attr_json :favs_are_hidden, :boolean
|
||||
has_many :faved_posts,
|
||||
class_name: "Domain::E621::Post",
|
||||
through: :favs,
|
||||
source: :post
|
||||
attr_json_scoped :favs_are_hidden, :boolean
|
||||
|
||||
# number of favorites that the user has, derived from scraped html
|
||||
# on /posts/<post_id>/favorites?page=<n>
|
||||
# Used to find users with a significant number of favorites
|
||||
attr_json :num_other_favs_cached, :integer
|
||||
attr_json :scanned_favs_status, :string
|
||||
attr_json :scanned_favs_at, :datetime
|
||||
attr_json_scoped :num_other_favs_cached, :integer
|
||||
attr_json_scoped :scanned_favs_status, :string
|
||||
attr_json_scoped :scanned_favs_at, :datetime
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def url_name
|
||||
|
||||
38
app/models/domain/post.rb
Normal file
38
app/models/domain/post.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
# typed: strict
|
||||
class Domain::Post < ReduxApplicationRecord
|
||||
extend T::Helpers
|
||||
include AttrJsonRecordAliases
|
||||
self.table_name = "domain_posts"
|
||||
abstract!
|
||||
|
||||
sig { returns(String) }
|
||||
def type
|
||||
super
|
||||
end
|
||||
|
||||
sig { params(value: String).returns(String) }
|
||||
def type=(value)
|
||||
super
|
||||
end
|
||||
|
||||
has_many :files,
|
||||
class_name: "::Domain::PostFile",
|
||||
inverse_of: :post,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :user_post_creations,
|
||||
class_name: "::Domain::UserPostCreation",
|
||||
inverse_of: :post,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :user_post_favs,
|
||||
class_name: "::Domain::UserPostFav",
|
||||
inverse_of: :post,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :faving_users, through: :user_post_favs, source: :user
|
||||
|
||||
sig { abstract.returns(T.nilable(String)) }
|
||||
def to_param
|
||||
end
|
||||
end
|
||||
59
app/models/domain/post/e621_post.rb
Normal file
59
app/models/domain/post/e621_post.rb
Normal file
@@ -0,0 +1,59 @@
|
||||
# typed: strict
|
||||
class Domain::Post::E621Post < Domain::Post
|
||||
class FileError
|
||||
include AttrJson::Model
|
||||
attr_json :retry_count, :integer
|
||||
attr_json :status_code, :integer
|
||||
attr_json :log_entry_id, :integer
|
||||
end
|
||||
|
||||
attr_json_scoped :state, :string
|
||||
attr_json_scoped :e621_id, :integer
|
||||
# When was the post's /posts/<post_id>/favorites pages scanned?
|
||||
# Used to identify users with a significant number of favorites, setting
|
||||
# their `num_other_favs_cached` attribute
|
||||
attr_json_scoped :scanned_post_favs_at, :datetime
|
||||
attr_json_scoped :rating, :string
|
||||
attr_json_scoped :tags_array, ActiveModel::Type::Value.new
|
||||
attr_json_scoped :flags_array, :string, array: true
|
||||
attr_json_scoped :pools_array, :string, array: true
|
||||
attr_json_scoped :sources_array, :string, array: true
|
||||
attr_json_scoped :artists_array, :string, array: true
|
||||
|
||||
attr_json_scoped :e621_updated_at, :datetime
|
||||
attr_json_scoped :parent_post_id, :integer
|
||||
attr_json_scoped :last_index_page_id, :integer
|
||||
attr_json_scoped :caused_by_entry_id, :integer
|
||||
attr_json_scoped :scan_log_entry_id, :integer
|
||||
attr_json_scoped :index_page_ids, :integer, array: true
|
||||
attr_json_scoped :prev_md5s, :string, array: true
|
||||
attr_json_scoped :scan_error, :string
|
||||
attr_json_scoped :file_error, FileError.to_type
|
||||
attr_json_scoped :uploader_user_id, :integer
|
||||
|
||||
belongs_to :parent_post, class_name: "Domain::Post::E621Post", optional: true
|
||||
belongs_to :uploader_user,
|
||||
class_name: "::Domain::User::E621User",
|
||||
inverse_of: :uploaded_posts,
|
||||
optional: true
|
||||
|
||||
has_one :file, class_name: "::Domain::PostFile", foreign_key: :post_id
|
||||
belongs_to :last_index_page, class_name: "HttpLogEntry", optional: true
|
||||
|
||||
validates :state, inclusion: { in: %w[ok removed scan_error file_error] }
|
||||
validates :rating, inclusion: { in: %w[s q e] }
|
||||
validates :e621_id, presence: true
|
||||
|
||||
after_initialize do
|
||||
self.state ||= "ok"
|
||||
self.flags_array ||= []
|
||||
self.pools_array ||= []
|
||||
self.sources_array ||= []
|
||||
self.artists_array ||= []
|
||||
end
|
||||
|
||||
sig { override.returns(T.nilable(String)) }
|
||||
def to_param
|
||||
"e621/#{self.e621_id}" if self.e621_id.present?
|
||||
end
|
||||
end
|
||||
56
app/models/domain/post/fa_post.rb
Normal file
56
app/models/domain/post/fa_post.rb
Normal file
@@ -0,0 +1,56 @@
|
||||
# typed: strict
|
||||
class Domain::Post::FaPost < Domain::Post
|
||||
include AttrJsonRecordAliases
|
||||
|
||||
attr_json_scoped :title, :string
|
||||
attr_json_scoped :state, :string
|
||||
attr_json_scoped :fa_id, :integer
|
||||
attr_json_scoped :category, :string
|
||||
attr_json_scoped :theme, :string
|
||||
attr_json_scoped :species, :string
|
||||
attr_json_scoped :gender, :string
|
||||
attr_json_scoped :description, :string
|
||||
attr_json_scoped :keywords, :string, array: true, default: []
|
||||
attr_json_scoped :num_favorites, :integer
|
||||
attr_json_scoped :num_comments, :integer
|
||||
attr_json_scoped :num_views, :integer
|
||||
attr_json_scoped :posted_at, :datetime
|
||||
attr_json_scoped :scanned_at, :datetime
|
||||
attr_json_scoped :scan_file_error, :string
|
||||
attr_json :last_user_page_id, :integer
|
||||
attr_json :last_submission_page_id, :integer
|
||||
attr_json :first_browse_page_id, :integer
|
||||
attr_json :first_gallery_page_id, :integer
|
||||
attr_json :first_seen_entry_id, :integer
|
||||
|
||||
belongs_to :last_user_page, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :last_submission_page, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :first_browse_page, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :first_gallery_page, class_name: "::HttpLogEntry", optional: true
|
||||
belongs_to :first_seen_entry, class_name: "::HttpLogEntry", optional: true
|
||||
|
||||
has_one :user_post_creation,
|
||||
class_name: "::Domain::UserPostCreation",
|
||||
inverse_of: :post,
|
||||
dependent: :destroy
|
||||
|
||||
has_one :creator,
|
||||
through: :user_post_creation,
|
||||
source: :user,
|
||||
class_name: "::Domain::User::FaUser"
|
||||
|
||||
has_one :file,
|
||||
class_name: "::Domain::PostFile",
|
||||
inverse_of: :post,
|
||||
dependent: :destroy
|
||||
|
||||
after_initialize { self.state ||= "ok" }
|
||||
|
||||
validates :state, inclusion: { in: %w[ok removed scan_error file_error] }
|
||||
validates :fa_id, presence: true
|
||||
|
||||
sig { override.returns(T.nilable(String)) }
|
||||
def to_param
|
||||
"fa/#{self.fa_id}" if self.fa_id.present?
|
||||
end
|
||||
end
|
||||
16
app/models/domain/post_file.rb
Normal file
16
app/models/domain/post_file.rb
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: strict
|
||||
class Domain::PostFile < ReduxApplicationRecord
|
||||
include AttrJsonRecordAliases
|
||||
self.table_name = "domain_post_files"
|
||||
|
||||
belongs_to :post, class_name: "::Domain::Post", inverse_of: :files
|
||||
belongs_to :log_entry, class_name: "::HttpLogEntry"
|
||||
|
||||
attr_json_scoped :state, :string
|
||||
attr_json_scoped :url_str, :string
|
||||
attr_json_scoped :error, :string
|
||||
|
||||
validates :state, inclusion: { in: %w[ok error] }
|
||||
|
||||
after_initialize { self.state ||= "ok" }
|
||||
end
|
||||
55
app/models/domain/user.rb
Normal file
55
app/models/domain/user.rb
Normal file
@@ -0,0 +1,55 @@
|
||||
# typed: strict
|
||||
class Domain::User < ReduxApplicationRecord
|
||||
extend T::Helpers
|
||||
include AttrJsonRecordAliases
|
||||
self.table_name = "domain_users"
|
||||
abstract!
|
||||
|
||||
sig { returns(String) }
|
||||
def type
|
||||
super
|
||||
end
|
||||
|
||||
sig { params(value: String).returns(String) }
|
||||
def type=(value)
|
||||
super
|
||||
end
|
||||
|
||||
attr_json_scoped :migrated_user_favs_at, :datetime
|
||||
|
||||
has_many :user_post_creations,
|
||||
class_name: "::Domain::UserPostCreation",
|
||||
inverse_of: :user,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :user_post_favs,
|
||||
class_name: "::Domain::UserPostFav",
|
||||
inverse_of: :user,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :user_user_follows_from,
|
||||
class_name: "::Domain::UserUserFollow",
|
||||
foreign_key: :from_id,
|
||||
inverse_of: :from,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :user_user_follows_to,
|
||||
class_name: "::Domain::UserUserFollow",
|
||||
foreign_key: :to_id,
|
||||
inverse_of: :to,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :faved_posts, through: :user_post_favs, source: :post
|
||||
has_many :following_users, through: :user_user_follows_to, source: :to
|
||||
has_many :followed_by_users, through: :user_user_follows_from, source: :from
|
||||
|
||||
has_one :avatar,
|
||||
-> { order(created_at: :desc) },
|
||||
class_name: "::Domain::UserAvatar",
|
||||
inverse_of: :user
|
||||
|
||||
has_many :avatars,
|
||||
class_name: "::Domain::UserAvatar",
|
||||
inverse_of: :user,
|
||||
dependent: :destroy
|
||||
end
|
||||
22
app/models/domain/user/e621_user.rb
Normal file
22
app/models/domain/user/e621_user.rb
Normal file
@@ -0,0 +1,22 @@
|
||||
# typed: strict
|
||||
class Domain::User::E621User < Domain::User
|
||||
attr_json_scoped :e621_id, :integer
|
||||
attr_json_scoped :name, :string
|
||||
attr_json_scoped :favs_are_hidden, :boolean
|
||||
attr_json_scoped :num_other_favs_cached, :integer
|
||||
attr_json_scoped :scanned_favs_status, :string
|
||||
attr_json_scoped :scanned_favs_at, :datetime
|
||||
|
||||
has_many :uploaded_posts,
|
||||
class_name: "::Domain::Post::E621Post",
|
||||
foreign_key: :uploader_user_id,
|
||||
inverse_of: :uploader_user
|
||||
|
||||
validates :scanned_favs_status,
|
||||
inclusion: {
|
||||
in: %w[ok error],
|
||||
if: :scanned_favs_status?,
|
||||
}
|
||||
validates :e621_id, presence: true
|
||||
validates :name, presence: true
|
||||
end
|
||||
14
app/models/domain/user/fa_user.rb
Normal file
14
app/models/domain/user/fa_user.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# typed: strict
|
||||
class Domain::User::FaUser < Domain::User
|
||||
has_many :posts,
|
||||
class_name: "::Domain::Fa::Post",
|
||||
through: :user_post_creations,
|
||||
source: :post
|
||||
|
||||
attr_json_scoped :name, :string
|
||||
attr_json_scoped :url_name, :string
|
||||
attr_json_scoped :migrated_followers_at, :datetime
|
||||
|
||||
validates :name, presence: true
|
||||
validates :url_name, presence: true
|
||||
end
|
||||
13
app/models/domain/user_avatar.rb
Normal file
13
app/models/domain/user_avatar.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
# typed: strict
|
||||
class Domain::UserAvatar < ReduxApplicationRecord
|
||||
include AttrJsonRecordAliases
|
||||
self.table_name = "domain_user_avatars"
|
||||
belongs_to :user, class_name: "::Domain::User", inverse_of: :avatar
|
||||
|
||||
attr_json :url, :string
|
||||
attr_json :state, :string
|
||||
attr_json :downloaded_at, :datetime
|
||||
|
||||
attr_json :log_entry_id, :integer
|
||||
belongs_to :log_entry, class_name: "::HttpLogEntry", optional: true
|
||||
end
|
||||
14
app/models/domain/user_post_creation.rb
Normal file
14
app/models/domain/user_post_creation.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
class Domain::UserPostCreation < ReduxApplicationRecord
|
||||
include AttrJsonRecordAliases
|
||||
self.table_name = "domain_user_post_creations"
|
||||
self.primary_key = %i[user_id post_id]
|
||||
|
||||
validates :user_id, uniqueness: { scope: :post_id }
|
||||
|
||||
belongs_to :post,
|
||||
class_name: "::Domain::Post",
|
||||
inverse_of: :user_post_creations
|
||||
belongs_to :user,
|
||||
class_name: "::Domain::User",
|
||||
inverse_of: :user_post_creations
|
||||
end
|
||||
7
app/models/domain/user_post_fav.rb
Normal file
7
app/models/domain/user_post_fav.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
class Domain::UserPostFav < ReduxApplicationRecord
|
||||
self.table_name = "domain_user_post_favs"
|
||||
self.primary_key = %i[user_id post_id]
|
||||
|
||||
belongs_to :user, class_name: "Domain::User", inverse_of: :user_post_favs
|
||||
belongs_to :post, class_name: "Domain::Post", inverse_of: :user_post_favs
|
||||
end
|
||||
7
app/models/domain/user_user_follow.rb
Normal file
7
app/models/domain/user_user_follow.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
class Domain::UserUserFollow < ReduxApplicationRecord
|
||||
self.table_name = "domain_user_user_follows"
|
||||
self.primary_key = %i[from_id to_id]
|
||||
|
||||
belongs_to :from, class_name: "Domain::User"
|
||||
belongs_to :to, class_name: "Domain::User"
|
||||
end
|
||||
@@ -2,6 +2,7 @@
|
||||
class ReduxApplicationRecord < ActiveRecord::Base
|
||||
extend T::Sig
|
||||
include HasPrometheusClient
|
||||
include HasColorLogger
|
||||
|
||||
# hack to make sorbet recognize the `@after_save_deferred_jobs` instance variable
|
||||
sig { params(attributes: T.untyped).void }
|
||||
@@ -11,7 +12,6 @@ class ReduxApplicationRecord < ActiveRecord::Base
|
||||
end
|
||||
|
||||
self.abstract_class = true
|
||||
logger.level = Logger::ERROR
|
||||
|
||||
after_initialize { observe(:initialize) }
|
||||
after_create { observe(:create) }
|
||||
|
||||
@@ -61,6 +61,9 @@ Rails.application.configure do
|
||||
# Highlight code that triggered database queries in logs.
|
||||
config.active_record.verbose_query_logs = true
|
||||
|
||||
ActiveRecord::Base.logger = Logger.new(STDOUT)
|
||||
ActiveRecord::Base.logger.level = :error
|
||||
|
||||
# Suppress logger output for asset requests.
|
||||
config.assets.quiet = true
|
||||
|
||||
|
||||
163
db/migrate/20250203235035_create_domain_posts.rb
Normal file
163
db/migrate/20250203235035_create_domain_posts.rb
Normal file
@@ -0,0 +1,163 @@
|
||||
# typed: strict
|
||||
#
|
||||
class CreateDomainPosts < ActiveRecord::Migration[7.2]
|
||||
extend T::Sig
|
||||
|
||||
sig { void }
|
||||
def change
|
||||
reversible do |dir|
|
||||
dir.up do
|
||||
execute "CREATE TYPE domain_post_type AS ENUM ('Domain::Post::FaPost', 'Domain::Post::E621Post')"
|
||||
end
|
||||
|
||||
dir.down { execute "DROP TYPE domain_post_type" }
|
||||
end
|
||||
|
||||
create_table :domain_posts do |t|
|
||||
t.enum :type, null: false, enum_type: "domain_post_type"
|
||||
t.jsonb :json_attributes, default: {}
|
||||
t.timestamps
|
||||
|
||||
t.index :type
|
||||
end
|
||||
|
||||
reversible do |dir|
|
||||
dir.up do
|
||||
execute "CREATE TYPE domain_user_type AS ENUM ('Domain::User::FaUser', 'Domain::User::E621User')"
|
||||
end
|
||||
|
||||
dir.down { execute "DROP TYPE domain_user_type" }
|
||||
end
|
||||
|
||||
create_table :domain_users do |t|
|
||||
t.enum :type, null: false, enum_type: "domain_user_type"
|
||||
t.jsonb :json_attributes, default: {}
|
||||
t.timestamps
|
||||
|
||||
t.index :type
|
||||
end
|
||||
|
||||
create_table :domain_user_avatars do |t|
|
||||
t.string :type, null: false
|
||||
t.references :user, null: false, foreign_key: { to_table: :domain_users }
|
||||
t.jsonb :json_attributes, default: {}
|
||||
t.timestamps
|
||||
|
||||
t.index :type
|
||||
end
|
||||
|
||||
create_table :domain_post_files do |t|
|
||||
t.references :post, null: false, foreign_key: { to_table: :domain_posts }
|
||||
t.references :log_entry,
|
||||
null: false,
|
||||
foreign_key: {
|
||||
to_table: :http_log_entries,
|
||||
}
|
||||
t.jsonb :json_attributes, default: {}
|
||||
t.timestamps
|
||||
end
|
||||
|
||||
create_table :domain_user_post_creations, id: false do |t|
|
||||
t.references :user,
|
||||
null: false,
|
||||
foreign_key: {
|
||||
to_table: :domain_users,
|
||||
},
|
||||
index: false
|
||||
|
||||
t.references :post,
|
||||
null: false,
|
||||
foreign_key: {
|
||||
to_table: :domain_posts,
|
||||
},
|
||||
index: false
|
||||
|
||||
t.index %i[user_id post_id], unique: true
|
||||
t.index %i[post_id user_id]
|
||||
end
|
||||
|
||||
create_table :domain_user_post_favs, id: false do |t|
|
||||
t.references :user,
|
||||
null: false,
|
||||
foreign_key: {
|
||||
to_table: :domain_users,
|
||||
},
|
||||
index: false
|
||||
t.references :post,
|
||||
null: false,
|
||||
foreign_key: {
|
||||
to_table: :domain_posts,
|
||||
},
|
||||
index: false
|
||||
t.boolean :removed, null: false, default: false
|
||||
t.index %i[user_id post_id], unique: true
|
||||
t.index %i[post_id user_id]
|
||||
end
|
||||
|
||||
create_table :domain_user_user_follows, id: false do |t|
|
||||
t.references :from,
|
||||
null: false,
|
||||
foreign_key: {
|
||||
to_table: :domain_users,
|
||||
},
|
||||
index: false
|
||||
t.references :to,
|
||||
null: false,
|
||||
foreign_key: {
|
||||
to_table: :domain_users,
|
||||
},
|
||||
index: false
|
||||
t.index %i[from_id to_id], unique: true
|
||||
t.index %i[to_id from_id]
|
||||
end
|
||||
|
||||
reversible do |dir|
|
||||
dir.up do
|
||||
# timestamps are formatted like `2001-02-03T04:05:06Z`
|
||||
# aka ISO 8601
|
||||
execute <<~SQL
|
||||
CREATE OR REPLACE FUNCTION f_cast_isots(text)
|
||||
RETURNS timestamptz AS
|
||||
$$SELECT to_timestamp($1, 'YYYY-MM-DDTHH24:MI:SSZ')$$
|
||||
LANGUAGE sql IMMUTABLE;
|
||||
SQL
|
||||
end
|
||||
|
||||
dir.down { execute "DROP FUNCTION f_cast_isots(text)" }
|
||||
end
|
||||
|
||||
add_index :domain_posts,
|
||||
"(cast(json_attributes->>'fa_id' as integer))",
|
||||
where: "type = 'Domain::Post::FaPost'",
|
||||
name: "idx_domain_fa_posts_on_fa_id",
|
||||
unique: true
|
||||
|
||||
add_index :domain_posts,
|
||||
"((json_attributes->>'e621_id')::integer)",
|
||||
where: "type = 'Domain::Post::E621Post'",
|
||||
name: "idx_domain_e621_posts_on_e621_id",
|
||||
unique: true
|
||||
|
||||
add_index :domain_posts,
|
||||
"((json_attributes->>'uploader_user_id')::integer)",
|
||||
where: "type = 'Domain::Post::E621Post'",
|
||||
name: "idx_domain_e621_posts_on_uploader_user_id",
|
||||
unique: true
|
||||
|
||||
add_index :domain_users,
|
||||
"((json_attributes->>'url_name')::text)",
|
||||
where: "type = 'Domain::User::FaUser'",
|
||||
name: "idx_domain_fa_users_on_url_name",
|
||||
unique: true
|
||||
|
||||
add_index :domain_users,
|
||||
"((json_attributes->>'e621_id')::integer)",
|
||||
where: "type = 'Domain::User::E621User'",
|
||||
name: "idx_domain_e621_users_on_e621_id",
|
||||
unique: true
|
||||
|
||||
add_index :domain_users,
|
||||
"(json_attributes->>'migrated_user_favs_at')",
|
||||
name: "idx_domain_users_on_migrated_user_favs_at"
|
||||
end
|
||||
end
|
||||
449
db/structure.sql
449
db/structure.sql
@@ -93,6 +93,26 @@ CREATE EXTENSION IF NOT EXISTS vector WITH SCHEMA public;
|
||||
COMMENT ON EXTENSION vector IS 'vector data type and ivfflat access method';
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_type; Type: TYPE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TYPE public.domain_post_type AS ENUM (
|
||||
'Domain::Post::FaPost',
|
||||
'Domain::Post::E621Post'
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_type; Type: TYPE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TYPE public.domain_user_type AS ENUM (
|
||||
'Domain::User::FaUser',
|
||||
'Domain::User::E621User'
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: postable_type; Type: TYPE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -105,6 +125,15 @@ CREATE TYPE public.postable_type AS ENUM (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: f_cast_isots(text); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE FUNCTION public.f_cast_isots(text) RETURNS timestamp with time zone
|
||||
LANGUAGE sql IMMUTABLE
|
||||
AS $_$SELECT to_timestamp($1, 'YYYY-MM-DDTHH24:MI:SSZ')$_$;
|
||||
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_table_access_method = heap;
|
||||
@@ -2626,6 +2655,71 @@ CREATE SEQUENCE public.domain_inkbunny_users_id_seq
|
||||
ALTER SEQUENCE public.domain_inkbunny_users_id_seq OWNED BY public.domain_inkbunny_users.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_files; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_post_files (
|
||||
id bigint NOT NULL,
|
||||
post_id bigint NOT NULL,
|
||||
log_entry_id bigint NOT NULL,
|
||||
json_attributes jsonb DEFAULT '{}'::jsonb,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_files_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.domain_post_files_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_files_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.domain_post_files_id_seq OWNED BY public.domain_post_files.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_posts; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_posts (
|
||||
id bigint NOT NULL,
|
||||
type public.domain_post_type NOT NULL,
|
||||
json_attributes jsonb DEFAULT '{}'::jsonb,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_posts_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.domain_posts_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_posts_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.domain_posts_id_seq OWNED BY public.domain_posts.id;
|
||||
|
||||
|
||||
SET default_tablespace = mirai;
|
||||
|
||||
--
|
||||
@@ -2759,6 +2853,102 @@ ALTER SEQUENCE public.domain_twitter_users_id_seq OWNED BY public.domain_twitter
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
--
|
||||
-- Name: domain_user_avatars; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_user_avatars (
|
||||
id bigint NOT NULL,
|
||||
type character varying NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
json_attributes jsonb DEFAULT '{}'::jsonb,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_avatars_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.domain_user_avatars_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_avatars_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.domain_user_avatars_id_seq OWNED BY public.domain_user_avatars.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_post_creations; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_user_post_creations (
|
||||
user_id bigint NOT NULL,
|
||||
post_id bigint NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_post_favs; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_user_post_favs (
|
||||
user_id bigint NOT NULL,
|
||||
post_id bigint NOT NULL,
|
||||
removed boolean DEFAULT false NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_user_follows; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_user_user_follows (
|
||||
from_id bigint NOT NULL,
|
||||
to_id bigint NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_users (
|
||||
id bigint NOT NULL,
|
||||
type public.domain_user_type NOT NULL,
|
||||
json_attributes jsonb DEFAULT '{}'::jsonb,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.domain_users_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.domain_users_id_seq OWNED BY public.domain_users.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: flat_sst_entries; Type: TABLE; Schema: public; Owner: -
|
||||
--
|
||||
@@ -4195,6 +4385,20 @@ ALTER TABLE ONLY public.domain_inkbunny_tags ALTER COLUMN id SET DEFAULT nextval
|
||||
ALTER TABLE ONLY public.domain_inkbunny_users ALTER COLUMN id SET DEFAULT nextval('public.domain_inkbunny_users_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_files id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_post_files ALTER COLUMN id SET DEFAULT nextval('public.domain_post_files_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_posts id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_posts ALTER COLUMN id SET DEFAULT nextval('public.domain_posts_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_twitter_tweets id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -4216,6 +4420,20 @@ ALTER TABLE ONLY public.domain_twitter_user_versions ALTER COLUMN id SET DEFAULT
|
||||
ALTER TABLE ONLY public.domain_twitter_users ALTER COLUMN id SET DEFAULT nextval('public.domain_twitter_users_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_avatars id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_avatars ALTER COLUMN id SET DEFAULT nextval('public.domain_user_avatars_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_users ALTER COLUMN id SET DEFAULT nextval('public.domain_users_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: global_states id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -4928,6 +5146,22 @@ ALTER TABLE ONLY public.domain_inkbunny_users
|
||||
ADD CONSTRAINT domain_inkbunny_users_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_files domain_post_files_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_post_files
|
||||
ADD CONSTRAINT domain_post_files_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_posts domain_posts_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_posts
|
||||
ADD CONSTRAINT domain_posts_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
SET default_tablespace = mirai;
|
||||
|
||||
--
|
||||
@@ -4956,6 +5190,22 @@ ALTER TABLE ONLY public.domain_twitter_users
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
--
|
||||
-- Name: domain_user_avatars domain_user_avatars_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_avatars
|
||||
ADD CONSTRAINT domain_user_avatars_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users domain_users_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_users
|
||||
ADD CONSTRAINT domain_users_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: global_states global_states_pkey; Type: CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -5098,6 +5348,48 @@ CREATE INDEX domain_fa_users_url_name_idx ON public.domain_fa_users USING gist (
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
--
|
||||
-- Name: idx_domain_e621_posts_on_e621_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX idx_domain_e621_posts_on_e621_id ON public.domain_posts USING btree ((((json_attributes ->> 'e621_id'::text))::integer)) WHERE (type = 'Domain::Post::E621Post'::public.domain_post_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_e621_posts_on_uploader_user_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX idx_domain_e621_posts_on_uploader_user_id ON public.domain_posts USING btree ((((json_attributes ->> 'uploader_user_id'::text))::integer)) WHERE (type = 'Domain::Post::E621Post'::public.domain_post_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_e621_users_on_e621_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX idx_domain_e621_users_on_e621_id ON public.domain_users USING btree ((((json_attributes ->> 'e621_id'::text))::integer)) WHERE (type = 'Domain::User::E621User'::public.domain_user_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_fa_posts_on_fa_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX idx_domain_fa_posts_on_fa_id ON public.domain_posts USING btree ((((json_attributes ->> 'fa_id'::text))::integer)) WHERE (type = 'Domain::Post::FaPost'::public.domain_post_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_fa_users_on_url_name; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX idx_domain_fa_users_on_url_name ON public.domain_users USING btree (((json_attributes ->> 'url_name'::text))) WHERE (type = 'Domain::User::FaUser'::public.domain_user_type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_domain_users_on_migrated_user_favs_at; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX idx_domain_users_on_migrated_user_favs_at ON public.domain_users USING btree (((json_attributes ->> 'migrated_user_favs_at'::text)));
|
||||
|
||||
|
||||
--
|
||||
-- Name: idx_on_good_job_execution_id_685ddb5560; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -6375,6 +6667,27 @@ CREATE UNIQUE INDEX index_domain_inkbunny_users_on_ib_user_id ON public.domain_i
|
||||
CREATE INDEX index_domain_inkbunny_users_on_shallow_update_log_entry_id ON public.domain_inkbunny_users USING btree (shallow_update_log_entry_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_post_files_on_log_entry_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_post_files_on_log_entry_id ON public.domain_post_files USING btree (log_entry_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_post_files_on_post_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_post_files_on_post_id ON public.domain_post_files USING btree (post_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_posts_on_type; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_posts_on_type ON public.domain_posts USING btree (type);
|
||||
|
||||
|
||||
SET default_tablespace = mirai;
|
||||
|
||||
--
|
||||
@@ -6435,6 +6748,69 @@ CREATE UNIQUE INDEX index_domain_twitter_users_on_tw_id ON public.domain_twitter
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_avatars_on_type; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_avatars_on_type ON public.domain_user_avatars USING btree (type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_avatars_on_user_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_avatars_on_user_id ON public.domain_user_avatars USING btree (user_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_post_creations_on_post_id_and_user_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_post_creations_on_post_id_and_user_id ON public.domain_user_post_creations USING btree (post_id, user_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_post_creations_on_user_id_and_post_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX index_domain_user_post_creations_on_user_id_and_post_id ON public.domain_user_post_creations USING btree (user_id, post_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_post_favs_on_post_id_and_user_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_post_favs_on_post_id_and_user_id ON public.domain_user_post_favs USING btree (post_id, user_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_post_favs_on_user_id_and_post_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX index_domain_user_post_favs_on_user_id_and_post_id ON public.domain_user_post_favs USING btree (user_id, post_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_user_follows_on_from_id_and_to_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX index_domain_user_user_follows_on_from_id_and_to_id ON public.domain_user_user_follows USING btree (from_id, to_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_user_follows_on_to_id_and_from_id; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_user_follows_on_to_id_and_from_id ON public.domain_user_user_follows USING btree (to_id, from_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_users_on_type; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_users_on_type ON public.domain_users USING btree (type);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_e621_posts_on_scanned_post_favs_at; Type: INDEX; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7669,6 +8045,14 @@ ALTER TABLE ONLY public.http_log_entries
|
||||
ADD CONSTRAINT fk_rails_42f35e9da0 FOREIGN KEY (response_headers_id) REFERENCES public.http_log_entry_headers(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_user_follows fk_rails_4b2ab65400; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_user_follows
|
||||
ADD CONSTRAINT fk_rails_4b2ab65400 FOREIGN KEY (from_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_fa_favs fk_rails_503a610bac; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7725,6 +8109,14 @@ ALTER TABLE ONLY public.domain_fa_user_avatar_versions
|
||||
ADD CONSTRAINT fk_rails_77fefb9ac3 FOREIGN KEY (item_id) REFERENCES public.domain_fa_user_avatars(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_files fk_rails_7eb6ae5fa3; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_post_files
|
||||
ADD CONSTRAINT fk_rails_7eb6ae5fa3 FOREIGN KEY (post_id) REFERENCES public.domain_posts(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_inkbunny_posts fk_rails_82ffd77f0c; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7757,6 +8149,22 @@ ALTER TABLE ONLY public.good_job_execution_log_lines_collections
|
||||
ADD CONSTRAINT fk_rails_98c288034f FOREIGN KEY (good_job_execution_id) REFERENCES public.good_job_executions(id) ON DELETE CASCADE;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_post_creations fk_rails_9f4b85bc57; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_post_creations
|
||||
ADD CONSTRAINT fk_rails_9f4b85bc57 FOREIGN KEY (user_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_user_follows fk_rails_b45e6e3979; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_user_follows
|
||||
ADD CONSTRAINT fk_rails_b45e6e3979 FOREIGN KEY (to_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_inkbunny_posts fk_rails_c2d9f4b382; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7781,6 +8189,22 @@ ALTER TABLE ONLY public.http_log_entries
|
||||
ADD CONSTRAINT fk_rails_c5f7bcff78 FOREIGN KEY (caused_by_id) REFERENCES public.http_log_entries(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_post_favs fk_rails_c79733f291; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_post_favs
|
||||
ADD CONSTRAINT fk_rails_c79733f291 FOREIGN KEY (user_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_post_favs fk_rails_ce892be9a6; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_post_favs
|
||||
ADD CONSTRAINT fk_rails_ce892be9a6 FOREIGN KEY (post_id) REFERENCES public.domain_posts(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: http_log_entries fk_rails_cf47f64c57; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7789,6 +8213,14 @@ ALTER TABLE ONLY public.http_log_entries
|
||||
ADD CONSTRAINT fk_rails_cf47f64c57 FOREIGN KEY (request_headers_id) REFERENCES public.http_log_entry_headers(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_post_files fk_rails_d059c07f77; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_post_files
|
||||
ADD CONSTRAINT fk_rails_d059c07f77 FOREIGN KEY (log_entry_id) REFERENCES public.http_log_entries(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_inkbunny_users fk_rails_d6ea75e723; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7821,6 +8253,14 @@ ALTER TABLE ONLY public.domain_inkbunny_follows
|
||||
ADD CONSTRAINT fk_rails_ee473fedf4 FOREIGN KEY (follower_id) REFERENCES public.domain_inkbunny_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_post_creations fk_rails_f3c2231511; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_post_creations
|
||||
ADD CONSTRAINT fk_rails_f3c2231511 FOREIGN KEY (post_id) REFERENCES public.domain_posts(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_fa_posts fk_rails_f5d5c17363; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7829,6 +8269,14 @@ ALTER TABLE ONLY public.domain_fa_posts
|
||||
ADD CONSTRAINT fk_rails_f5d5c17363 FOREIGN KEY (file_id) REFERENCES public.http_log_entries(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_avatars fk_rails_f89912a20f; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_avatars
|
||||
ADD CONSTRAINT fk_rails_f89912a20f FOREIGN KEY (user_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_twitter_tweets on_author_id; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -7844,6 +8292,7 @@ ALTER TABLE ONLY public.domain_twitter_tweets
|
||||
SET search_path TO "$user", public;
|
||||
|
||||
INSERT INTO "schema_migrations" (version) VALUES
|
||||
('20250203235035'),
|
||||
('20250131060105'),
|
||||
('20250131055824'),
|
||||
('20250129174128'),
|
||||
|
||||
@@ -20,7 +20,8 @@ namespace :e621 do
|
||||
task scan_user_favs: :environment do
|
||||
while user =
|
||||
Domain::E621::User
|
||||
.where(scanned_favs_at: nil)
|
||||
.where_scanned_favs_at("is null")
|
||||
.where_num_other_favs_cached("< ?", 200)
|
||||
.order("RANDOM()")
|
||||
.take
|
||||
Domain::E621::Job::ScanUserFavsJob.perform_now(user: user)
|
||||
@@ -78,7 +79,19 @@ namespace :e621 do
|
||||
|
||||
desc "debug sql"
|
||||
task debug_sql: :environment do
|
||||
puts Domain::E621::Post.where(last_index_page_id: nil).to_sql
|
||||
binding.pry
|
||||
# Domain::Post::E621Post.where(e621_id: 5350363)
|
||||
# puts Domain::Post::E621Post.where(e621_id: 5_350_363).explain.inspect
|
||||
# puts Domain::Post::FaPost.where(fa_id: 52_801_830).explain.inspect
|
||||
# puts Domain::Fa::Post.where(fa_id: 52_801_830).explain.inspect
|
||||
puts Domain::Fa::Post
|
||||
.joins(
|
||||
"
|
||||
LEFT JOIN domain_posts ON domain_fa_posts.fa_id =
|
||||
(domain_posts.json_attributes->>'fa_id')::integer
|
||||
",
|
||||
)
|
||||
.where(domain_posts: { id: nil, type: "Domain::Post::FaPost" })
|
||||
.explain
|
||||
.inspect
|
||||
end
|
||||
end
|
||||
|
||||
6
sorbet/rbi/dsl/blob_entry.rbi
generated
6
sorbet/rbi/dsl/blob_entry.rbi
generated
@@ -11,12 +11,18 @@ class BlobEntry
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/blob_file.rbi
generated
6
sorbet/rbi/dsl/blob_file.rbi
generated
@@ -11,12 +11,18 @@ class BlobFile
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig { params(attributes: T.untyped, block: T.nilable(T.proc.params(object: ::BlobFile).void)).returns(::BlobFile) }
|
||||
def new(attributes = nil, &block); end
|
||||
|
||||
|
||||
6
sorbet/rbi/dsl/domain/e621/fav.rbi
generated
6
sorbet/rbi/dsl/domain/e621/fav.rbi
generated
@@ -11,12 +11,18 @@ class Domain::E621::Fav
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/e621/post.rbi
generated
6
sorbet/rbi/dsl/domain/e621/post.rbi
generated
@@ -15,6 +15,9 @@ class Domain::E621::Post
|
||||
sig { returns(T.nilable(Domain::E621::Post::FileError)) }
|
||||
def file_error; end
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
@@ -42,6 +45,9 @@ class Domain::E621::Post
|
||||
sig { returns(T::Array[Symbol]) }
|
||||
def attr_json_registry; end
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/e621/tag.rbi
generated
6
sorbet/rbi/dsl/domain/e621/tag.rbi
generated
@@ -11,12 +11,18 @@ class Domain::E621::Tag
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/e621/tagging.rbi
generated
6
sorbet/rbi/dsl/domain/e621/tagging.rbi
generated
@@ -12,6 +12,9 @@ class Domain::E621::Tagging
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
@@ -21,6 +24,9 @@ class Domain::E621::Tagging
|
||||
sig { returns(T::Hash[T.any(String, Symbol), Integer]) }
|
||||
def categories; end
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
32
sorbet/rbi/dsl/domain/e621/user.rbi
generated
32
sorbet/rbi/dsl/domain/e621/user.rbi
generated
@@ -11,6 +11,9 @@ class Domain::E621::User
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
@@ -38,6 +41,9 @@ class Domain::E621::User
|
||||
sig { returns(T::Array[Symbol]) }
|
||||
def attr_json_registry; end
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
@@ -427,6 +433,20 @@ class Domain::E621::User
|
||||
sig { params(ids: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
||||
def fav_ids=(ids); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def faved_post_ids; end
|
||||
|
||||
sig { params(ids: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
||||
def faved_post_ids=(ids); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::E621::User` class because it declared `has_many :faved_posts, through: :favs`.
|
||||
# 🔗 [Rails guide for `has_many_through` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association)
|
||||
sig { returns(::Domain::E621::Post::PrivateCollectionProxy) }
|
||||
def faved_posts; end
|
||||
|
||||
sig { params(value: T::Enumerable[::Domain::E621::Post]).void }
|
||||
def faved_posts=(value); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::E621::User` class because it declared `has_many :favs`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::E621::Fav::PrivateCollectionProxy) }
|
||||
@@ -533,6 +553,9 @@ class Domain::E621::User
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def order(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def order_favs_are_hidden(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def order_num_other_favs_cached(*args, &blk); end
|
||||
|
||||
@@ -585,6 +608,9 @@ class Domain::E621::User
|
||||
sig { params(args: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def where(*args); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def where_favs_are_hidden(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateAssociationRelation) }
|
||||
def where_num_other_favs_cached(*args, &blk); end
|
||||
|
||||
@@ -1360,6 +1386,9 @@ class Domain::E621::User
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def order(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def order_favs_are_hidden(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def order_num_other_favs_cached(*args, &blk); end
|
||||
|
||||
@@ -1412,6 +1441,9 @@ class Domain::E621::User
|
||||
sig { params(args: T.untyped).returns(PrivateRelation) }
|
||||
def where(*args); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def where_favs_are_hidden(*args, &blk); end
|
||||
|
||||
sig { params(args: T.untyped, blk: T.untyped).returns(PrivateRelation) }
|
||||
def where_num_other_favs_cached(*args, &blk); end
|
||||
|
||||
|
||||
6
sorbet/rbi/dsl/domain/fa/fav.rbi
generated
6
sorbet/rbi/dsl/domain/fa/fav.rbi
generated
@@ -11,12 +11,18 @@ class Domain::Fa::Fav
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/fa/follow.rbi
generated
6
sorbet/rbi/dsl/domain/fa/follow.rbi
generated
@@ -11,12 +11,18 @@ class Domain::Fa::Follow
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/fa/post.rbi
generated
6
sorbet/rbi/dsl/domain/fa/post.rbi
generated
@@ -12,6 +12,9 @@ class Domain::Fa::Post
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
@@ -39,6 +42,9 @@ class Domain::Fa::Post
|
||||
sig { returns(T::Array[Symbol]) }
|
||||
def attr_json_registry; end
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/fa/post_factor.rbi
generated
6
sorbet/rbi/dsl/domain/fa/post_factor.rbi
generated
@@ -11,12 +11,18 @@ class Domain::Fa::PostFactor
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/fa/user.rbi
generated
6
sorbet/rbi/dsl/domain/fa/user.rbi
generated
@@ -27,6 +27,9 @@ class Domain::Fa::User
|
||||
sig { returns(T::Boolean) }
|
||||
def due_for_page_scan?; end
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig { returns(T.nilable(Time)) }
|
||||
def scanned_favs_at; end
|
||||
|
||||
@@ -78,6 +81,9 @@ class Domain::Fa::User
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/fa/user_avatar.rbi
generated
6
sorbet/rbi/dsl/domain/fa/user_avatar.rbi
generated
@@ -12,12 +12,18 @@ class Domain::Fa::UserAvatar
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/fa/user_factor.rbi
generated
6
sorbet/rbi/dsl/domain/fa/user_factor.rbi
generated
@@ -11,12 +11,18 @@ class Domain::Fa::UserFactor
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/fav.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/fav.rbi
generated
@@ -10,12 +10,18 @@ class Domain::Inkbunny::Fav
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/file.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/file.rbi
generated
@@ -12,12 +12,18 @@ class Domain::Inkbunny::File
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/follow.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/follow.rbi
generated
@@ -10,12 +10,18 @@ class Domain::Inkbunny::Follow
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/pool.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/pool.rbi
generated
@@ -11,12 +11,18 @@ class Domain::Inkbunny::Pool
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/pool_join.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/pool_join.rbi
generated
@@ -11,12 +11,18 @@ class Domain::Inkbunny::PoolJoin
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/post.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/post.rbi
generated
@@ -12,12 +12,18 @@ class Domain::Inkbunny::Post
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/tag.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/tag.rbi
generated
@@ -10,12 +10,18 @@ class Domain::Inkbunny::Tag
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/tagging.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/tagging.rbi
generated
@@ -10,12 +10,18 @@ class Domain::Inkbunny::Tagging
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/inkbunny/user.rbi
generated
6
sorbet/rbi/dsl/domain/inkbunny/user.rbi
generated
@@ -12,6 +12,9 @@ class Domain::Inkbunny::User
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
@@ -21,6 +24,9 @@ class Domain::Inkbunny::User
|
||||
sig { returns(T::Hash[T.any(String, Symbol), Integer]) }
|
||||
def avatar_states; end
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
16
sorbet/rbi/dsl/domain/migrate_to_domain.rbi
generated
Normal file
16
sorbet/rbi/dsl/domain/migrate_to_domain.rbi
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Domain::MigrateToDomain`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Domain::MigrateToDomain`.
|
||||
|
||||
|
||||
class Domain::MigrateToDomain
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
end
|
||||
end
|
||||
1311
sorbet/rbi/dsl/domain/post.rbi
generated
Normal file
1311
sorbet/rbi/dsl/domain/post.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
2779
sorbet/rbi/dsl/domain/post/e621_post.rbi
generated
Normal file
2779
sorbet/rbi/dsl/domain/post/e621_post.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
sorbet/rbi/dsl/domain/post/e621_post/file_error.rbi
generated
Normal file
26
sorbet/rbi/dsl/domain/post/e621_post/file_error.rbi
generated
Normal file
@@ -0,0 +1,26 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `Domain::Post::E621Post::FileError`.
|
||||
# Please instead update this file by running `bin/tapioca dsl Domain::Post::E621Post::FileError`.
|
||||
|
||||
|
||||
class Domain::Post::E621Post::FileError
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def log_entry_id; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def log_entry_id=(value); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def retry_count; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def retry_count=(value); end
|
||||
|
||||
sig { returns(T.nilable(::Integer)) }
|
||||
def status_code; end
|
||||
|
||||
sig { params(value: T.nilable(::Integer)).returns(T.nilable(::Integer)) }
|
||||
def status_code=(value); end
|
||||
end
|
||||
2881
sorbet/rbi/dsl/domain/post/fa_post.rbi
generated
Normal file
2881
sorbet/rbi/dsl/domain/post/fa_post.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
1573
sorbet/rbi/dsl/domain/post_file.rbi
generated
Normal file
1573
sorbet/rbi/dsl/domain/post_file.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
sorbet/rbi/dsl/domain/twitter/media.rbi
generated
6
sorbet/rbi/dsl/domain/twitter/media.rbi
generated
@@ -12,12 +12,18 @@ class Domain::Twitter::Media
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/twitter/tweet.rbi
generated
6
sorbet/rbi/dsl/domain/twitter/tweet.rbi
generated
@@ -12,12 +12,18 @@ class Domain::Twitter::Tweet
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/domain/twitter/user.rbi
generated
6
sorbet/rbi/dsl/domain/twitter/user.rbi
generated
@@ -12,12 +12,18 @@ class Domain::Twitter::User
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
1467
sorbet/rbi/dsl/domain/user.rbi
generated
Normal file
1467
sorbet/rbi/dsl/domain/user.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
1937
sorbet/rbi/dsl/domain/user/e621_user.rbi
generated
Normal file
1937
sorbet/rbi/dsl/domain/user/e621_user.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
1730
sorbet/rbi/dsl/domain/user/fa_user.rbi
generated
Normal file
1730
sorbet/rbi/dsl/domain/user/fa_user.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
1620
sorbet/rbi/dsl/domain/user_avatar.rbi
generated
Normal file
1620
sorbet/rbi/dsl/domain/user_avatar.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
1177
sorbet/rbi/dsl/domain/user_post_creation.rbi
generated
Normal file
1177
sorbet/rbi/dsl/domain/user_post_creation.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
1192
sorbet/rbi/dsl/domain/user_post_fav.rbi
generated
Normal file
1192
sorbet/rbi/dsl/domain/user_post_fav.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
1151
sorbet/rbi/dsl/domain/user_user_follow.rbi
generated
Normal file
1151
sorbet/rbi/dsl/domain/user_user_follow.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
6
sorbet/rbi/dsl/flat_sst_entry.rbi
generated
6
sorbet/rbi/dsl/flat_sst_entry.rbi
generated
@@ -10,12 +10,18 @@ class FlatSstEntry
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/global_state.rbi
generated
6
sorbet/rbi/dsl/global_state.rbi
generated
@@ -11,12 +11,18 @@ class GlobalState
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
@@ -11,12 +11,18 @@ class GoodJobExecutionLogLinesCollection
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/http_log_entry.rbi
generated
6
sorbet/rbi/dsl/http_log_entry.rbi
generated
@@ -12,12 +12,18 @@ class HttpLogEntry
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/http_log_entry_header.rbi
generated
6
sorbet/rbi/dsl/http_log_entry_header.rbi
generated
@@ -10,12 +10,18 @@ class HttpLogEntryHeader
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
6
sorbet/rbi/dsl/indexed_post.rbi
generated
6
sorbet/rbi/dsl/indexed_post.rbi
generated
@@ -10,12 +10,18 @@ class IndexedPost
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
private
|
||||
|
||||
sig { returns(NilClass) }
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig do
|
||||
params(
|
||||
attributes: T.untyped,
|
||||
|
||||
16
sorbet/rbi/dsl/redux_application_record.rbi
generated
Normal file
16
sorbet/rbi/dsl/redux_application_record.rbi
generated
Normal file
@@ -0,0 +1,16 @@
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for dynamic methods in `ReduxApplicationRecord`.
|
||||
# Please instead update this file by running `bin/tapioca dsl ReduxApplicationRecord`.
|
||||
|
||||
|
||||
class ReduxApplicationRecord
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
end
|
||||
end
|
||||
6
sorbet/rbi/dsl/user.rbi
generated
6
sorbet/rbi/dsl/user.rbi
generated
@@ -11,6 +11,9 @@ class User
|
||||
extend CommonRelationMethods
|
||||
extend GeneratedRelationMethods
|
||||
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def password_confirmation; end
|
||||
|
||||
@@ -23,6 +26,9 @@ class User
|
||||
def to_ary; end
|
||||
|
||||
class << self
|
||||
sig { returns(ColorLogger) }
|
||||
def logger; end
|
||||
|
||||
sig { params(attributes: T.untyped, block: T.nilable(T.proc.params(object: ::User).void)).returns(::User) }
|
||||
def new(attributes = nil, &block); end
|
||||
|
||||
|
||||
14
spec/factories/domain/post/e621_post.rb
Normal file
14
spec/factories/domain/post/e621_post.rb
Normal file
@@ -0,0 +1,14 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_post_e621_post, class: "Domain::Post::E621Post" do
|
||||
sequence(:e621_id) { |n| n }
|
||||
state { "ok" }
|
||||
rating { "s" }
|
||||
tags_array { {} }
|
||||
flags_array { [] }
|
||||
pools_array { [] }
|
||||
sources_array { [] }
|
||||
artists_array { [] }
|
||||
e621_updated_at { Time.current }
|
||||
end
|
||||
end
|
||||
52
spec/factories/domain/post/fa_post.rb
Normal file
52
spec/factories/domain/post/fa_post.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_post_fa_post, class: "Domain::Post::FaPost" do
|
||||
sequence(:fa_id) { |n| n }
|
||||
state { "ok" }
|
||||
category { "artwork" }
|
||||
theme { "general" }
|
||||
species { "unspecified" }
|
||||
gender { "unspecified" }
|
||||
description { "Test description" }
|
||||
keywords { %w[test factory] }
|
||||
num_favorites { 0 }
|
||||
num_comments { 0 }
|
||||
num_views { 0 }
|
||||
posted_at { Time.current }
|
||||
scanned_at { Time.current }
|
||||
|
||||
trait :with_last_user_page do
|
||||
association :last_user_page, factory: :http_log_entry
|
||||
end
|
||||
|
||||
trait :with_last_submission_page do
|
||||
association :last_submission_page, factory: :http_log_entry
|
||||
end
|
||||
|
||||
trait :with_first_browse_page do
|
||||
association :first_browse_page, factory: :http_log_entry
|
||||
end
|
||||
|
||||
trait :with_first_gallery_page do
|
||||
association :first_gallery_page, factory: :http_log_entry
|
||||
end
|
||||
|
||||
trait :with_first_seen_entry do
|
||||
association :first_seen_entry, factory: :http_log_entry
|
||||
end
|
||||
|
||||
trait :removed do
|
||||
state { "removed" }
|
||||
end
|
||||
|
||||
trait :scan_error do
|
||||
state { "scan_error" }
|
||||
scan_file_error { "Failed to scan file" }
|
||||
end
|
||||
|
||||
trait :file_error do
|
||||
state { "file_error" }
|
||||
scan_file_error { "Failed to process file" }
|
||||
end
|
||||
end
|
||||
end
|
||||
9
spec/factories/domain/post_file.rb
Normal file
9
spec/factories/domain/post_file.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_post_file, class: "Domain::PostFile" do
|
||||
post { create(:domain_post_fa_post) }
|
||||
log_entry { create(:http_log_entry) }
|
||||
url_str { "https://example.com/image.jpg" }
|
||||
state { "ok" }
|
||||
end
|
||||
end
|
||||
11
spec/factories/domain/user/e621_user.rb
Normal file
11
spec/factories/domain/user/e621_user.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_user_e621_user, class: "Domain::User::E621User" do
|
||||
sequence(:e621_id) { |n| n }
|
||||
sequence(:name) { |n| "user#{n}" }
|
||||
favs_are_hidden { false }
|
||||
num_other_favs_cached { 0 }
|
||||
scanned_favs_status { "ok" }
|
||||
scanned_favs_at { nil }
|
||||
end
|
||||
end
|
||||
7
spec/factories/domain/user/fa_user.rb
Normal file
7
spec/factories/domain/user/fa_user.rb
Normal file
@@ -0,0 +1,7 @@
|
||||
# typed: false
|
||||
FactoryBot.define do
|
||||
factory :domain_user_fa_user, class: "Domain::User::FaUser" do
|
||||
sequence(:url_name) { |n| "user_#{n}" }
|
||||
sequence(:name) { |n| "User#{n}" }
|
||||
end
|
||||
end
|
||||
@@ -71,7 +71,7 @@ describe Domain::Fa::Job::UserIncrementalJob do
|
||||
expect(
|
||||
SpecUtil.enqueued_jobs(Domain::Fa::Job::UserFollowsJob),
|
||||
).to be_empty
|
||||
expect(meesh.scanned_follows_at).to be_within(1.second).of(Time.now)
|
||||
expect(meesh.scanned_follows_at).to be_within(1.second).of(Time.current)
|
||||
|
||||
# 19 newly seen faved posts
|
||||
expect(SpecUtil.enqueued_jobs(Domain::Fa::Job::ScanPostJob).length).to be(
|
||||
@@ -79,7 +79,7 @@ describe Domain::Fa::Job::UserIncrementalJob do
|
||||
)
|
||||
# No new fav in last position, so don't enqueue scan
|
||||
expect(SpecUtil.enqueued_jobs(Domain::Fa::Job::FavsJob)).to be_empty
|
||||
expect(meesh.scanned_favs_at).to be_within(1.second).of(Time.now)
|
||||
expect(meesh.scanned_favs_at).to be_within(1.second).of(Time.current)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
139
spec/models/domain/post/e621_post_spec.rb
Normal file
139
spec/models/domain/post/e621_post_spec.rb
Normal file
@@ -0,0 +1,139 @@
|
||||
# typed: false
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Domain::Post::E621Post, type: :model do
|
||||
describe "validations" do
|
||||
let(:post) { build(:domain_post_e621_post) }
|
||||
|
||||
it "requires e621_id" do
|
||||
post.e621_id = nil
|
||||
expect(post).not_to be_valid
|
||||
expect(post.errors[:e621_id]).to include("can't be blank")
|
||||
end
|
||||
|
||||
it "requires state" do
|
||||
post.state = nil
|
||||
expect(post).not_to be_valid
|
||||
expect(post.errors[:state]).to include("is not included in the list")
|
||||
end
|
||||
|
||||
it "validates state inclusion" do
|
||||
%w[ok removed scan_error file_error].each do |state|
|
||||
post.state = state
|
||||
expect(post).to be_valid
|
||||
end
|
||||
post.state = "invalid_state"
|
||||
expect(post).not_to be_valid
|
||||
expect(post.errors[:state]).to include("is not included in the list")
|
||||
end
|
||||
|
||||
it "validates rating inclusion" do
|
||||
%w[s q e].each do |rating|
|
||||
post.rating = rating
|
||||
expect(post).to be_valid
|
||||
end
|
||||
post.rating = "invalid_rating"
|
||||
expect(post).not_to be_valid
|
||||
expect(post.errors[:rating]).to include("is not included in the list")
|
||||
end
|
||||
end
|
||||
|
||||
describe "initialization" do
|
||||
let(:post) { described_class.new }
|
||||
|
||||
it "sets default values" do
|
||||
expect(post.state).to eq("ok")
|
||||
expect(post.flags_array).to eq([])
|
||||
expect(post.pools_array).to eq([])
|
||||
expect(post.sources_array).to eq([])
|
||||
expect(post.artists_array).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
describe "attributes" do
|
||||
it "can be queried using generated scopes" do
|
||||
post1 = create(:domain_post_e621_post)
|
||||
post2 = create(:domain_post_e621_post, scan_error: "an error")
|
||||
post3 = create(:domain_post_e621_post, scan_error: nil)
|
||||
|
||||
expect(described_class.where_scan_error("is not null")).to match_array(
|
||||
[post2],
|
||||
)
|
||||
expect(described_class.where_scan_error("is null")).to match_array(
|
||||
[post1, post3],
|
||||
)
|
||||
|
||||
post2.scan_error = nil
|
||||
post2.save!
|
||||
expect(described_class.where_scan_error("is null")).to match_array(
|
||||
[post1, post2, post3],
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "associations" do
|
||||
it "belongs to parent_e621" do
|
||||
parent = create(:domain_post_e621_post)
|
||||
post = create(:domain_post_e621_post)
|
||||
post.parent_post = parent
|
||||
post.save!
|
||||
|
||||
expect(post.parent_post).to eq(parent)
|
||||
end
|
||||
|
||||
it "has one file" do
|
||||
post = create(:domain_post_e621_post)
|
||||
file = create(:domain_post_file, post: post)
|
||||
post.reload
|
||||
expect(post.file).to eq(file)
|
||||
end
|
||||
|
||||
it "belongs to last_index_page" do
|
||||
post = create(:domain_post_e621_post)
|
||||
log_entry = create(:http_log_entry)
|
||||
post.last_index_page = log_entry
|
||||
post.save!
|
||||
expect(post.last_index_page).to eq(log_entry)
|
||||
end
|
||||
|
||||
it "has an uploader" do
|
||||
user = create(:domain_user_e621_user)
|
||||
post = create(:domain_post_e621_post, uploader_user: user)
|
||||
expect(post.uploader_user).to eq(user)
|
||||
expect(user.uploaded_posts).to eq([post])
|
||||
end
|
||||
end
|
||||
|
||||
describe "#to_param" do
|
||||
let(:post) { build(:domain_post_e621_post, e621_id: 12_345) }
|
||||
|
||||
it "returns nil when e621_id is not present" do
|
||||
post.e621_id = nil
|
||||
expect(post.to_param).to be_nil
|
||||
end
|
||||
|
||||
it "returns formatted string when e621_id is present" do
|
||||
expect(post.to_param).to eq("e621/12345")
|
||||
end
|
||||
end
|
||||
|
||||
describe "file error handling" do
|
||||
let(:post) { create(:domain_post_e621_post) }
|
||||
|
||||
it "can store file error details" do
|
||||
error =
|
||||
Domain::Post::E621Post::FileError.new(
|
||||
retry_count: 3,
|
||||
status_code: 404,
|
||||
log_entry_id: 123,
|
||||
)
|
||||
post.file_error = error
|
||||
post.save!
|
||||
|
||||
post.reload
|
||||
expect(post.file_error.retry_count).to eq(3)
|
||||
expect(post.file_error.status_code).to eq(404)
|
||||
expect(post.file_error.log_entry_id).to eq(123)
|
||||
end
|
||||
end
|
||||
end
|
||||
119
spec/models/domain/post/fa_post_spec.rb
Normal file
119
spec/models/domain/post/fa_post_spec.rb
Normal file
@@ -0,0 +1,119 @@
|
||||
# typed: false
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Domain::Post::FaPost do
|
||||
describe "validations" do
|
||||
let(:post) { build(:domain_post_fa_post) }
|
||||
|
||||
it "requires fa_id" do
|
||||
post.fa_id = nil
|
||||
expect(post).not_to be_valid
|
||||
expect(post.errors[:fa_id]).to include("can't be blank")
|
||||
end
|
||||
|
||||
it "validates state inclusion" do
|
||||
post.state = "invalid"
|
||||
expect(post).not_to be_valid
|
||||
expect(post.errors[:state]).to include("is not included in the list")
|
||||
|
||||
%w[ok removed scan_error file_error].each do |valid_state|
|
||||
post.state = valid_state
|
||||
expect(post).to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it "defaults state to 'ok'" do
|
||||
new_post = described_class.new
|
||||
expect(new_post.state).to eq("ok")
|
||||
end
|
||||
end
|
||||
|
||||
describe "creators" do
|
||||
it "works" do
|
||||
post = create(:domain_post_fa_post)
|
||||
user = create(:domain_user_fa_user)
|
||||
post.creator = user
|
||||
expect(post.creator).to eq(user)
|
||||
|
||||
expect(post.user_post_creations.count).to eq(1)
|
||||
expect(post.user_post_creations.first.user).to eq(user)
|
||||
end
|
||||
end
|
||||
|
||||
describe "files" do
|
||||
it "works" do
|
||||
post = create(:domain_post_fa_post)
|
||||
file = create(:domain_post_file, post: post)
|
||||
expect(post.file).to eq(file)
|
||||
|
||||
expect(Domain::PostFile.where(post: post).count).to eq(1)
|
||||
expect(Domain::PostFile.where(post: post).first).to eq(file)
|
||||
end
|
||||
end
|
||||
|
||||
describe "attributes" do
|
||||
let(:post) { build(:domain_post_fa_post) }
|
||||
let(:time) { Time.current }
|
||||
|
||||
it "can be initialized by fa_id" do
|
||||
post = described_class.new(fa_id: 123)
|
||||
expect(post).to be_valid
|
||||
expect(post.fa_id).to eq(123)
|
||||
expect(post.state).to eq("ok")
|
||||
expect(post.save).to be_truthy
|
||||
end
|
||||
|
||||
it "handles basic attributes" do
|
||||
post.category = "artwork"
|
||||
post.theme = "fantasy"
|
||||
post.species = "dragon"
|
||||
post.gender = "male"
|
||||
post.description = "A cool description"
|
||||
post.num_favorites = 42
|
||||
post.num_comments = 10
|
||||
post.num_views = 100
|
||||
|
||||
expect(post.category).to eq("artwork")
|
||||
expect(post.theme).to eq("fantasy")
|
||||
expect(post.species).to eq("dragon")
|
||||
expect(post.gender).to eq("male")
|
||||
expect(post.description).to eq("A cool description")
|
||||
expect(post.num_favorites).to eq(42)
|
||||
expect(post.num_comments).to eq(10)
|
||||
expect(post.num_views).to eq(100)
|
||||
end
|
||||
|
||||
it "handles array attributes" do
|
||||
keywords = %w[dragon fantasy digital]
|
||||
post.keywords = keywords
|
||||
expect(post.keywords).to eq(keywords)
|
||||
end
|
||||
|
||||
it "handles datetime attributes" do
|
||||
post.posted_at = time
|
||||
post.scanned_at = time
|
||||
|
||||
expect(post.posted_at).to be_within(1.second).of(time)
|
||||
expect(post.scanned_at).to be_within(1.second).of(time)
|
||||
end
|
||||
|
||||
it "defaults keywords to empty array" do
|
||||
new_post = described_class.new
|
||||
expect(new_post.keywords).to eq([])
|
||||
end
|
||||
end
|
||||
|
||||
describe "factory" do
|
||||
it "works" do
|
||||
post = create(:domain_post_fa_post)
|
||||
expect(post).to be_valid
|
||||
expect(post.type).to eq("Domain::Post::FaPost")
|
||||
end
|
||||
|
||||
it "works with traits" do
|
||||
post = create(:domain_post_fa_post, :removed)
|
||||
expect(post).to be_valid
|
||||
expect(post.state).to eq("removed")
|
||||
end
|
||||
end
|
||||
end
|
||||
85
spec/models/domain/user/e621_user_spec.rb
Normal file
85
spec/models/domain/user/e621_user_spec.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
# typed: false
|
||||
require "rails_helper"
|
||||
|
||||
RSpec.describe Domain::User::E621User, type: :model do
|
||||
describe "validations" do
|
||||
let(:user) { build(:domain_user_e621_user) }
|
||||
|
||||
it "is valid with valid attributes" do
|
||||
expect(user).to be_valid
|
||||
end
|
||||
|
||||
it "requires e621_id" do
|
||||
user.e621_id = nil
|
||||
expect(user).not_to be_valid
|
||||
expect(user.errors[:e621_id]).to include("can't be blank")
|
||||
end
|
||||
|
||||
it "requires name" do
|
||||
user.name = nil
|
||||
expect(user).not_to be_valid
|
||||
expect(user.errors[:name]).to include("can't be blank")
|
||||
end
|
||||
|
||||
it "validates scanned_favs_status inclusion" do
|
||||
user.scanned_favs_status = nil
|
||||
expect(user).to be_valid # optional field
|
||||
|
||||
user.scanned_favs_status = "ok"
|
||||
expect(user).to be_valid
|
||||
|
||||
user.scanned_favs_status = "error"
|
||||
expect(user).to be_valid
|
||||
|
||||
user.scanned_favs_status = "invalid"
|
||||
expect(user).not_to be_valid
|
||||
expect(user.errors[:scanned_favs_status]).to include(
|
||||
"is not included in the list",
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
describe "initialization" do
|
||||
let(:user) { described_class.new }
|
||||
|
||||
it "has default values" do
|
||||
expect(user.favs_are_hidden).to be_nil
|
||||
expect(user.num_other_favs_cached).to be_nil
|
||||
expect(user.scanned_favs_status).to be_nil
|
||||
expect(user.scanned_favs_at).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
describe "attributes" do
|
||||
let(:user) { create(:domain_user_e621_user) }
|
||||
|
||||
it "can update favs_are_hidden" do
|
||||
user.favs_are_hidden = true
|
||||
expect(user.save).to be true
|
||||
user.reload
|
||||
expect(user.favs_are_hidden).to be true
|
||||
end
|
||||
|
||||
it "can update num_other_favs_cached" do
|
||||
user.num_other_favs_cached = 100
|
||||
expect(user.save).to be true
|
||||
user.reload
|
||||
expect(user.num_other_favs_cached).to eq(100)
|
||||
end
|
||||
|
||||
it "can update scanned_favs_status" do
|
||||
user.scanned_favs_status = "error"
|
||||
expect(user.save).to be true
|
||||
user.reload
|
||||
expect(user.scanned_favs_status).to eq("error")
|
||||
end
|
||||
|
||||
it "can update scanned_favs_at" do
|
||||
time = Time.current
|
||||
user.scanned_favs_at = time
|
||||
expect(user.save).to be true
|
||||
user.reload
|
||||
expect(user.scanned_favs_at).to be_within(1.second).of(time)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user