fix e621 scan post job

This commit is contained in:
Dylan Knutson
2024-12-23 22:49:55 +00:00
parent 9391a2cfe1
commit 1c86e73df9
17 changed files with 624 additions and 442 deletions

View File

@@ -6,7 +6,7 @@
"workbench.preferredLightColorTheme": "Spinel Light",
"rubyLsp.formatter": "syntax_tree",
"[ruby]": {
"editor.defaultFormatter": "Shopify.ruby-lsp"
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[erb]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"

View File

@@ -1,149 +1,60 @@
module Domain::E621::Job
class PostsIndexJob < Base
TagAndCategory = Domain::E621::TagUtil::TagAndCategory
queue_as :e621
ignore_signature_args :caused_by_entry
def perform(args)
@caused_by_entry = args[:caused_by_entry]
caused_by_entry = args[:caused_by_entry]
response =
http_client.get(
"https://e621.net/posts.json",
caused_by_entry: @caused_by_entry
caused_by_entry: caused_by_entry,
)
if response.status_code != 200
fatal_error(
"non 200 response for /posts.json: #{response.status_code.to_s.underline}"
"non 200 response for /posts.json: #{response.status_code.to_s.underline}",
)
end
@log_entry = response.log_entry
index_log_entry = response.log_entry
json = JSON.parse(response.body)
if json["posts"].nil?
fatal_error("no posts in response: HLE #{@log_entry.id}}")
fatal_error("no posts in response: HLE #{index_log_entry.id}}")
end
e621_id_to_post =
Domain::E621::Post
.where(e621_id: json["posts"].map { |post_json| post_json["id"] })
.includes(taggings: :tag)
.index_by(&:e621_id)
e621_posts =
json["posts"].map do |post_json|
Domain::E621::TagUtil.initialize_or_update_post(
post_json: post_json,
caused_by_entry: index_log_entry,
)
end
@num_updated = 0
@num_created = 0
@num_seen = 0
created_posts = []
updated_posts = []
seen_posts = []
all_tag_names =
Set.new json["posts"]
.map { |post_json| tag_and_cat_for_json(post_json) }
.flatten
.map(&:name)
e621_posts.each do |e621_post|
created_posts << e621_post if e621_post.new_record?
updated_posts << e621_post if e621_post.changed?
seen_posts << e621_post
e621_post.save!
end
@name_to_tag_id, missing_tags =
Domain::E621::TagUtil.tag_names_to_id_map(
all_tag_names,
posts: e621_id_to_post.values
(created_posts + updated_posts).uniq.each do |post|
logger.info(
"[e621_id: #{post.e621_id.to_s.bold}] enqueueing static file job",
)
@name_to_tag_id.merge!(
Domain::E621::TagUtil.create_tags_from_names(missing_tags)
)
json["posts"].each do |post_json|
@num_seen += 1
e621_id = post_json["id"]
post =
e621_id_to_post[e621_id] ||
begin
@num_created += 1
Domain::E621::Post.new({ e621_id: e621_id })
end
logger.prefix = proc { "[e621_id #{post.e621_id.to_s.bold}]" }
@num_updated += 1 if update_post!(post, post_json)
end
logger.prefix = nil
logger.info(
"#{@num_updated} updated, #{@num_created} created, #{@num_seen} seen"
)
end
private
def update_post!(post, post_json)
e621_updated_at = post_json["updated_at"]
return false if post.state_detail["e621_updated_at"] == e621_updated_at
post.state_detail["e621_updated_at"] = post_json["updated_at"]
post.state_detail["index_page_ids"] ||= []
post.state_detail["index_page_ids"] << @log_entry.id
post.state_detail["last_index_page_id"] = @log_entry.id
e621_md5 = post_json["file"]["md5"]
if post.md5 && post.md5 != e621_md5
logger.warn(
"md5 changed for post: #{post.md5.to_s.bold} => #{e621_md5.to_s.bold}"
)
post.state_detail["prev_md5s"] ||= []
post.state_detail["prev_md5s"] << {
"md5" => post.md5,
"file_id" => post.file_id
}
post.file = nil
file_changed = true
else
file_changed = false
end
post.md5 = e621_md5
post.file_url_str ||= post_json["file"]["url"]
post.description = post_json["description"]
post.rating = post_json["rating"]
post.score = post_json["score"]["total"]
post.score_up = post_json["score"]["up"]
post.score_down = post_json["score"]["down"]
post.num_favorites = post_json["fav_count"]
post.num_comments = post_json["comment_count"]
post.change_seq = post_json["change_seq"]
post.parent_e621_id = post_json["relationships"]["parent_id"]
post.flags_array = post_json["flags"].to_a.select(&:second).map(&:first)
post.pools_array = post_json["pools"]
post.sources_array = post_json["sources"]
post.tags_array = post_json["tags"]
new_record = post.new_record?
Domain::E621::Post.transaction do
post.save!
Domain::E621::TagUtil.update_tags_on_post_with_cat(
post,
tag_and_cat_for_json(post_json),
@name_to_tag_id
)
end
if new_record || file_changed
defer_job(
Domain::E621::Job::StaticFileJob,
{ post: post, caused_by_entry: @log_entry }
{ post: post, caused_by_entry: index_log_entry },
)
end
true
end
TAG_CATEGORIES = %w[general species character copyright artist lore meta]
def tag_and_cat_for_json(post_json)
TAG_CATEGORIES
.map do |tc|
post_json["tags"][tc].map do |name|
TagAndCategory.new(name, "cat_#{tc}")
end
end
.flatten
logger.info(
"#{updated_posts.count} updated, #{created_posts.count} created, #{seen_posts.count} seen",
)
end
end
end

View File

@@ -4,7 +4,53 @@ module Domain::E621::Job
ignore_signature_args :caused_by_entry
def perform(args)
logger.info("ScanPostJob args: #{args.inspect}")
post = args[:post] || raise("no post provided")
@caused_by_entry = args[:caused_by_entry]
logger.prefix =
proc { "[e621_id #{post.e621_id.to_s.bold} / #{post.state.bold}]" }
if post.file.present?
logger.warn("Post #{post.e621_id} already has a file")
return
end
if post.file_url_str.present?
logger.error("Post #{post.e621_id} already has a file URL")
return
end
logger.info("Scanning post #{post.e621_id}")
response =
http_client.get(
"https://e621.net/posts/#{post.e621_id}.json",
caused_by_entry: @caused_by_entry,
)
if response.status_code != 200
post.state_detail["scan_log_entry_id"] = response.log_entry.id
post.state = :scan_error
post.state_detail[
"scan_error"
] = "Error scanning post #{post.e621_id}: #{response.status_code}"
post.save!
fatal_error(
"Error scanning post #{post.e621_id}: #{response.status_code}",
)
end
post_json = JSON.parse(response.body)["post"]
post =
Domain::E621::TagUtil.initialize_or_update_post(
post_json: post_json,
caused_by_entry: response.log_entry,
)
post.save!
unless post.file.present?
Domain::E621::Job::StaticFileJob.perform_later(
{ post: post, caused_by_entry: response.log_entry },
)
end
end
end
end

View File

@@ -42,7 +42,7 @@ class Scraper::JobBase < ApplicationJob
sig << Digest::SHA256.hexdigest(sig_arguments.inspect)[0...16]
sig = sig.join("|")
sig
end
end,
)
# make the concurrency config threadlocal so it can be modified
@@ -87,21 +87,21 @@ class Scraper::JobBase < ApplicationJob
attr_to_mapper.call(
Domain::Fa::User,
:url_name,
filter_mapper.call(links, :fa_user, :url_name)
filter_mapper.call(links, :fa_user, :url_name),
)
fa_id_to_fa_post =
attr_to_mapper.call(
Domain::Fa::Post,
:fa_id,
filter_mapper.call(links, :fa_post, :fa_id)
filter_mapper.call(links, :fa_post, :fa_id),
)
name_to_twitter_user =
attr_to_mapper.call(
Domain::Twitter::User,
:name,
filter_mapper.call(links, :twitter_user, :name)
filter_mapper.call(links, :twitter_user, :name),
)
links.each do |link|
@@ -143,18 +143,18 @@ class Scraper::JobBase < ApplicationJob
(
{
params: params,
desc: "twitter user " + (user&.name || name).bold
desc: "twitter user " + (user&.name || name).bold,
}
)
if !user || user.due_for_timeline_tweets_scan?
job_defs << job_def.merge(
job: Domain::Twitter::Job::UserTimelineTweetsJob
job: Domain::Twitter::Job::UserTimelineTweetsJob,
)
end
else
logger.warn(
"unknown link type #{link_type.to_s.bold}: #{link.inspect.bold}"
"unknown link type #{link_type.to_s.bold}: #{link.inspect.bold}",
)
end
end
@@ -173,15 +173,15 @@ class Scraper::JobBase < ApplicationJob
[
"link finder -",
job_class.name.split("::").last.to_s.ljust(22).bold.light_black,
desc
].join(" ")
desc,
].join(" "),
)
defer_job(job_class, params.merge({ caused_by_entry: log_entry }))
end
duration_ms = (1000 * (Time.now - start_time)).to_i.to_s
logger.info(
"link finder - enqueue #{job_defs.size.to_s.light_white.bold} jobs (#{duration_ms.bold} ms)"
"link finder - enqueue #{job_defs.size.to_s.light_white.bold} jobs (#{duration_ms.bold} ms)",
)
end

View File

@@ -3,86 +3,59 @@ module Domain::E621::TagUtil
TagAndCategory = Struct.new(:name, :category)
# convert tag names [String] into {String -> Integer} ID map
def self.tag_names_to_id_map(tag_names, posts: [])
tags = Domain::E621::Tag.where(name: tag_names)
name_to_tag_id = tags.map { |tag| [tag.name, tag.id] }.to_h
posts.each do |post|
post.tags.each { |tag| name_to_tag_id[tag.name] = tag.id }
end
[
# main tag map
name_to_tag_id,
# missing tags
tag_names - tags.map(&:name)
]
end
def self.initialize_or_update_post(post_json:, caused_by_entry: nil)
# create all posts that don't already exist
e621_id = post_json["id"]
e621_post = Domain::E621::Post.find_or_initialize_by(e621_id: e621_id)
def self.create_tags_from_names(tag_names)
return {} unless tag_names.any?
e621_tag_names =
Domain::E621::Tagging
.categories
.keys
.flat_map { |tag_category| post_json["tags"][tag_category] }
.sort
.uniq
logger.info("creating #{tag_names.size.to_s.bold} missing tags")
upsert_hashes = tag_names.map { |name| { name: name } }
name_to_tag_id = {}
Domain::E621::Tag
.upsert_all(
upsert_hashes,
unique_by: :name,
update_only: :name,
returning: %i[id name]
e621_updated_at = post_json["updated_at"]
return false if e621_post.state_detail["e621_updated_at"] == e621_updated_at
e621_post.state_detail["e621_updated_at"] = post_json["updated_at"]
e621_post.state_detail["index_page_ids"] ||= []
e621_post.state_detail[
"caused_by_entry_id"
] = caused_by_entry.id if caused_by_entry
e621_md5 = post_json["file"]["md5"]
if e621_post.md5 && e621_post.md5 != e621_md5
logger.warn(
"md5 changed for post: #{e621_post.md5.to_s.bold} => #{e621_md5.to_s.bold}",
)
.each { |row| name_to_tag_id[row["name"]] = row["id"] }
name_to_tag_id
end
def self.update_tags_on_post(post, tags, name_to_tag_id)
model_tags = tag_and_cat_for_model(post).map(&:name)
to_add = tags - model_tags
to_remove = model_tags - tags
add_and_remove_tags(post, to_add, to_remove, name_to_tag_id)
end
def self.update_tags_on_post_with_cat(post, tag_and_cats, name_to_tag_id)
model_tag_and_cats = tag_and_cat_for_model(post)
to_add = tag_and_cats - model_tag_and_cats
to_remove = model_tag_and_cats - tag_and_cats
add_and_remove_tags(post, to_add, to_remove, name_to_tag_id)
end
def self.tag_and_cat_for_model(model)
model.taggings.map do |tagging|
TagAndCategory.new(tagging.tag.name, tagging.category)
end
end
def self.add_and_remove_tags(post, to_add, to_remove, name_to_tag_id)
raise("post must be persisted") if post.new_record?
if to_remove.any?
to_remove_ids =
to_remove.map do |tacos|
name = (tacos.is_a?(TagAndCategory) ? tacos.name : tacos)
name_to_tag_id[name] || raise("invariant: #{name} not in id map")
end
post.taggings.where(tag_id: to_remove_ids).delete_all
e621_post.state_detail["prev_md5s"] ||= []
e621_post.state_detail["prev_md5s"] << {
"md5" => e621_post.md5,
"file_id" => e621_post.file_id,
}
e621_post.file = nil
end
post.taggings.insert_all!(
to_add.map do |tacos|
name = tag_and_cat_or_str_to_name(tacos)
id = name_to_tag_id[name] || raise("invariant: #{name} not in id map")
e621_post.md5 = e621_md5
e621_post.file_url_str = post_json["file"]["url"]
e621_post.description = post_json["description"]
e621_post.rating = post_json["rating"]
e621_post.score = post_json["score"]["total"]
e621_post.score_up = post_json["score"]["up"]
e621_post.score_down = post_json["score"]["down"]
e621_post.num_favorites = post_json["fav_count"]
e621_post.num_comments = post_json["comment_count"]
e621_post.change_seq = post_json["change_seq"]
e621_post.parent_e621_id = post_json["relationships"]["parent_id"]
if tacos.is_a?(TagAndCategory)
{ tag_id: id, category: tacos.category }
else
{ tag_id: id, category: "cat_general" }
end
end
) if to_add.any?
end
e621_post.flags_array =
post_json["flags"].to_a.select(&:second).map(&:first)
e621_post.pools_array = post_json["pools"]
e621_post.sources_array = post_json["sources"]
e621_post.tags_array = e621_tag_names
def self.tag_and_cat_or_str_to_name(tacos)
tacos.is_a?(TagAndCategory) ? tacos.name : tacos
e621_post
end
end

View File

@@ -21,8 +21,7 @@ class Domain::E621::Post < ReduxApplicationRecord
self.tags_array ||= []
end
has_many :taggings, class_name: "Domain::E621::Tagging"
has_many :taggings, class_name: "Domain::E621::Tagging", inverse_of: :post
has_many :tags, class_name: "Domain::E621::Tag", through: :taggings
# If the file was scraped, this is the blob entry that represents it
@@ -49,8 +48,8 @@ class Domain::E621::Post < ReduxApplicationRecord
rating: legacy_model.rating,
sources_array: legacy_model.sources,
tags_array: legacy_model.tags.map(&:value),
artists_array: legacy_model.artists || []
}
artists_array: legacy_model.artists || [],
},
)
if legacy_model.e621_status != "active"
@@ -65,7 +64,7 @@ class Domain::E621::Post < ReduxApplicationRecord
http_log_entries =
::HttpLogEntry.where(
uri_host: model.file_uri.host,
uri_path: model.file_uri.path
uri_path: model.file_uri.path,
)
http_log_entry = http_log_entries.first
@@ -73,7 +72,7 @@ class Domain::E621::Post < ReduxApplicationRecord
legacy_hles =
::Legacy::HttpLogEntry.where(
host: model.file_uri.host,
path: model.file_uri.path
path: model.file_uri.path,
)
legacy_hle = legacy_hles.first
@@ -90,8 +89,8 @@ class Domain::E621::Post < ReduxApplicationRecord
requested_at: Time.now,
request_headers: ::HttpLogEntryHeader.empty,
response_headers: ::HttpLogEntryHeader.empty,
performed_by: "legacy"
}
performed_by: "legacy",
},
)
end
@@ -105,7 +104,7 @@ class Domain::E621::Post < ReduxApplicationRecord
# unable to construct http & blob entries, skip
File.write(
Rails.root.join("tmp/e621_legacy_post_importer_failures"),
"#{model.e621_id} - (no hle) - unable to reconstruct http / blob entry\n"
"#{model.e621_id} - (no hle) - unable to reconstruct http / blob entry\n",
)
http_log_entry = nil
end
@@ -117,7 +116,7 @@ class Domain::E621::Post < ReduxApplicationRecord
if model.md5 != Digest::MD5.hexdigest(blob_entry.contents)
File.write(
Rails.root.join("tmp/e621_legacy_post_importer_failures"),
"#{model.e621_id} - #{http_log_entry.status_code} - expected #{model.md5} != actual #{Digest::MD5.hexdigest(blob_entry.contents)}\n"
"#{model.e621_id} - #{http_log_entry.status_code} - expected #{model.md5} != actual #{Digest::MD5.hexdigest(blob_entry.contents)}\n",
)
http_log_entry = nil
end

View File

@@ -1,3 +1,4 @@
class Domain::E621::Tag < ReduxApplicationRecord
self.table_name = "domain_e621_tags"
has_many :taggings, class_name: "Domain::E621::Tagging", inverse_of: :tag
end

View File

@@ -1,18 +1,13 @@
class Domain::E621::Tagging < ReduxApplicationRecord
self.table_name = "domain_e621_taggings"
belongs_to :post, class_name: "Domain::E621::Post"
belongs_to :tag, class_name: "Domain::E621::Tag"
self.primary_key = %i[post_id tag_id]
belongs_to :post, class_name: "Domain::E621::Post", inverse_of: :taggings
belongs_to :tag, class_name: "Domain::E621::Tag", inverse_of: :taggings
validates_presence_of :post, :tag
enum :category,
%i[
cat_general
cat_artist
cat_copyright
cat_character
cat_species
cat_invalid
cat_meta
cat_lore
]
%i[general artist copyright character species invalid meta lore],
prefix: true
validates_inclusion_of(:category, in: self.categories.keys)
end

View File

@@ -0,0 +1,30 @@
class UniqueE621TaggingsIndex < ActiveRecord::Migration[7.2]
def up
add_index :domain_e621_taggings, %i[post_id tag_id], unique: true
remove_index :domain_e621_taggings, :post_id
remove_index :domain_e621_taggings, :tag_id
remove_column :domain_e621_taggings, :id, :bigint
# columns cannot be null
change_column_null :domain_e621_taggings, :post_id, false
change_column_null :domain_e621_taggings, :tag_id, false
# foreign key constraints
add_foreign_key :domain_e621_taggings, :domain_e621_posts, column: :post_id
add_foreign_key :domain_e621_taggings, :domain_e621_tags, column: :tag_id
end
def down
add_column :domain_e621_taggings, :id, :bigint, primary_key: true
add_index :domain_e621_taggings, :post_id
add_index :domain_e621_taggings, :tag_id
remove_index :domain_e621_taggings, %i[post_id tag_id]
change_column_null :domain_e621_taggings, :post_id, true
change_column_null :domain_e621_taggings, :tag_id, true
# foreign key constraints
remove_foreign_key :domain_e621_taggings, :domain_e621_posts
remove_foreign_key :domain_e621_taggings, :domain_e621_tags
end
end

