backfill user search names
This commit is contained in:
38
Rakefile
38
Rakefile
@@ -93,19 +93,35 @@ task :reverse_csv do
|
||||
out_csv.close
|
||||
end
|
||||
|
||||
task migrate_domain: :environment do
|
||||
task migrate_to_domain: :environment do
|
||||
only_user = ENV["only_user"]
|
||||
allowed_domains = %w[e621 fa ib]
|
||||
only_domains = (ENV["only_domains"] || "").split(",")
|
||||
only_domains = allowed_domains if only_domains.empty?
|
||||
if (only_domains - allowed_domains).any?
|
||||
raise "only_domains must be a subset of #{allowed_domains.join(", ")}"
|
||||
end
|
||||
|
||||
migrator = Domain::MigrateToDomain.new
|
||||
migrator.migrate_e621_users(only_user: only_user)
|
||||
migrator.migrate_e621_posts(only_user: only_user)
|
||||
migrator.migrate_fa_users(only_user: only_user)
|
||||
migrator.migrate_fa_posts(only_user: only_user)
|
||||
migrator.migrate_e621_users_favs(only_user: only_user)
|
||||
migrator.migrate_fa_users_favs(only_user: only_user)
|
||||
migrator.migrate_fa_users_followed_users(only_user: only_user)
|
||||
migrator.migrate_inkbunny_users(only_user: only_user)
|
||||
migrator.migrate_inkbunny_posts(only_user: only_user)
|
||||
migrator.migrate_inkbunny_pools(only_user: nil) if only_user.nil?
|
||||
|
||||
if only_domains.include?("e621")
|
||||
migrator.migrate_e621_users(only_user: only_user)
|
||||
migrator.migrate_e621_posts(only_user: only_user)
|
||||
migrator.migrate_e621_users_favs(only_user: only_user)
|
||||
end
|
||||
|
||||
if only_domains.include?("fa")
|
||||
migrator.migrate_fa_users(only_user: only_user)
|
||||
migrator.migrate_fa_posts(only_user: only_user)
|
||||
migrator.migrate_fa_users_favs(only_user: only_user)
|
||||
migrator.migrate_fa_users_followed_users(only_user: only_user)
|
||||
end
|
||||
|
||||
if only_domains.include?("ib")
|
||||
migrator.migrate_inkbunny_users(only_user: only_user)
|
||||
migrator.migrate_inkbunny_posts(only_user: only_user)
|
||||
migrator.migrate_inkbunny_pools(only_user: nil) if only_user.nil?
|
||||
end
|
||||
end
|
||||
|
||||
task infer_last_submission_log_entries: :environment do
|
||||
|
||||
@@ -11,7 +11,6 @@ class Domain::Fa::Job::Base < Scraper::JobBase
|
||||
def initialize(*args)
|
||||
super(*T.unsafe(args))
|
||||
@posts_enqueued_for_scan = T.let(Set.new, T::Set[Integer])
|
||||
@force_scan = T.let(false, T::Boolean)
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
@@ -473,6 +473,9 @@ class Domain::MigrateToDomain
|
||||
new_post.last_file_updated_at = old_post.last_file_updated_at
|
||||
new_post.deep_update_log_entry_id = old_post.deep_update_log_entry_id
|
||||
new_post.shallow_update_log_entry_id = old_post.shallow_update_log_entry_id
|
||||
new_post.shallow_updated_at = old_post.shallow_updated_at
|
||||
new_post.deep_updated_at = old_post.deep_updated_at
|
||||
new_post.ib_detail_raw = old_post.ib_detail_raw
|
||||
|
||||
if old_creator = old_post.creator
|
||||
new_post.creator =
|
||||
@@ -792,9 +795,12 @@ class Domain::MigrateToDomain
|
||||
).returns(T::Hash[String, T.untyped])
|
||||
end
|
||||
def clean_attributes(klass, attributes)
|
||||
json_attributes =
|
||||
T.unsafe(klass).attr_json_registry.attribute_names.map(&:to_s)
|
||||
attributes.except(*json_attributes).except("id", "created_at", "updated_at")
|
||||
reject_attrs = klass.columns.filter(&:virtual?).map(&:name)
|
||||
if klass < AttrJsonRecordAliases
|
||||
reject_attrs +=
|
||||
T.unsafe(klass).attr_json_registry.attribute_names.map(&:to_s)
|
||||
end
|
||||
attributes.except(*reject_attrs).except("id", "created_at", "updated_at")
|
||||
end
|
||||
|
||||
sig do
|
||||
@@ -804,10 +810,12 @@ class Domain::MigrateToDomain
|
||||
batch: T::Array[T.all(T.type_parameter(:Old), ActiveRecord::Base)],
|
||||
unique_by: T.nilable(T::Array[Symbol]),
|
||||
model_mapper:
|
||||
T
|
||||
.proc
|
||||
.params(record: T.all(T.type_parameter(:Old), ActiveRecord::Base))
|
||||
.returns(T.all(T.type_parameter(:New), ActiveRecord::Base)),
|
||||
T.nilable(
|
||||
T
|
||||
.proc
|
||||
.params(record: T.all(T.type_parameter(:Old), ActiveRecord::Base))
|
||||
.returns(T.all(T.type_parameter(:New), ActiveRecord::Base)),
|
||||
),
|
||||
)
|
||||
.returns(T::Array[T.type_parameter(:New)])
|
||||
end
|
||||
@@ -816,10 +824,14 @@ class Domain::MigrateToDomain
|
||||
models = []
|
||||
klass.transaction do
|
||||
batch.each do |record|
|
||||
model = model_mapper.call(record)
|
||||
model.name_for_search = model.names_for_search_value if model.is_a?(
|
||||
Domain::User,
|
||||
)
|
||||
model = model_mapper ? model_mapper.call(record) : record
|
||||
|
||||
if model.is_a?(Domain::User)
|
||||
model.names_for_search_values.each do |name|
|
||||
model.user_search_names.build(name:)
|
||||
end
|
||||
end
|
||||
|
||||
models << model
|
||||
attributes << clean_attributes(klass, model.attributes)
|
||||
end
|
||||
@@ -830,6 +842,20 @@ class Domain::MigrateToDomain
|
||||
end
|
||||
returned.zip(models).each { |hash, model| model.id = hash["id"] }
|
||||
end
|
||||
|
||||
if klass < Domain::User
|
||||
models.each do |model|
|
||||
model.user_search_names.each do |user_search_name|
|
||||
user_search_name.user_id = model.id
|
||||
end
|
||||
end
|
||||
|
||||
migrate_batch(
|
||||
Domain::UserSearchName,
|
||||
models.flat_map(&:user_search_names),
|
||||
)
|
||||
end
|
||||
|
||||
models
|
||||
end
|
||||
end
|
||||
|
||||
@@ -41,21 +41,39 @@ class Domain::User < ReduxApplicationRecord
|
||||
super
|
||||
end
|
||||
|
||||
before_save do
|
||||
self.name_for_search = names_for_search_value
|
||||
true
|
||||
after_save :set_names_for_search
|
||||
|
||||
sig { void }
|
||||
def set_names_for_search
|
||||
values = names_for_search_values
|
||||
models = user_search_names.pluck(:name)
|
||||
|
||||
missing_values = values - models
|
||||
extra_values = models - values
|
||||
|
||||
::Domain::UserSearchName.upsert_all(
|
||||
missing_values.map { |name| { user_id: id, name: name } },
|
||||
unique_by: %i[user_id name],
|
||||
)
|
||||
::Domain::UserSearchName.where(user_id: id, name: extra_values).delete_all
|
||||
end
|
||||
|
||||
sig(:final) { returns(String) }
|
||||
def names_for_search_value
|
||||
sig(:final) { returns(T::Array[String]) }
|
||||
def names_for_search_values
|
||||
names_for_search
|
||||
.map { |name| name.downcase.gsub(/[^a-zA-Z0-9\-\.]/, "") }
|
||||
.map { |name| name.downcase.strip }
|
||||
.reject(&:blank?)
|
||||
.uniq
|
||||
.join("|")
|
||||
.sort
|
||||
end
|
||||
|
||||
attr_json :migrated_user_favs_at, :datetime
|
||||
|
||||
has_many :user_search_names,
|
||||
class_name: "::Domain::UserSearchName",
|
||||
inverse_of: :user,
|
||||
dependent: :destroy
|
||||
|
||||
has_many :user_post_creations,
|
||||
class_name: "::Domain::UserPostCreation",
|
||||
inverse_of: :user,
|
||||
|
||||
@@ -64,7 +64,7 @@ class Domain::User::FaUser < Domain::User
|
||||
|
||||
sig { override.returns(T::Array[String]) }
|
||||
def names_for_search
|
||||
[name, full_name].compact
|
||||
[name, url_name, full_name].compact
|
||||
end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
|
||||
6
app/models/domain/user_search_name.rb
Normal file
6
app/models/domain/user_search_name.rb
Normal file
@@ -0,0 +1,6 @@
|
||||
# typed: strict
|
||||
class Domain::UserSearchName < ReduxApplicationRecord
|
||||
self.table_name = "domain_user_search_names"
|
||||
belongs_to :user, class_name: "Domain::User", inverse_of: :user_search_names
|
||||
validates :name, presence: true
|
||||
end
|
||||
@@ -60,12 +60,30 @@ class CreateUnifiedDomainTables < ActiveRecord::Migration[7.2]
|
||||
|
||||
create_table :domain_users do |t|
|
||||
t.enum :type, null: false, enum_type: "domain_user_type"
|
||||
t.string :name_for_search
|
||||
t.jsonb :json_attributes, default: {}
|
||||
t.timestamps
|
||||
|
||||
t.index :type
|
||||
t.index :name_for_search, using: :gin, opclass: :gin_trgm_ops
|
||||
end
|
||||
|
||||
create_table :domain_user_search_names do |t|
|
||||
t.references :user, null: false, foreign_key: { to_table: :domain_users }
|
||||
|
||||
t.string :name, null: false
|
||||
t.virtual :dmetaphone_primary,
|
||||
type: :string,
|
||||
as: "dmetaphone(name)",
|
||||
stored: true
|
||||
t.virtual :dmetaphone_alt,
|
||||
type: :string,
|
||||
as: "dmetaphone_alt(name)",
|
||||
stored: true
|
||||
|
||||
t.index %i[user_id name], unique: true
|
||||
|
||||
t.index :name, using: :gin, opclass: :gin_trgm_ops
|
||||
t.index :dmetaphone_primary, using: :gin, opclass: :gin_trgm_ops
|
||||
t.index :dmetaphone_alt, using: :gin, opclass: :gin_trgm_ops
|
||||
end
|
||||
|
||||
create_table :domain_user_avatars do |t|
|
||||
|
||||
@@ -2993,6 +2993,38 @@ CREATE TABLE public.domain_user_post_favs (
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_search_names; Type: TABLE; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
CREATE TABLE public.domain_user_search_names (
|
||||
id bigint NOT NULL,
|
||||
user_id bigint NOT NULL,
|
||||
name character varying NOT NULL,
|
||||
dmetaphone_primary character varying GENERATED ALWAYS AS (public.dmetaphone((name)::text)) STORED,
|
||||
dmetaphone_alt character varying GENERATED ALWAYS AS (public.dmetaphone_alt((name)::text)) STORED
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_search_names_id_seq; Type: SEQUENCE; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE SEQUENCE public.domain_user_search_names_id_seq
|
||||
START WITH 1
|
||||
INCREMENT BY 1
|
||||
NO MINVALUE
|
||||
NO MAXVALUE
|
||||
CACHE 1;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_search_names_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER SEQUENCE public.domain_user_search_names_id_seq OWNED BY public.domain_user_search_names.id;
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_user_follows; Type: TABLE; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
@@ -3010,7 +3042,6 @@ CREATE TABLE public.domain_user_user_follows (
|
||||
CREATE TABLE public.domain_users (
|
||||
id bigint NOT NULL,
|
||||
type public.domain_user_type NOT NULL,
|
||||
name_for_search character varying,
|
||||
json_attributes jsonb DEFAULT '{}'::jsonb,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
@@ -4523,6 +4554,13 @@ ALTER TABLE ONLY public.domain_twitter_users ALTER COLUMN id SET DEFAULT nextval
|
||||
ALTER TABLE ONLY public.domain_user_avatars ALTER COLUMN id SET DEFAULT nextval('public.domain_user_avatars_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_search_names id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_search_names ALTER COLUMN id SET DEFAULT nextval('public.domain_user_search_names_id_seq'::regclass);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users id; Type: DEFAULT; Schema: public; Owner: -
|
||||
--
|
||||
@@ -5300,6 +5338,14 @@ ALTER TABLE ONLY public.domain_user_avatars
|
||||
ADD CONSTRAINT domain_user_avatars_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_search_names domain_user_search_names_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_search_names
|
||||
ADD CONSTRAINT domain_user_search_names_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_users domain_users_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
@@ -6948,6 +6994,41 @@ CREATE INDEX index_domain_user_post_favs_on_post_id_and_user_id ON public.domain
|
||||
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_search_names_on_dmetaphone_alt; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_search_names_on_dmetaphone_alt ON public.domain_user_search_names USING gin (dmetaphone_alt public.gin_trgm_ops);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_search_names_on_dmetaphone_primary; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_search_names_on_dmetaphone_primary ON public.domain_user_search_names USING gin (dmetaphone_primary public.gin_trgm_ops);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_search_names_on_name; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_search_names_on_name ON public.domain_user_search_names USING gin (name public.gin_trgm_ops);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_search_names_on_user_id; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_user_search_names_on_user_id ON public.domain_user_search_names USING btree (user_id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_search_names_on_user_id_and_name; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX index_domain_user_search_names_on_user_id_and_name ON public.domain_user_search_names USING btree (user_id, name);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_user_user_follows_on_from_id_and_to_id; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
@@ -6962,13 +7043,6 @@ CREATE UNIQUE INDEX index_domain_user_user_follows_on_from_id_and_to_id ON publi
|
||||
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_name_for_search; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
|
||||
CREATE INDEX index_domain_users_on_name_for_search ON public.domain_users USING gin (name_for_search public.gin_trgm_ops);
|
||||
|
||||
|
||||
--
|
||||
-- Name: index_domain_users_on_type; Type: INDEX; Schema: public; Owner: -; Tablespace: mirai
|
||||
--
|
||||
@@ -8300,6 +8374,14 @@ ALTER TABLE ONLY public.domain_inkbunny_posts
|
||||
ADD CONSTRAINT fk_rails_82ffd77f0c FOREIGN KEY (shallow_update_log_entry_id) REFERENCES public.http_log_entries(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_user_search_names fk_rails_8475fe75b5; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY public.domain_user_search_names
|
||||
ADD CONSTRAINT fk_rails_8475fe75b5 FOREIGN KEY (user_id) REFERENCES public.domain_users(id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: domain_fa_follows fk_rails_87bfff6dba; Type: FK CONSTRAINT; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
@@ -15,13 +15,13 @@ class Domain::Inkbunny::Job::UserGalleryJob
|
||||
|
||||
sig do
|
||||
params(
|
||||
args: T.untyped,
|
||||
args: T::Hash[::Symbol, T.untyped],
|
||||
block: T.nilable(T.proc.params(job: Domain::Inkbunny::Job::UserGalleryJob).void)
|
||||
).returns(T.any(Domain::Inkbunny::Job::UserGalleryJob, FalseClass))
|
||||
end
|
||||
def perform_later(args, &block); end
|
||||
|
||||
sig { params(args: T.untyped).returns(T.untyped) }
|
||||
sig { params(args: T::Hash[::Symbol, T.untyped]).returns(T.untyped) }
|
||||
def perform_now(args); end
|
||||
end
|
||||
end
|
||||
|
||||
71
sorbet/rbi/dsl/domain/user.rbi
generated
71
sorbet/rbi/dsl/domain/user.rbi
generated
@@ -530,6 +530,20 @@ class Domain::User
|
||||
sig { params(value: T::Enumerable[::Domain::UserPostFav]).void }
|
||||
def user_post_favs=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids; end
|
||||
|
||||
sig { params(ids: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids=(ids); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_search_names`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserSearchName::PrivateCollectionProxy) }
|
||||
def user_search_names; end
|
||||
|
||||
sig { params(value: T::Enumerable[::Domain::UserSearchName]).void }
|
||||
def user_search_names=(value); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_user_follows_from`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserUserFollow::PrivateCollectionProxy) }
|
||||
@@ -949,51 +963,6 @@ class Domain::User
|
||||
sig { void }
|
||||
def migrated_user_favs_at_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search; end
|
||||
|
||||
sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
|
||||
def name_for_search=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def name_for_search_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_was; end
|
||||
|
||||
sig { void }
|
||||
def name_for_search_will_change!; end
|
||||
|
||||
sig { void }
|
||||
def restore_created_at!; end
|
||||
|
||||
@@ -1009,9 +978,6 @@ class Domain::User
|
||||
sig { void }
|
||||
def restore_migrated_user_favs_at!; end
|
||||
|
||||
sig { void }
|
||||
def restore_name_for_search!; end
|
||||
|
||||
sig { void }
|
||||
def restore_type!; end
|
||||
|
||||
@@ -1048,12 +1014,6 @@ class Domain::User
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_migrated_user_favs_at?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_name_for_search; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable([T.untyped, T.untyped])) }
|
||||
def saved_change_to_type; end
|
||||
|
||||
@@ -1181,9 +1141,6 @@ class Domain::User
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_migrated_user_favs_at?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_type?; end
|
||||
|
||||
|
||||
71
sorbet/rbi/dsl/domain/user/e621_user.rbi
generated
71
sorbet/rbi/dsl/domain/user/e621_user.rbi
generated
@@ -576,6 +576,20 @@ class Domain::User::E621User
|
||||
sig { params(value: T::Enumerable[::Domain::UserPostFav]).void }
|
||||
def user_post_favs=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids; end
|
||||
|
||||
sig { params(ids: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids=(ids); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_search_names`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserSearchName::PrivateCollectionProxy) }
|
||||
def user_search_names; end
|
||||
|
||||
sig { params(value: T::Enumerable[::Domain::UserSearchName]).void }
|
||||
def user_search_names=(value); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_user_follows_from`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserUserFollow::PrivateCollectionProxy) }
|
||||
@@ -1112,51 +1126,6 @@ class Domain::User::E621User
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search; end
|
||||
|
||||
sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
|
||||
def name_for_search=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def name_for_search_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_was; end
|
||||
|
||||
sig { void }
|
||||
def name_for_search_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_in_database; end
|
||||
|
||||
@@ -1299,9 +1268,6 @@ class Domain::User::E621User
|
||||
sig { void }
|
||||
def restore_name!; end
|
||||
|
||||
sig { void }
|
||||
def restore_name_for_search!; end
|
||||
|
||||
sig { void }
|
||||
def restore_num_other_favs_cached!; end
|
||||
|
||||
@@ -1368,12 +1334,6 @@ class Domain::User::E621User
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_name?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_name_for_search; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_num_other_favs_cached; end
|
||||
|
||||
@@ -1634,9 +1594,6 @@ class Domain::User::E621User
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_name?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_num_other_favs_cached?; end
|
||||
|
||||
|
||||
71
sorbet/rbi/dsl/domain/user/fa_user.rbi
generated
71
sorbet/rbi/dsl/domain/user/fa_user.rbi
generated
@@ -616,6 +616,20 @@ class Domain::User::FaUser
|
||||
sig { params(value: T::Enumerable[::Domain::UserPostFav]).void }
|
||||
def user_post_favs=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids; end
|
||||
|
||||
sig { params(ids: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids=(ids); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_search_names`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserSearchName::PrivateCollectionProxy) }
|
||||
def user_search_names; end
|
||||
|
||||
sig { params(value: T::Enumerable[::Domain::UserSearchName]).void }
|
||||
def user_search_names=(value); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_user_follows_from`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserUserFollow::PrivateCollectionProxy) }
|
||||
@@ -1432,51 +1446,6 @@ class Domain::User::FaUser
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search; end
|
||||
|
||||
sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
|
||||
def name_for_search=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def name_for_search_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_was; end
|
||||
|
||||
sig { void }
|
||||
def name_for_search_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_in_database; end
|
||||
|
||||
@@ -1952,9 +1921,6 @@ class Domain::User::FaUser
|
||||
sig { void }
|
||||
def restore_name!; end
|
||||
|
||||
sig { void }
|
||||
def restore_name_for_search!; end
|
||||
|
||||
sig { void }
|
||||
def restore_num_comments_given!; end
|
||||
|
||||
@@ -2093,12 +2059,6 @@ class Domain::User::FaUser
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_name?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_name_for_search; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::Integer), T.nilable(::Integer)])) }
|
||||
def saved_change_to_num_comments_given; end
|
||||
|
||||
@@ -2714,9 +2674,6 @@ class Domain::User::FaUser
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_name?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_num_comments_given?; end
|
||||
|
||||
|
||||
71
sorbet/rbi/dsl/domain/user/inkbunny_user.rbi
generated
71
sorbet/rbi/dsl/domain/user/inkbunny_user.rbi
generated
@@ -621,6 +621,20 @@ class Domain::User::InkbunnyUser
|
||||
sig { params(value: T::Enumerable[::Domain::UserPostFav]).void }
|
||||
def user_post_favs=(value); end
|
||||
|
||||
sig { returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids; end
|
||||
|
||||
sig { params(ids: T::Array[T.untyped]).returns(T::Array[T.untyped]) }
|
||||
def user_search_name_ids=(ids); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_search_names`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserSearchName::PrivateCollectionProxy) }
|
||||
def user_search_names; end
|
||||
|
||||
sig { params(value: T::Enumerable[::Domain::UserSearchName]).void }
|
||||
def user_search_names=(value); end
|
||||
|
||||
# This method is created by ActiveRecord on the `Domain::User` class because it declared `has_many :user_user_follows_from`.
|
||||
# 🔗 [Rails guide for `has_many` association](https://guides.rubyonrails.org/association_basics.html#the-has-many-association)
|
||||
sig { returns(::Domain::UserUserFollow::PrivateCollectionProxy) }
|
||||
@@ -1202,51 +1216,6 @@ class Domain::User::InkbunnyUser
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search; end
|
||||
|
||||
sig { params(value: T.nilable(::String)).returns(T.nilable(::String)) }
|
||||
def name_for_search=(value); end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_before_last_save; end
|
||||
|
||||
sig { returns(T.untyped) }
|
||||
def name_for_search_before_type_cast; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def name_for_search_came_from_user?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_change_to_be_saved; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_in_database; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def name_for_search_previous_change; end
|
||||
|
||||
sig { params(from: T.nilable(::String), to: T.nilable(::String)).returns(T::Boolean) }
|
||||
def name_for_search_previously_changed?(from: T.unsafe(nil), to: T.unsafe(nil)); end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_previously_was; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_for_search_was; end
|
||||
|
||||
sig { void }
|
||||
def name_for_search_will_change!; end
|
||||
|
||||
sig { returns(T.nilable(::String)) }
|
||||
def name_in_database; end
|
||||
|
||||
@@ -1292,9 +1261,6 @@ class Domain::User::InkbunnyUser
|
||||
sig { void }
|
||||
def restore_name!; end
|
||||
|
||||
sig { void }
|
||||
def restore_name_for_search!; end
|
||||
|
||||
sig { void }
|
||||
def restore_scanned_gallery_at!; end
|
||||
|
||||
@@ -1364,12 +1330,6 @@ class Domain::User::InkbunnyUser
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_name?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::String), T.nilable(::String)])) }
|
||||
def saved_change_to_name_for_search; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def saved_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T.nilable([T.nilable(::ActiveSupport::TimeWithZone), T.nilable(::ActiveSupport::TimeWithZone)])) }
|
||||
def saved_change_to_scanned_gallery_at; end
|
||||
|
||||
@@ -1672,9 +1632,6 @@ class Domain::User::InkbunnyUser
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_name?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_name_for_search?; end
|
||||
|
||||
sig { returns(T::Boolean) }
|
||||
def will_save_change_to_scanned_gallery_at?; end
|
||||
|
||||
|
||||
1273
sorbet/rbi/dsl/domain/user_search_name.rbi
generated
Normal file
1273
sorbet/rbi/dsl/domain/user_search_name.rbi
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -151,6 +151,14 @@ RSpec.describe Domain::MigrateToDomain do
|
||||
)
|
||||
end
|
||||
|
||||
it "migrates search names" do
|
||||
migrator.migrate_fa_users
|
||||
new_user = Domain::User::FaUser.find_by(url_name: old_user.url_name)
|
||||
expect(new_user.user_search_names.pluck(:name)).to match_array(
|
||||
["test user full name", "test_user", "testuser"],
|
||||
)
|
||||
end
|
||||
|
||||
it "handles multiple users in batches" do
|
||||
# Create a few more old users
|
||||
additional_users =
|
||||
|
||||
@@ -148,5 +148,32 @@ RSpec.describe Domain::User::FaUser, type: :model do
|
||||
expect(user.posts).not_to include(faved_post1, faved_post2)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#user_search_names" do
|
||||
let(:user) do
|
||||
create(
|
||||
:domain_user_fa_user,
|
||||
name: "name_attr",
|
||||
url_name: "url_name_attr",
|
||||
full_name: "artist name",
|
||||
)
|
||||
end
|
||||
|
||||
it "returns associated user search names" do
|
||||
user.reload
|
||||
expect(user.user_search_names.map(&:name)).to match_array(
|
||||
["name_attr", "url_name_attr", "artist name"],
|
||||
)
|
||||
end
|
||||
|
||||
it "changes search names when name changes" do
|
||||
user.name = "new_name"
|
||||
user.save!
|
||||
user.reload
|
||||
expect(user.user_search_names.map(&:name)).to match_array(
|
||||
["artist name", "new_name", "url_name_attr"],
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user