Add basic CollectionItem model

This commit is contained in:
David Roetzel 2025-11-19 14:54:10 +01:00
parent 80b3723bb6
commit 827ba9eb08
No known key found for this signature in database
8 changed files with 132 additions and 1 deletions

View File

@ -21,6 +21,8 @@ class Collection < ApplicationRecord
belongs_to :account
belongs_to :tag, optional: true
has_many :collection_items, dependent: :delete_all
validates :name, presence: true
validates :description, presence: true
validates :uri, presence: true, if: :remote?

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
# == Schema Information
#
# Table name: collection_items
#
# id :bigint(8) not null, primary key
# activity_uri :string
# approval_last_verified_at :datetime
# approval_uri :string
# object_uri :string
# position :integer default(1), not null
# state :integer default("pending"), not null
# created_at :datetime not null
# updated_at :datetime not null
# account_id :bigint(8)
# collection_id :bigint(8) not null
#
class CollectionItem < ApplicationRecord
belongs_to :collection
belongs_to :account, optional: true
enum :state,
{ pending: 0, accepted: 1, rejected: 2, revoked: 3 },
validate: true
delegate :local?, :remote?, to: :collection
validates :position, numericality: { only_integer: true, greater_than: 0 }
validates :activity_uri, presence: true, if: :local_item_with_remote_account?
validates :account, presence: true, if: :accepted?
validates :object_uri, presence: true, if: -> { account.nil? }
scope :ordered, -> { order(position: :asc) }
def local_item_with_remote_account?
local? && account&.remote?
end
end

View File

@ -13,6 +13,8 @@ module Account::Associations
has_many :account_warnings
has_many :aliases, class_name: 'AccountAlias'
has_many :bookmarks
has_many :collections
has_many :collection_items
has_many :conversations, class_name: 'AccountConversation'
has_many :custom_filters
has_many :favourites

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class CreateCollectionItems < ActiveRecord::Migration[8.0]
def change
create_table :collection_items do |t|
t.references :collection, null: false, foreign_key: { on_delete: :cascade }
t.references :account, foreign_key: true
t.integer :position, null: false, default: 1
t.string :object_uri, index: { unique: true, where: 'activity_uri IS NOT NULL' }
t.string :approval_uri, index: { unique: true, where: 'approval_uri IS NOT NULL' }
t.string :activity_uri
t.datetime :approval_last_verified_at
t.integer :state, null: false, default: 0
t.timestamps
end
end
end

View File

@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema[8.0].define(version: 2025_11_18_115657) do
ActiveRecord::Schema[8.0].define(version: 2025_11_19_093332) do
# These are extensions that must be enabled in order to support this database
enable_extension "pg_catalog.plpgsql"
@ -351,6 +351,23 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_18_115657) do
t.index ["reference_account_id"], name: "index_canonical_email_blocks_on_reference_account_id"
end
create_table "collection_items", force: :cascade do |t|
t.bigint "collection_id", null: false
t.bigint "account_id"
t.integer "position", default: 1, null: false
t.string "object_uri"
t.string "approval_uri"
t.string "activity_uri"
t.datetime "approval_last_verified_at"
t.integer "state", default: 0, null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["account_id"], name: "index_collection_items_on_account_id"
t.index ["approval_uri"], name: "index_collection_items_on_approval_uri", unique: true, where: "(approval_uri IS NOT NULL)"
t.index ["collection_id"], name: "index_collection_items_on_collection_id"
t.index ["object_uri"], name: "index_collection_items_on_object_uri", unique: true, where: "(activity_uri IS NOT NULL)"
end
create_table "collections", force: :cascade do |t|
t.bigint "account_id", null: false
t.string "name", null: false
@ -1402,6 +1419,8 @@ ActiveRecord::Schema[8.0].define(version: 2025_11_18_115657) do
add_foreign_key "bulk_import_rows", "bulk_imports", on_delete: :cascade
add_foreign_key "bulk_imports", "accounts", on_delete: :cascade
add_foreign_key "canonical_email_blocks", "accounts", column: "reference_account_id", on_delete: :cascade
add_foreign_key "collection_items", "accounts"
add_foreign_key "collection_items", "collections", on_delete: :cascade
add_foreign_key "collections", "accounts"
add_foreign_key "collections", "tags"
add_foreign_key "conversation_mutes", "accounts", name: "fk_225b4212bb", on_delete: :cascade

View File

@ -17,3 +17,7 @@ Fabricator(:account) do
discoverable true
indexable true
end
Fabricator(:remote_account, from: :account) do
domain 'example.com'
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
Fabricator(:collection_item) do
collection { Fabricate.build(:collection) }
account { Fabricate.build(:account) }
position 1
state :accepted
end
Fabricator(:unverified_remote_collection_item, from: :collection_item) do
account nil
object_uri { Fabricate.build(:remote_account).uri }
approval_uri { sequence(:uri) { |i| "https://example.com/authorizations/#{i}" } }
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
require 'rails_helper'
RSpec.describe CollectionItem do
describe 'Validations' do
subject { Fabricate.build(:collection_item) }
it { is_expected.to define_enum_for(:state) }
it { is_expected.to validate_numericality_of(:position).only_integer.is_greater_than(0) }
context 'when account inclusion is accepted' do
subject { Fabricate.build(:collection_item, state: :accepted) }
it { is_expected.to validate_presence_of(:account) }
end
context 'when item is local and account is remote' do
subject { Fabricate.build(:collection_item, account: remote_account) }
let(:remote_account) { Fabricate.build(:remote_account) }
it { is_expected.to validate_presence_of(:activity_uri) }
end
context 'when account is not present' do
subject { Fabricate.build(:unverified_remote_collection_item) }
it { is_expected.to validate_presence_of(:object_uri) }
end
end
end