240
db/schema.rb generated
View File

@@ -10,15 +10,25 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
ActiveRecord::Schema[7.2].define(version: 2024_12_23_175146) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_prewarm"
enable_extension "pg_stat_statements"
enable_extension "pg_trgm"
enable_extension "pgcrypto"
enable_extension "plpgsql"
enable_extension "vector"
create_table "blob_entries", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
t.binary "contents", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["sha256"], name: "index_blob_entries_on_sha256", unique: true
end
create_table "blob_entries_p", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
@@ -29,7 +39,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_on_sha256", unique: true
end
create_table "blob_entries_p_00", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_00", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -38,7 +49,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_00_on_sha256", unique: true
end
create_table "blob_entries_p_01", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_01", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -47,7 +59,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_01_on_sha256", unique: true
end
create_table "blob_entries_p_02", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_02", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -56,7 +69,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_02_on_sha256", unique: true
end
create_table "blob_entries_p_03", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_03", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -65,7 +79,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_03_on_sha256", unique: true
end
create_table "blob_entries_p_04", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_04", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -74,7 +89,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_04_on_sha256", unique: true
end
create_table "blob_entries_p_05", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_05", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -83,7 +99,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_05_on_sha256", unique: true
end
create_table "blob_entries_p_06", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_06", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -92,7 +109,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_06_on_sha256", unique: true
end
create_table "blob_entries_p_07", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_07", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -101,7 +119,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_07_on_sha256", unique: true
end
create_table "blob_entries_p_08", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_08", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -110,7 +129,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_08_on_sha256", unique: true
end
create_table "blob_entries_p_09", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_09", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -119,7 +139,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_09_on_sha256", unique: true
end
create_table "blob_entries_p_10", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_10", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -128,7 +149,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_10_on_sha256", unique: true
end
create_table "blob_entries_p_11", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_11", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -137,7 +159,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_11_on_sha256", unique: true
end
create_table "blob_entries_p_12", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_12", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -146,7 +169,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_12_on_sha256", unique: true
end
create_table "blob_entries_p_13", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_13", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -155,7 +179,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_13_on_sha256", unique: true
end
create_table "blob_entries_p_14", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_14", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -164,7 +189,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_14_on_sha256", unique: true
end
create_table "blob_entries_p_15", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_15", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -173,7 +199,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_15_on_sha256", unique: true
end
create_table "blob_entries_p_16", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_16", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -182,7 +209,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_16_on_sha256", unique: true
end
create_table "blob_entries_p_17", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_17", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -191,7 +219,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_17_on_sha256", unique: true
end
create_table "blob_entries_p_18", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_18", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -200,7 +229,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_18_on_sha256", unique: true
end
create_table "blob_entries_p_19", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_19", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -209,7 +239,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_19_on_sha256", unique: true
end
create_table "blob_entries_p_20", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_20", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -218,7 +249,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_20_on_sha256", unique: true
end
create_table "blob_entries_p_21", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_21", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -227,7 +259,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_21_on_sha256", unique: true
end
create_table "blob_entries_p_22", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_22", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -236,7 +269,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_22_on_sha256", unique: true
end
create_table "blob_entries_p_23", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_23", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -245,7 +279,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_23_on_sha256", unique: true
end
create_table "blob_entries_p_24", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_24", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -254,7 +289,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_24_on_sha256", unique: true
end
create_table "blob_entries_p_25", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_25", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -263,7 +299,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_25_on_sha256", unique: true
end
create_table "blob_entries_p_26", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_26", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -272,7 +309,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_26_on_sha256", unique: true
end
create_table "blob_entries_p_27", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_27", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -281,7 +319,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_27_on_sha256", unique: true
end
create_table "blob_entries_p_28", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_28", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -290,7 +329,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_28_on_sha256", unique: true
end
create_table "blob_entries_p_29", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_29", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -299,7 +339,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_29_on_sha256", unique: true
end
create_table "blob_entries_p_30", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_30", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -308,7 +349,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_30_on_sha256", unique: true
end
create_table "blob_entries_p_31", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_31", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -317,7 +359,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_31_on_sha256", unique: true
end
create_table "blob_entries_p_32", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_32", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -326,7 +369,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_32_on_sha256", unique: true
end
create_table "blob_entries_p_33", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_33", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -335,7 +379,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_33_on_sha256", unique: true
end
create_table "blob_entries_p_34", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_34", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -344,7 +389,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_34_on_sha256", unique: true
end
create_table "blob_entries_p_35", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_35", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -353,7 +399,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_35_on_sha256", unique: true
end
create_table "blob_entries_p_36", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_36", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -362,7 +409,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_36_on_sha256", unique: true
end
create_table "blob_entries_p_37", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_37", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -371,7 +419,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_37_on_sha256", unique: true
end
create_table "blob_entries_p_38", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_38", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -380,7 +429,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_38_on_sha256", unique: true
end
create_table "blob_entries_p_39", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_39", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -389,7 +439,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_39_on_sha256", unique: true
end
create_table "blob_entries_p_40", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_40", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -398,7 +449,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_40_on_sha256", unique: true
end
create_table "blob_entries_p_41", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_41", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -407,7 +459,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_41_on_sha256", unique: true
end
create_table "blob_entries_p_42", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_42", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -416,7 +469,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_42_on_sha256", unique: true
end
create_table "blob_entries_p_43", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_43", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -425,7 +479,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_43_on_sha256", unique: true
end
create_table "blob_entries_p_44", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_44", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -434,7 +489,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_44_on_sha256", unique: true
end
create_table "blob_entries_p_45", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_45", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -443,7 +499,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_45_on_sha256", unique: true
end
create_table "blob_entries_p_46", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_46", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -452,7 +509,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_46_on_sha256", unique: true
end
create_table "blob_entries_p_47", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_47", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -461,7 +519,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_47_on_sha256", unique: true
end
create_table "blob_entries_p_48", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_48", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -470,7 +529,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_48_on_sha256", unique: true
end
create_table "blob_entries_p_49", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_49", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -479,7 +539,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_49_on_sha256", unique: true
end
create_table "blob_entries_p_50", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_50", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -488,7 +549,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_50_on_sha256", unique: true
end
create_table "blob_entries_p_51", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_51", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -497,7 +559,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_51_on_sha256", unique: true
end
create_table "blob_entries_p_52", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_52", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -506,7 +569,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_52_on_sha256", unique: true
end
create_table "blob_entries_p_53", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_53", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -515,7 +579,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_53_on_sha256", unique: true
end
create_table "blob_entries_p_54", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_54", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -524,7 +589,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_54_on_sha256", unique: true
end
create_table "blob_entries_p_55", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_55", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -533,7 +599,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_55_on_sha256", unique: true
end
create_table "blob_entries_p_56", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_56", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -542,7 +609,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_56_on_sha256", unique: true
end
create_table "blob_entries_p_57", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_57", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -551,7 +619,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_57_on_sha256", unique: true
end
create_table "blob_entries_p_58", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_58", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -560,7 +629,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_58_on_sha256", unique: true
end
create_table "blob_entries_p_59", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_59", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -569,7 +639,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_59_on_sha256", unique: true
end
create_table "blob_entries_p_60", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_60", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -578,7 +649,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_60_on_sha256", unique: true
end
create_table "blob_entries_p_61", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_61", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -587,7 +659,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_61_on_sha256", unique: true
end
create_table "blob_entries_p_62", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_62", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -596,7 +669,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["sha256"], name: "index_blob_entries_p_62_on_sha256", unique: true
end
create_table "blob_entries_p_63", primary_key: "sha256", id: :binary, force: :cascade do |t|
create_table "blob_entries_p_63", id: false, force: :cascade do |t|
t.binary "sha256", null: false
t.binary "base_sha256"
t.string "content_type", null: false
t.integer "size", null: false
@@ -1269,9 +1343,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.datetime "updated_at"
t.string "signature"
t.jsonb "args"
t.index ["priority", "run_at"], name: "delayed_jobs_priority_run_at_idx"
t.index ["queue"], name: "delayed_jobs_queue_idx"
t.index ["signature"], name: "delayed_jobs_signature_idx", unique: true
t.index ["priority", "run_at"], name: "delayed_jobs_priority"
end
create_table "domain_e621_post_versions", force: :cascade do |t|
@@ -1313,12 +1385,11 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["parent_e621_id"], name: "index_domain_e621_posts_on_parent_e621_id"
end
create_table "domain_e621_taggings", force: :cascade do |t|
create_table "domain_e621_taggings", id: false, force: :cascade do |t|
t.integer "category"
t.bigint "post_id"
t.bigint "tag_id"
t.index ["post_id"], name: "index_domain_e621_taggings_on_post_id"
t.index ["tag_id"], name: "index_domain_e621_taggings_on_tag_id"
t.bigint "post_id", null: false
t.bigint "tag_id", null: false
t.index ["post_id", "tag_id"], name: "index_domain_e621_taggings_on_post_id_and_tag_id", unique: true
end
create_table "domain_e621_tags", force: :cascade do |t|
@@ -1333,6 +1404,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
create_table "domain_fa_favs", id: false, force: :cascade do |t|
t.bigint "user_id", null: false
t.bigint "post_id", null: false
t.index ["post_id"], name: "index_domain_fa_favs_on_post_id"
t.index ["user_id", "post_id"], name: "index_domain_fa_favs_on_user_id_and_post_id", unique: true
t.index ["user_id"], name: "index_domain_fa_favs_on_user_id"
end
@@ -1375,7 +1447,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.jsonb "state_detail"
t.jsonb "log_entry_detail"
t.index ["creator_id"], name: "index_domain_fa_posts_on_creator_id"
t.index ["fa_id", "id"], name: "index_domain_fa_posts_on_fa_id", unique: true
t.index ["fa_id"], name: "index_domain_fa_posts_on_fa_id", unique: true
t.index ["file_id"], name: "index_domain_fa_posts_on_file_id"
end
@@ -1435,9 +1507,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.jsonb "state_detail"
t.datetime "scanned_follows_at"
t.datetime "scanned_favs_at"
t.index ["name"], name: "domain_fa_users_name_idx", opclass: :gist_trgm_ops, using: :gist
t.index ["name"], name: "index_domain_fa_users_on_name", unique: true
t.index ["url_name"], name: "domain_fa_users_url_name_idx", opclass: :gist_trgm_ops, using: :gist
t.index ["url_name"], name: "index_domain_fa_users_on_url_name", unique: true
end
@@ -1533,13 +1603,6 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.datetime "updated_at", null: false
end
create_table "domain_inkbunny_user_avatars", force: :cascade do |t|
t.bigint "user_id", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["user_id"], name: "index_domain_inkbunny_user_avatars_on_user_id"
end
create_table "domain_inkbunny_users", force: :cascade do |t|
t.integer "state", null: false
t.json "state_detail"
@@ -1595,6 +1658,7 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.integer "state"
t.json "state_detail"
t.json "raw_data"
t.integer "tw_id"
t.string "name", null: false
t.string "nick"
t.string "description"
@@ -1605,7 +1669,6 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.datetime "scanned_timeline_at"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "tw_id"
t.index ["name"], name: "index_domain_twitter_users_on_name", unique: true
t.index ["tw_id"], name: "index_domain_twitter_users_on_tw_id", unique: true
end
@@ -1775,7 +1838,11 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
t.index ["item_type", "item_id"], name: "index_versions_on_item_type_and_item_id"
end
add_foreign_key "blob_entries", "blob_entries", column: "base_sha256", primary_key: "sha256"
add_foreign_key "domain_e621_post_versions", "domain_e621_posts", column: "item_id"
add_foreign_key "domain_e621_taggings", "domain_e621_posts", column: "post_id"
add_foreign_key "domain_e621_taggings", "domain_e621_tags", column: "tag_id"
add_foreign_key "domain_fa_favs", "domain_fa_posts", column: "post_id"
add_foreign_key "domain_fa_favs", "domain_fa_users", column: "user_id"
add_foreign_key "domain_fa_follows", "domain_fa_users", column: "followed_id"
add_foreign_key "domain_fa_follows", "domain_fa_users", column: "follower_id"
@@ -1795,7 +1862,8 @@ ActiveRecord::Schema[7.0].define(version: 2024_12_20_174922) do
add_foreign_key "domain_inkbunny_pool_joins", "domain_inkbunny_posts", column: "post_id"
add_foreign_key "domain_twitter_medias", "domain_twitter_tweets", column: "tweet_id"
add_foreign_key "domain_twitter_medias", "http_log_entries", column: "file_id"
add_foreign_key "domain_twitter_tweets", "domain_twitter_users", column: "author_id", primary_key: "tw_id", name: "on_author_id"
add_foreign_key "domain_twitter_tweets", "domain_twitter_users", column: "author_id"
add_foreign_key "domain_twitter_user_versions", "domain_twitter_users", column: "item_id"
add_foreign_key "http_log_entries", "http_log_entries", column: "caused_by_id"
add_foreign_key "http_log_entries", "http_log_entry_headers", column: "request_headers_id"
add_foreign_key "http_log_entries", "http_log_entry_headers", column: "response_headers_id"

