#66 検索時のフォロー中アカウント一覧作成処理を改善
This commit is contained in:
parent
583f5fe906
commit
22d1f52597
7 changed files with 90 additions and 5 deletions
|
@ -199,10 +199,7 @@ class SearchQueryTransformer < Parslet::Transform
|
||||||
def following_account_ids
|
def following_account_ids
|
||||||
return @following_account_ids if defined?(@following_account_ids)
|
return @following_account_ids if defined?(@following_account_ids)
|
||||||
|
|
||||||
account_exists_sql = Account.where('accounts.id = follows.target_account_id').where(searchability: %w(public public_unlisted private)).reorder(nil).select(1).to_sql
|
@following_account_ids = @options[:current_account].following.includes(:account_stat).where(account_stat: { searchable_by_follower: true }).select(:id).pluck(:id)
|
||||||
status_exists_sql = Status.where('statuses.account_id = follows.target_account_id').where(reblog_of_id: nil).where(searchability: %w(public public_unlisted private)).reorder(nil).select(1).to_sql
|
|
||||||
following_accounts = Follow.where(account_id: @options[:current_account].id).merge(Account.where("EXISTS (#{account_exists_sql})").or(Account.where("EXISTS (#{status_exists_sql})")))
|
|
||||||
@following_account_ids = following_accounts.pluck(:target_account_id)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
# updated_at :datetime not null
|
# updated_at :datetime not null
|
||||||
# last_status_at :datetime
|
# last_status_at :datetime
|
||||||
# group_activitypub_count :integer
|
# group_activitypub_count :integer
|
||||||
|
# searchable_by_follower :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class AccountStat < ApplicationRecord
|
class AccountStat < ApplicationRecord
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
# hidden_anonymous :boolean default(FALSE), not null
|
# hidden_anonymous :boolean default(FALSE), not null
|
||||||
# detect_invalid_subscription :boolean default(FALSE), not null
|
# detect_invalid_subscription :boolean default(FALSE), not null
|
||||||
# reject_reply_exclude_followers :boolean default(FALSE), not null
|
# reject_reply_exclude_followers :boolean default(FALSE), not null
|
||||||
|
# reject_friend :boolean default(FALSE), not null
|
||||||
#
|
#
|
||||||
|
|
||||||
class DomainBlock < ApplicationRecord
|
class DomainBlock < ApplicationRecord
|
||||||
|
|
|
@ -157,6 +157,9 @@ class Status < ApplicationRecord
|
||||||
after_create_commit :store_uri, if: :local?
|
after_create_commit :store_uri, if: :local?
|
||||||
after_create_commit :update_statistics, if: :local?
|
after_create_commit :update_statistics, if: :local?
|
||||||
|
|
||||||
|
after_create_commit :set_searchable_follow_on_create
|
||||||
|
after_destroy_commit :set_searchable_follow_on_destroy
|
||||||
|
|
||||||
before_validation :prepare_contents, if: :local?
|
before_validation :prepare_contents, if: :local?
|
||||||
before_validation :set_reblog
|
before_validation :set_reblog
|
||||||
before_validation :set_visibility
|
before_validation :set_visibility
|
||||||
|
@ -670,6 +673,21 @@ class Status < ApplicationRecord
|
||||||
ActivityTracker.increment('activity:statuses:local')
|
ActivityTracker.increment('activity:statuses:local')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def set_searchable_follow_on_create
|
||||||
|
return unless public_searchability? || public_unlisted_searchability? || private_searchability?
|
||||||
|
return if account.account_stat.nil? || account.account_stat.searchable_by_follower
|
||||||
|
|
||||||
|
account.account_stat.update(searchable_by_follower: true)
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_searchable_follow_on_destroy
|
||||||
|
return unless public_searchability? || public_unlisted_searchability? || private_searchability?
|
||||||
|
return if account.account_stat.nil? || !account.account_stat.searchable_by_follower
|
||||||
|
return if account.statuses.exists?(searchability: %i(public public_unlisted unlisted private))
|
||||||
|
|
||||||
|
account.account_stat.update(searchable_by_follower: false)
|
||||||
|
end
|
||||||
|
|
||||||
def increment_counter_caches
|
def increment_counter_caches
|
||||||
return if direct_visibility?
|
return if direct_visibility?
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
require Rails.root.join('lib', 'mastodon', 'migration_helpers')
|
||||||
|
|
||||||
|
class AddSearchableFollowToAccountStats < ActiveRecord::Migration[7.0]
|
||||||
|
include Mastodon::MigrationHelpers
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
class AccountStat < ApplicationRecord; end
|
||||||
|
|
||||||
|
def change
|
||||||
|
safety_assured do
|
||||||
|
add_column_with_default :account_stats, :searchable_by_follower, :boolean, default: false, allow_null: false
|
||||||
|
|
||||||
|
AccountStat.where('EXISTS (SELECT 1 FROM statuses WHERE searchability IN (0, 10, 1) AND account_id = account_stats.account_id)')
|
||||||
|
.update_all(searchable_by_follower: true) # rubocop:disable Rails/SkipsModelValidations
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
21
db/schema.rb
21
db/schema.rb
|
@ -10,7 +10,7 @@
|
||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema[7.0].define(version: 2023_10_01_050733) do
|
ActiveRecord::Schema[7.0].define(version: 2023_10_07_090807) do
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_01_050733) do
|
||||||
t.datetime "updated_at", precision: nil, null: false
|
t.datetime "updated_at", precision: nil, null: false
|
||||||
t.datetime "last_status_at", precision: nil
|
t.datetime "last_status_at", precision: nil
|
||||||
t.integer "group_activitypub_count"
|
t.integer "group_activitypub_count"
|
||||||
|
t.boolean "searchable_by_follower", default: false, null: false
|
||||||
t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true
|
t.index ["account_id"], name: "index_account_stats_on_account_id", unique: true
|
||||||
t.index ["last_status_at", "account_id"], name: "index_account_stats_on_last_status_at_and_account_id", order: { last_status_at: "DESC NULLS LAST" }
|
t.index ["last_status_at", "account_id"], name: "index_account_stats_on_last_status_at_and_account_id", order: { last_status_at: "DESC NULLS LAST" }
|
||||||
end
|
end
|
||||||
|
@ -584,6 +585,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_01_050733) do
|
||||||
t.boolean "hidden_anonymous", default: false, null: false
|
t.boolean "hidden_anonymous", default: false, null: false
|
||||||
t.boolean "detect_invalid_subscription", default: false, null: false
|
t.boolean "detect_invalid_subscription", default: false, null: false
|
||||||
t.boolean "reject_reply_exclude_followers", default: false, null: false
|
t.boolean "reject_reply_exclude_followers", default: false, null: false
|
||||||
|
t.boolean "reject_friend", default: false, null: false
|
||||||
t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true
|
t.index ["domain"], name: "index_domain_blocks_on_domain", unique: true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -676,6 +678,23 @@ ActiveRecord::Schema[7.0].define(version: 2023_10_01_050733) do
|
||||||
t.index ["target_account_id"], name: "index_follows_on_target_account_id"
|
t.index ["target_account_id"], name: "index_follows_on_target_account_id"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "friend_domains", force: :cascade do |t|
|
||||||
|
t.string "domain", default: "", null: false
|
||||||
|
t.string "inbox_url", default: "", null: false
|
||||||
|
t.integer "active_state", default: 0, null: false
|
||||||
|
t.integer "passive_state", default: 0, null: false
|
||||||
|
t.string "active_follow_activity_id"
|
||||||
|
t.string "passive_follow_activity_id"
|
||||||
|
t.boolean "available", default: true, null: false
|
||||||
|
t.boolean "public_unlisted", default: true, null: false
|
||||||
|
t.boolean "pseudo_relay", default: false, null: false
|
||||||
|
t.boolean "unlocked", default: false, null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["domain"], name: "index_friend_domains_on_domain", unique: true
|
||||||
|
t.index ["inbox_url"], name: "index_friend_domains_on_inbox_url", unique: true
|
||||||
|
end
|
||||||
|
|
||||||
create_table "identities", force: :cascade do |t|
|
create_table "identities", force: :cascade do |t|
|
||||||
t.string "provider", default: "", null: false
|
t.string "provider", default: "", null: false
|
||||||
t.string "uid", default: "", null: false
|
t.string "uid", default: "", null: false
|
||||||
|
|
|
@ -571,5 +571,34 @@ RSpec.describe Status do
|
||||||
status.reload
|
status.reload
|
||||||
expect(status.uri).to start_with('https://')
|
expect(status.uri).to start_with('https://')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'saves as searchable by followers' do
|
||||||
|
status = described_class.create(account: alice, text: 'foo', searchability: :public)
|
||||||
|
expect(status.account.account_stat.searchable_by_follower).to be true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe 'after destroy' do
|
||||||
|
it 'saves as not searchable by followers' do
|
||||||
|
status = described_class.create(account: alice, text: 'foo', searchability: :public)
|
||||||
|
status.destroy
|
||||||
|
expect(status.account.account_stat.searchable_by_follower).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'on multiple posts' do
|
||||||
|
status1 = described_class.create(account: alice, text: 'foo', searchability: :public)
|
||||||
|
status2 = described_class.create(account: alice, text: 'foo', searchability: :public)
|
||||||
|
status3 = described_class.create(account: alice, text: 'foo', searchability: :public)
|
||||||
|
status4 = described_class.create(account: alice, text: 'foo', searchability: :public)
|
||||||
|
status5 = described_class.create(account: alice, text: 'foo', searchability: :public)
|
||||||
|
status1.destroy
|
||||||
|
status2.destroy
|
||||||
|
status3.destroy
|
||||||
|
expect(alice.account_stat.searchable_by_follower).to be true
|
||||||
|
status4.destroy
|
||||||
|
expect(alice.account_stat.searchable_by_follower).to be true
|
||||||
|
status5.destroy
|
||||||
|
expect(alice.account_stat.searchable_by_follower).to be false
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue