fix typing
This commit is contained in:
@@ -31,7 +31,7 @@ class DbSampler
|
||||
|
||||
sig { void.params(file: T.untyped) }
|
||||
def initialize(file)
|
||||
@file = T.let(file, StringIO)
|
||||
@file = T.let(file, T.any(StringIO, IO))
|
||||
@handled = T.let(Set.new, T::Set[ReduxApplicationRecord])
|
||||
end
|
||||
|
||||
@@ -148,7 +148,9 @@ class DbSampler
|
||||
|
||||
sig { params(model: ReduxApplicationRecord, level: Integer).void }
|
||||
def dump(model, level)
|
||||
@file.puts(Base64.strict_encode64(Zstd.compress(Marshal.dump(model), 1)))
|
||||
@file.puts(
|
||||
Base64.strict_encode64(Zstd.compress(Marshal.dump(model), level: 1)),
|
||||
)
|
||||
id = model.id
|
||||
id = HexUtil.bin2hex(id) if model.class.primary_key == "sha256"
|
||||
$stderr.puts ("-" * level) + " dumped #{model.class.name}/#{id}"
|
||||
|
||||
24
app/lib/graph.rb
Normal file
24
app/lib/graph.rb
Normal file
@@ -0,0 +1,24 @@
|
||||
# typed: strict
|
||||
module Graph
|
||||
class Base < ActiveRecord::Base
|
||||
end
|
||||
|
||||
class Node < Base
|
||||
end
|
||||
|
||||
class Edge < Base
|
||||
end
|
||||
end
|
||||
|
||||
require_relative "graph/node/belongs_to_many_nodes_assoc"
|
||||
require_relative "graph/node/belongs_to_node_assoc"
|
||||
require_relative "graph/node/has_one_node_assoc"
|
||||
require_relative "graph/node/has_many_nodes_assoc"
|
||||
require_relative "graph/node_mixin"
|
||||
require_relative "graph/edge_mixin"
|
||||
|
||||
require_relative "graph/column_type"
|
||||
require_relative "graph/active_record_query_extensions"
|
||||
require_relative "graph/base"
|
||||
require_relative "graph/node"
|
||||
require_relative "graph/edge"
|
||||
@@ -1,7 +1,7 @@
|
||||
# typed: strict
|
||||
require_relative("./active_record_query_extensions")
|
||||
|
||||
class Graph::Base < ReduxApplicationRecord
|
||||
class Graph::Base < ActiveRecord::Base
|
||||
extend T::Sig
|
||||
extend T::Helpers
|
||||
abstract!
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# typed: false
|
||||
# typed: strict
|
||||
class Domain::Fa::User < ReduxApplicationRecord
|
||||
self.table_name = "domain_fa_users"
|
||||
include Pundit::Authorization
|
||||
@@ -65,6 +65,9 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
# `url_name` can be longer.
|
||||
validates_presence_of(:name, :url_name)
|
||||
validate do
|
||||
T.bind(self, Domain::Fa::User)
|
||||
name = self.name
|
||||
url_name = self.url_name
|
||||
if name && url_name
|
||||
expected = self.class.name_to_url_name(name)
|
||||
|
||||
@@ -100,50 +103,68 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
|
||||
before_destroy { throw :abort if posts.any? }
|
||||
|
||||
SCAN_TYPES = {
|
||||
page: 1.month,
|
||||
gallery: 1.year,
|
||||
follows: 1.month,
|
||||
favs: 1.month,
|
||||
incremental: 1.month,
|
||||
}
|
||||
SCAN_TYPES =
|
||||
T.let(
|
||||
{
|
||||
page: 1.month,
|
||||
gallery: 1.year,
|
||||
follows: 1.month,
|
||||
favs: 1.month,
|
||||
incremental: 1.month,
|
||||
},
|
||||
T::Hash[Symbol, ActiveSupport::Duration],
|
||||
)
|
||||
|
||||
SCAN_FIELD_TYPES = {
|
||||
page: :column,
|
||||
gallery: :column,
|
||||
follows: :column,
|
||||
favs: :column,
|
||||
incremental: :state_detail,
|
||||
}
|
||||
SCAN_FIELD_TYPES =
|
||||
T.let(
|
||||
{
|
||||
page: :column,
|
||||
gallery: :column,
|
||||
follows: :column,
|
||||
favs: :column,
|
||||
incremental: :state_detail,
|
||||
},
|
||||
T::Hash[Symbol, Symbol],
|
||||
)
|
||||
|
||||
SCAN_TYPES.keys.each do |scan_type|
|
||||
define_method(:"due_for_#{scan_type}_scan?") { scan_due?(scan_type) }
|
||||
define_method(:"due_for_#{scan_type}_scan?") do
|
||||
T.bind(self, Domain::Fa::User)
|
||||
scan_due?(scan_type)
|
||||
end
|
||||
|
||||
define_method(:"time_ago_for_#{scan_type}_scan") do
|
||||
T.bind(self, Domain::Fa::User)
|
||||
scanned_ago_in_words(scan_type)
|
||||
end
|
||||
|
||||
next unless SCAN_FIELD_TYPES[scan_type] == :state_detail
|
||||
|
||||
define_method(:"scanned_#{scan_type}_at") do
|
||||
T.bind(self, Domain::Fa::User)
|
||||
get_scanned_at_value(scan_type)
|
||||
end
|
||||
|
||||
define_method(:"scanned_#{scan_type}_at=") do |value|
|
||||
T.bind(self, Domain::Fa::User)
|
||||
set_scanned_at_value(scan_type, value)
|
||||
end
|
||||
end
|
||||
|
||||
DATE_HELPER = Class.new.extend(ActionView::Helpers::DateHelper)
|
||||
class DateHelper
|
||||
extend ActionView::Helpers::DateHelper
|
||||
end
|
||||
|
||||
sig { params(scan_type: Symbol).returns(String) }
|
||||
def scanned_ago_in_words(scan_type)
|
||||
if (timestamp = get_scanned_at_value(scan_type))
|
||||
DATE_HELPER.time_ago_in_words(timestamp) + " ago"
|
||||
DateHelper.time_ago_in_words(timestamp) + " ago"
|
||||
else
|
||||
"never"
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(scan_type: Symbol).returns(T::Boolean) }
|
||||
def scan_due?(scan_type)
|
||||
duration =
|
||||
SCAN_TYPES[scan_type] || raise("invalid scan type '#{scan_type}'")
|
||||
@@ -151,6 +172,7 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
timestamp.nil? || timestamp <= duration.ago
|
||||
end
|
||||
|
||||
sig { params(other_user: Domain::Fa::User).void }
|
||||
def take_posts_from(other_user)
|
||||
return if other_user == self
|
||||
|
||||
@@ -165,21 +187,24 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
self.class.transaction { avatar || create_avatar! }
|
||||
end
|
||||
|
||||
sig do
|
||||
params(
|
||||
submission_parser:
|
||||
T.any(
|
||||
Domain::Fa::Parser::SubmissionParserHelper,
|
||||
Domain::Fa::Parser::ListedSubmissionParserHelper,
|
||||
),
|
||||
).returns(Domain::Fa::User)
|
||||
end
|
||||
def self.find_or_build_from_submission_parser(submission_parser)
|
||||
unless submission_parser.is_a?(
|
||||
Domain::Fa::Parser::ListedSubmissionParserHelper,
|
||||
) ||
|
||||
submission_parser.is_a?(Domain::Fa::Parser::SubmissionParserHelper)
|
||||
raise ArgumentError
|
||||
end
|
||||
|
||||
find_or_initialize_by(url_name: submission_parser.artist_url_name) do |user|
|
||||
user.name = submission_parser.artist
|
||||
end
|
||||
end
|
||||
|
||||
URL_NAME_EXCEPTIONS = { "Kammiu" => "rammiu" }
|
||||
URL_NAME_EXCEPTIONS = T.let({ "Kammiu" => "rammiu" }, T::Hash[String, String])
|
||||
|
||||
sig { params(name: String).returns(String) }
|
||||
def self.name_to_url_name(name)
|
||||
name = name.strip
|
||||
URL_NAME_EXCEPTIONS[name] || name.delete("_").gsub(/\s/, "").downcase
|
||||
@@ -197,15 +222,26 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
# exclude self.follows.pluck(:followed_id)
|
||||
|
||||
# find users similar to 'self' based on who 'self' follows
|
||||
sig do
|
||||
params(exclude_followed_by: T.nilable(Domain::Fa::User)).returns(
|
||||
PrivateRelation,
|
||||
)
|
||||
end
|
||||
def similar_users_by_follower(exclude_followed_by: nil)
|
||||
similar_users_by(:for_follower, exclude_followed_by)
|
||||
end
|
||||
|
||||
# find users similar to 'self one based on who follows 'self'
|
||||
sig do
|
||||
params(exclude_followed_by: T.nilable(Domain::Fa::User)).returns(
|
||||
PrivateRelation,
|
||||
)
|
||||
end
|
||||
def similar_users_by_followed(exclude_followed_by: nil)
|
||||
similar_users_by(:for_followed, exclude_followed_by)
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(HttpLogEntry)) }
|
||||
def guess_user_page_log_entry
|
||||
for_path =
|
||||
proc do |uri_path|
|
||||
@@ -234,14 +270,25 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
# TODO: - maybe can look for posts as well, those might list an avatar
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(String)) }
|
||||
def to_param
|
||||
url_name
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
sig do
|
||||
params(
|
||||
factor_col: Symbol,
|
||||
exclude_followed_by: T.nilable(Domain::Fa::User),
|
||||
).returns(PrivateRelation)
|
||||
end
|
||||
def similar_users_by(factor_col, exclude_followed_by)
|
||||
query = disco.nearest_neighbors(factor_col, distance: "euclidean")
|
||||
query =
|
||||
T.cast(
|
||||
T.must(disco).nearest_neighbors(factor_col, distance: "euclidean"),
|
||||
Domain::Fa::User::PrivateRelation,
|
||||
)
|
||||
|
||||
query =
|
||||
query.where.not(
|
||||
@@ -251,6 +298,7 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
users_from_disco_query(query)
|
||||
end
|
||||
|
||||
sig { params(disco_query: PrivateRelation).returns(PrivateRelation) }
|
||||
def users_from_disco_query(disco_query)
|
||||
Domain::Fa::User
|
||||
.select("domain_fa_users.*", disco_query.select_values.last)
|
||||
@@ -258,6 +306,7 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
.merge(disco_query.reselect(:user_id))
|
||||
end
|
||||
|
||||
sig { params(scan_type: Symbol).returns(T.nilable(Time)) }
|
||||
def get_scanned_at_value(scan_type)
|
||||
case SCAN_FIELD_TYPES[scan_type]
|
||||
when :column
|
||||
@@ -270,12 +319,13 @@ class Domain::Fa::User < ReduxApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
sig { params(scan_type: Symbol, value: T.nilable(Time)).void }
|
||||
def set_scanned_at_value(scan_type, value)
|
||||
case SCAN_FIELD_TYPES[scan_type]
|
||||
when :column
|
||||
send(:"scanned_#{scan_type}_at=", value)
|
||||
when :state_detail
|
||||
state_detail["scanned_#{scan_type}_at"] = value.iso8601
|
||||
state_detail["scanned_#{scan_type}_at"] = value&.iso8601
|
||||
else
|
||||
raise("invalid scan type '#{scan_type}'")
|
||||
end
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# typed: strict
|
||||
class Domain::Fa::UserFactor < ReduxApplicationRecord
|
||||
include Neighbor::Model
|
||||
self.table_name = "domain_fa_user_factors"
|
||||
|
||||
belongs_to :user, class_name: "::Domain::Fa::User"
|
||||
@@ -7,4 +8,8 @@ class Domain::Fa::UserFactor < ReduxApplicationRecord
|
||||
FACTORS_WIDTHS = 16
|
||||
has_neighbors :for_follower
|
||||
has_neighbors :for_followed
|
||||
|
||||
sig { void }
|
||||
def foo
|
||||
end
|
||||
end
|
||||
|
||||
2
sorbet/rbi/gems/neighbor@0.5.1.rbi
generated
2
sorbet/rbi/gems/neighbor@0.5.1.rbi
generated
@@ -1,4 +1,4 @@
|
||||
# typed: strict
|
||||
# typed: true
|
||||
|
||||
# DO NOT EDIT MANUALLY
|
||||
# This is an autogenerated file for types exported from the `neighbor` gem.
|
||||
|
||||
11
sorbet/rbi/shims/disco.rbi
Normal file
11
sorbet/rbi/shims/disco.rbi
Normal file
@@ -0,0 +1,11 @@
|
||||
# typed: strict
|
||||
|
||||
module Neighbor::Model
|
||||
sig do
|
||||
params(attribute_name: Symbol, distance: String).returns(
|
||||
ActiveRecord::Relation,
|
||||
)
|
||||
end
|
||||
def nearest_neighbors(attribute_name, distance:)
|
||||
end
|
||||
end
|
||||
89
sorbet/rbi/shims/domain_fa_user.rbi
Normal file
89
sorbet/rbi/shims/domain_fa_user.rbi
Normal file
@@ -0,0 +1,89 @@
|
||||
# typed: strict
|
||||
class Domain::Fa::User
|
||||
# define for:
|
||||
# :page
|
||||
# :gallery
|
||||
# :follows
|
||||
# :favs
|
||||
# :incremental
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def due_for_page_scan?
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def due_for_gallery_scan?
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def due_for_follows_scan?
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def due_for_favs_scan?
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def due_for_incremental_scan?
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def time_ago_for_page_scan
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def time_ago_for_gallery_scan
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def time_ago_for_follows_scan
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def time_ago_for_favs_scan
|
||||
end
|
||||
|
||||
sig { returns(String) }
|
||||
def time_ago_for_incremental_scan
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Time)) }
|
||||
def scanned_page_at
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Time)) }
|
||||
def scanned_gallery_at
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Time)) }
|
||||
def scanned_follows_at
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Time)) }
|
||||
def scanned_favs_at
|
||||
end
|
||||
|
||||
sig { returns(T.nilable(Time)) }
|
||||
def scanned_incremental_at
|
||||
end
|
||||
|
||||
sig { params(time: T.nilable(Time)).void }
|
||||
def scanned_page_at=(time)
|
||||
end
|
||||
|
||||
sig { params(time: T.nilable(Time)).void }
|
||||
def scanned_gallery_at=(time)
|
||||
end
|
||||
|
||||
sig { params(time: T.nilable(Time)).void }
|
||||
def scanned_follows_at=(time)
|
||||
end
|
||||
|
||||
sig { params(time: T.nilable(Time)).void }
|
||||
def scanned_favs_at=(time)
|
||||
end
|
||||
|
||||
sig { params(time: T.nilable(Time)).void }
|
||||
def scanned_incremental_at=(time)
|
||||
end
|
||||
end
|
||||
@@ -1,14 +1,8 @@
|
||||
# typed: true
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "./app/models/graph/node/belongs_to_node_assoc"
|
||||
require "./app/models/graph/node/has_one_node_assoc"
|
||||
require "./app/models/graph/node/has_many_nodes_assoc"
|
||||
require "./spec/lib/graph/nodes_for_tests"
|
||||
require "./app/lib/graph"
|
||||
require "./app/lib/has_color_logger"
|
||||
require "./app/lib/graph/base"
|
||||
require "./app/lib/graph/edge"
|
||||
require "./app/lib/graph/node"
|
||||
require "./spec/helpers/debug_helpers"
|
||||
require "./spec/helpers/http_client_mock_helpers"
|
||||
require "./spec/helpers/perform_job_helpers"
|
||||
|
||||
Reference in New Issue
Block a user