View File

@@ -13,9 +13,9 @@ describe Domain::E621::Job::PostsIndexJob do
content_type: "text/html",
contents:
SpecUtil.read_fixture_file("domain/e621/job/posts_index_1.json"),
caused_by_entry_idx: nil
}
]
caused_by_entry_idx: nil,
},
],
)
end
@@ -25,46 +25,54 @@ describe Domain::E621::Job::PostsIndexJob do
end
it "updates existing posts" do
Domain::E621::Post.create!(
{ e621_id: 4_247_443, md5: "1c6169aa51668681e9697a48144d7c78" }
)
expect do perform_now({}) end.to change(Domain::E621::Post, :count).by(4)
post = Domain::E621::Post.find_by(e621_id: 4_247_443)
expect(post.file_url_str).to eq(
"https://static1.e621.net/data/1c/61/1c6169aa51668681e9697a48144d7c78.jpg"
)
end
it "fixes tags to reflect reality" do
post =
Domain::E621::Post.create!(
{ e621_id: 4_247_443, md5: "1c6169aa51668681e9697a48144d7c78" }
{
e621_id: 4_247_443,
md5: "1c6169aa51668681e9697a48144d7c78",
tags_array: ["some_tag"],
},
)
tag1 = Domain::E621::Tag.create!(name: "tag1")
tag2 = Domain::E621::Tag.create!(name: "mammal")
post.taggings.create!(tag: tag1, category: "cat_general")
post.taggings.create!(tag: tag2, category: "cat_general")
post.save!
perform_now({})
expect(
SpecUtil.enqueued_jobs(Domain::E621::Job::StaticFileJob).length
).to eq(4)
expect(post.tags_array).to eq(["some_tag"])
expect do perform_now({}) end.to change(Domain::E621::Post, :count).by(4)
post.reload
# removes the tag1 tag
expect(post.tags.map(&:name)).not_to include("tag1")
# keeps tags that are in the json
expect(post.tags.map(&:name)).to include("absurd_res")
expect(post.tags.map(&:name)).to include("mammal")
# changes existing mammal/general tag to mammal/species
expect(
post.taggings.find { |tagging| tagging.tag.name == "mammal" }.category
).to eq("cat_species")
expect(post.file_url_str).to eq(
"https://static1.e621.net/data/1c/61/1c6169aa51668681e9697a48144d7c78.jpg",
)
expect(post.tags_array).to include("alcohol", "beach_ball", "wide_hips")
expect(post.tags_array).not_to include("some_tag")
end
# it "fixes tags to reflect reality" do
# post =
# Domain::E621::Post.create!(
# { e621_id: 4_247_443, md5: "1c6169aa51668681e9697a48144d7c78" },
# )
# tag1 = Domain::E621::Tag.create!(name: "tag1")
# tag2 = Domain::E621::Tag.create!(name: "mammal")
# post.taggings.create!(tag: tag1, category: "general")
# post.taggings.create!(tag: tag2, category: "general")
# post.save!
# perform_now({})
# expect(
# SpecUtil.enqueued_jobs(Domain::E621::Job::StaticFileJob).length,
# ).to eq(4)
# post.reload
# # removes the tag1 tag
# expect(post.tags.map(&:name)).not_to include("tag1")
# # keeps tags that are in the json
# expect(post.tags.map(&:name)).to include("absurd_res")
# expect(post.tags.map(&:name)).to include("mammal")
# # changes existing mammal/general tag to mammal/species
# expect(
# post.taggings.find { |tagging| tagging.tag.name == "mammal" }.category,
# ).to eq("species")
# end
it "updates a post where the md5 has changed" do
file = SpecUtil.create_http_log_entry
post =
@@ -72,21 +80,21 @@ describe Domain::E621::Job::PostsIndexJob do
{
e621_id: 4_247_443,
md5: "0000000051668681e9697a48144d7c78",
file: file
}
file: file,
},
)
perform_now({})
post.reload
expect(post.md5).to eq("1c6169aa51668681e9697a48144d7c78")
expect(post.file).to be_nil
expect(post.state_detail["prev_md5s"]).to eq(
["md5" => "0000000051668681e9697a48144d7c78", "file_id" => file.id]
["md5" => "0000000051668681e9697a48144d7c78", "file_id" => file.id],
)
static_file_jobs =
SpecUtil.enqueued_jobs(Domain::E621::Job::StaticFileJob)
expect(static_file_jobs.length).to eq(5)
expect(static_file_jobs).to match(
including(including(args: [including(post: post)]))
including(including(args: [including(post: post)])),
)
end
end

View File

@@ -0,0 +1,46 @@
require "rails_helper"
describe Domain::E621::Job::ScanPostJob do
let(:http_client_mock) { instance_double("::Scraper::HttpClient") }
let(:post) { SpecUtil.create_e621_post(e621_id: 2_227_914) }
before { Scraper::ClientFactory.http_client_mock = http_client_mock }
it "scans the post" do
caused_by_entry = SpecUtil.create_http_log_entry
mock_log_entries =
SpecUtil.init_http_client_mock(
http_client_mock,
[
{
uri: "https://e621.net/posts/2227914.json",
status_code: 200,
content_type: "application/json; charset=utf-8",
contents:
SpecUtil.read_fixture_file("domain/e621/job/posts_2227914.json"),
caused_by_entry: caused_by_entry,
},
],
)
expect(post.file).to be_nil
described_class.perform_now(
{ post: post, caused_by_entry: caused_by_entry },
)
post.reload
expect(post.file).to be_nil
expect(post.state).to eq("ok")
expect(post.file_url_str).to eq(
"https://static1.e621.net/data/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg",
)
expect(post.md5).to eq("c0fa5293f1d1440c2d3f2c3e027d3c36")
expect(post.tags_array).to include("black_nose", "facial_tuft")
expect(
SpecUtil.enqueued_jobs(Domain::E621::Job::StaticFileJob).length,
).to eq(1)
expect(
SpecUtil.enqueued_jobs(Domain::E621::Job::StaticFileJob).first[:args],
).to eq([{ post: post, caused_by_entry: mock_log_entries[0] }])
end
end

