Add circle editor

This commit is contained in:
KMY 2023-08-21 16:37:35 +09:00
parent c97e63bb18
commit b0854b1dd8
33 changed files with 1671 additions and 31 deletions

29
app/models/circle.rb Normal file
View file

@ -0,0 +1,29 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: circles
#
# id :bigint(8) not null, primary key
# account_id :bigint(8) not null
# title :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
#
class Circle < ApplicationRecord
include Paginable
PER_ACCOUNT_LIMIT = 100
belongs_to :account
has_many :circle_accounts, inverse_of: :circle, dependent: :destroy
has_many :accounts, through: :circle_accounts
validates :title, presence: true
validates_each :account_id, on: :create do |record, _attr, value|
record.errors.add(:base, I18n.t('lists.errors.limit')) if List.where(account_id: value).count >= PER_ACCOUNT_LIMIT
end
end

View file

@ -0,0 +1,39 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: circle_accounts
#
# id :bigint(8) not null, primary key
# circle_id :bigint(8)
# account_id :bigint(8) not null
# follow_id :bigint(8) not null
# created_at :datetime not null
# updated_at :datetime not null
#
class CircleAccount < ApplicationRecord
belongs_to :circle
belongs_to :account
belongs_to :follow
validates :account_id, uniqueness: { scope: :circle_id }
validate :validate_relationship
before_validation :set_follow
private
def set_follow
return if circle.account_id == account.id
self.follow = Follow.find_by!(account_id: account.id, target_account_id: circle.account_id)
end
def validate_relationship
return if circle.account_id == account_id
errors.add(:account_id, 'follow relationship missing') if follow_id.nil?
errors.add(:follow, 'mismatched accounts') if follow_id.present? && follow.account_id != account_id
end
end

View file

@ -87,6 +87,29 @@ module AccountSearch
LIMIT :limit OFFSET :offset
SQL
ADVANCED_SEARCH_WITH_FOLLOWED = <<~SQL.squish
WITH first_degree AS (
SELECT account_id
FROM follows
WHERE target_account_id = :id
UNION ALL
SELECT :id
)
SELECT
accounts.*,
(count(f.id) + 1) * #{BOOST} * ts_rank_cd(#{TEXT_SEARCH_RANKS}, to_tsquery('simple', :tsquery), 32) AS rank
FROM accounts
LEFT OUTER JOIN follows AS f ON (accounts.id = f.target_account_id AND f.account_id = :id)
LEFT JOIN account_stats AS s ON accounts.id = s.account_id
WHERE accounts.id IN (SELECT * FROM first_degree)
AND to_tsquery('simple', :tsquery) @@ #{TEXT_SEARCH_RANKS}
AND accounts.suspended_at IS NULL
AND accounts.moved_to_account_id IS NULL
GROUP BY accounts.id, s.id
ORDER BY rank DESC
LIMIT :limit OFFSET :offset
SQL
ADVANCED_SEARCH_WITHOUT_FOLLOWING = <<~SQL.squish
SELECT
accounts.*,
@ -126,9 +149,13 @@ module AccountSearch
end
end
def advanced_search_for(terms, account, limit: 10, following: false, offset: 0)
def advanced_search_for(terms, account, limit: 10, following: false, follower: false, offset: 0)
tsquery = generate_query_for_search(terms)
sql_template = following ? ADVANCED_SEARCH_WITH_FOLLOWING : ADVANCED_SEARCH_WITHOUT_FOLLOWING
sql_template = if following
ADVANCED_SEARCH_WITH_FOLLOWING
else
follower ? ADVANCED_SEARCH_WITH_FOLLOWED : ADVANCED_SEARCH_WITHOUT_FOLLOWING
end
find_by_sql([sql_template, { id: account.id, limit: limit, offset: offset, tsquery: tsquery }]).tap do |records|
ActiveRecord::Associations::Preloader.new(records: records, associations: :account_stat)