View File

@@ -1,71 +1,71 @@
require "rails_helper"
# require "rails_helper"
describe Domain::E621::CsvPostImporter do
let(:csv_row) do
{
"id" => 12_345,
"md5" => "1c6169aa51668681e9697a48144d7c78",
"updated_at" => "2023-08-24 07:35:09.171905",
"file_ext" => "jpg",
"description" => "a description",
"rating" => "s",
"score" => 67,
"up_score" => 69,
"down_score" => 2,
"fav_count" => 420,
"comment_count" => 1,
"change_seq" => 0,
"parent_id" => nil,
"is_deleted" => "f",
"is_pending" => "t",
"is_flagged" => "f",
"source" => "src1\nsrc2",
"tag_string" => "tag1 tag2"
}
end
# describe Domain::E621::CsvPostImporter do
# let(:csv_row) do
# {
# "id" => 12_345,
# "md5" => "1c6169aa51668681e9697a48144d7c78",
# "updated_at" => "2023-08-24 07:35:09.171905",
# "file_ext" => "jpg",
# "description" => "a description",
# "rating" => "s",
# "score" => 67,
# "up_score" => 69,
# "down_score" => 2,
# "fav_count" => 420,
# "comment_count" => 1,
# "change_seq" => 0,
# "parent_id" => nil,
# "is_deleted" => "f",
# "is_pending" => "t",
# "is_flagged" => "f",
# "source" => "src1\nsrc2",
# "tag_string" => "tag1 tag2",
# }
# end
it "imports new posts" do
expect do described_class.import_row(csv_row) end.to change(
Domain::E621::Post,
:count
).by(1)
post = Domain::E621::Post.find_by(e621_id: csv_row["id"])
expect(SpecUtil.enqueued_jobs(Domain::E621::Job::StaticFileJob)).to match(
[including(args: [{ post: post }])]
)
# it "imports new posts" do
# expect do described_class.import_row(csv_row) end.to change(
# Domain::E621::Post,
# :count,
# ).by(1)
# post = Domain::E621::Post.find_by(e621_id: csv_row["id"])
# expect(SpecUtil.enqueued_jobs(Domain::E621::Job::StaticFileJob)).to match(
# [including(args: [{ post: post }])],
# )
expect(post.md5).to eq(csv_row["md5"])
expect(post.file_url_str).to eq(
"https://static1.e621.net/data/1c/61/1c6169aa51668681e9697a48144d7c78.jpg"
)
expect(post.description).to eq(csv_row["description"])
expect(post.sources_array).to eq(%w[src1 src2])
expect(post.tags_array).to eq(%w[tag1 tag2])
expect(post.tags.map(&:name)).to match(%w[tag1 tag2])
expect(post.taggings.map(&:category).to_set).to eq(["cat_general"].to_set)
expect(post.e621_updated_at).to eq(Time.parse "2023-08-24T07:35:09")
end
# expect(post.md5).to eq(csv_row["md5"])
# expect(post.file_url_str).to eq(
# "https://static1.e621.net/data/1c/61/1c6169aa51668681e9697a48144d7c78.jpg",
# )
# expect(post.description).to eq(csv_row["description"])
# expect(post.sources_array).to eq(%w[src1 src2])
# expect(post.tags_array).to eq(%w[tag1 tag2])
# expect(post.tags.map(&:name)).to match(%w[tag1 tag2])
# expect(post.taggings.map(&:category).to_set).to eq(["general"].to_set)
# expect(post.e621_updated_at).to eq(Time.parse "2023-08-24T07:35:09")
# end
it "does not touch posts updated after the csv" do
post =
Domain::E621::Post.create!(
{
e621_id: csv_row["id"],
md5: csv_row["md5"],
tags_array: %w[tag3 tag4]
}
)
new_time = "2023-08-25T07:35:09-07:00"
post.e621_updated_at = new_time
post.save!
# it "does not touch posts updated after the csv" do
# post =
# Domain::E621::Post.create!(
# {
# e621_id: csv_row["id"],
# md5: csv_row["md5"],
# tags_array: %w[tag3 tag4],
# },
# )
# new_time = "2023-08-25T07:35:09-07:00"
# post.e621_updated_at = new_time
# post.save!
expect do described_class.import_row(csv_row) end.to_not change(
Domain::E621::Post,
:count
)
# expect do described_class.import_row(csv_row) end.to_not change(
# Domain::E621::Post,
# :count,
# )
post.reload
expect(post.e621_updated_at).to eq(Time.parse new_time)
expect(post.tags_array).to eq(%w[tag3 tag4])
end
end
# post.reload
# expect(post.e621_updated_at).to eq(Time.parse new_time)
# expect(post.tags_array).to eq(%w[tag3 tag4])
# end
# end

View File

@@ -23,14 +23,14 @@ class SpecUtil
allow(mock).to receive(:do_request).with(
expected_method,
expected_url,
request_headers
request_headers,
).and_return(
Scraper::CurlHttpPerformer::Response.new(
response_code,
response_headers,
response_time_ms,
response_body
)
response_body,
),
)
mock
end
@@ -75,8 +75,8 @@ class SpecUtil
response:
build_blob_entry(content_type: content_type, contents: contents),
content_type: content_type,
requested_at: Time.now
}
requested_at: Time.now,
},
)
raise entry.errors.full_messages.join(", ") unless entry.valid?
@@ -91,15 +91,15 @@ class SpecUtil
def self.build_blob_entry(content_type: "text/plain", contents: nil)
BlobEntryP.find_or_build(
content_type: content_type,
contents: contents || random_string(1024)
contents: contents || random_string(1024),
)
end
def self.create_http_headers
::HttpLogEntryHeader.find_or_create(
headers: {
test_header_key: "test header value #{random_string(16)}"
}
test_header_key: "test header value #{random_string(16)}",
},
)
end
@@ -112,7 +112,7 @@ class SpecUtil
uri: request[:uri],
contents: request[:contents],
content_type: request[:content_type],
status_code: request[:status_code] || 200
status_code: request[:status_code] || 200,
)
log_entry.save!
log_entries << log_entry
@@ -128,14 +128,14 @@ class SpecUtil
expect(http_client_mock).to(
receive(method).with(
log_entry.uri.to_s,
{ caused_by_entry: caused_by_entry }
{ caused_by_entry: caused_by_entry },
).and_return(
Scraper::HttpClient::Response.new(
log_entry.status_code,
log_entry.response.contents,
log_entry
)
)
log_entry,
),
),
)
end
@@ -157,9 +157,9 @@ class SpecUtil
priority: job.priority,
args:
::ActiveJob::Arguments.deserialize(
job.serialized_params["arguments"]
job.serialized_params["arguments"],
),
good_job: job
good_job: job,
}
end
.filter { |job| job_is_class(job_class, job) }
@@ -203,11 +203,21 @@ class SpecUtil
@last_fa_id += 1
Domain::Fa::Post.new(
creator: creator || build_domain_fa_user,
fa_id: fa_id || @last_fa_id
fa_id: fa_id || @last_fa_id,
)
end
def self.create_domain_fa_post(...)
build_domain_fa_post(...).tap { |model| model.save! }
end
def self.build_e621_post(e621_id: nil, file_url_str: nil, md5: nil)
::Domain::E621::Post.new(
{ e621_id: e621_id || 10, file_url_str: file_url_str, md5: md5 },
)
end
def self.create_e621_post(...)
build_e621_post(...).tap { |model| model.save! }
end
end

View File

@@ -0,0 +1,96 @@
{
"post": {
"id": 2227914,
"created_at": "2020-04-23T13:39:55.847-04:00",
"updated_at": "2024-12-23T07:51:12.693-05:00",
"file": {
"width": 2038,
"height": 1852,
"ext": "jpg",
"size": 130371,
"md5": "c0fa5293f1d1440c2d3f2c3e027d3c36",
"url": "https://static1.e621.net/data/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg"
},
"preview": {
"width": 150,
"height": 136,
"url": "https://static1.e621.net/data/preview/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg"
},
"sample": {
"has": true,
"height": 772,
"width": 850,
"url": "https://static1.e621.net/data/sample/c0/fa/c0fa5293f1d1440c2d3f2c3e027d3c36.jpg",
"alternates": {}
},
"score": { "up": 3566, "down": -56, "total": 3510 },
"tags": {
"general": [
"black_nose",
"blursed_image",
"cheek_tuft",
"dot_eyes",
"facial_tuft",
"feral",
"humor",
"lego_brick",
"male",
"owo",
"pun",
"simple_background",
"smile",
"solo",
"text",
"tuft",
"uwu",
"visual_pun",
"white_background"
],
"artist": ["taga"],
"contributor": [],
"copyright": ["beastars", "lego"],
"character": ["legoshi_(beastars)"],
"species": [
"animate_inanimate",
"canid",
"canine",
"canis",
"mammal",
"wolf"
],
"invalid": [],
"meta": ["2020", "hi_res", "icon", "meme"],
"lore": []
},
"locked_tags": [],
"change_seq": 63272003,
"flags": {
"pending": false,
"flagged": false,
"note_locked": false,
"status_locked": false,
"rating_locked": false,
"deleted": false
},
"rating": "s",
"fav_count": 3782,
"sources": [
"https://twitter.com/TagaArt/status/1253377037718478849",
"https://pbs.twimg.com/media/EWTjxXAXQAMvd8n?format=jpg\u0026name=orig"
],
"pools": [],
"relationships": {
"parent_id": null,
"has_children": true,
"has_active_children": true,
"children": [2274259, 2315595, 2603435]
},
"approver_id": null,
"uploader_id": 55747,
"description": "Im sorry\nIm really really really sorry\n",
"comment_count": 91,
"is_favorited": false,
"has_notes": false,
"duration": null
}
}

View File

@@ -22,8 +22,8 @@ module TestUtil
response:
build_blob_entry(content_type: content_type, contents: contents),
content_type: content_type,
requested_at: Time.now
}
requested_at: Time.now,
},
)
raise entry.errors.full_messages.join(", ") unless entry.valid?
@@ -33,7 +33,7 @@ module TestUtil
def self.build_blob_entry(content_type: "text/plain", contents: nil)
BlobEntryP.find_or_build(
content_type: content_type,
contents: contents || random_string(1024)
contents: contents || random_string(1024),
)
end
@@ -46,8 +46,8 @@ module TestUtil
def self.create_http_headers
::HttpLogEntryHeader.find_or_create(
headers: {
test_header_key: "test header value #{random_string(16)}"
}
test_header_key: "test header value #{random_string(16)}",
},
)
end
@@ -55,7 +55,7 @@ module TestUtil
str = random_string(8)
user =
::Domain::Fa::User.new(
{ name: "Test-User-#{str}", url_name: "test-user-#{str.downcase}" }
{ name: "Test-User-#{str}", url_name: "test-user-#{str.downcase}" },
)
user.valid? || raise(user.errors.full_messages.join(", "))
user
@@ -115,9 +115,9 @@ module TestUtil
response_code,
response_headers,
response_time_ms,
response_body
response_body,
),
[expected_url, request_headers]
[expected_url, request_headers],
)
mock
end