* add party_shares table and model with associations * add party share errors and blueprint * add party shares controller and routes * include shared parties in listings and show * add party share factory and model specs * add party shares controller specs * include shares in party response for owners * add crew shared_parties endpoint
63 lines
1.9 KiB
Ruby
63 lines
1.9 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
##
|
|
# PartyShare represents a sharing relationship between a party and a group (e.g., a crew).
|
|
# It allows party owners to share their parties with specific groups, granting view access
|
|
# to members of those groups without changing the party's base visibility.
|
|
#
|
|
# @!attribute [rw] party
|
|
# @return [Party] the party being shared.
|
|
# @!attribute [rw] shareable
|
|
# @return [Crew] the polymorphic group the party is shared with.
|
|
# @!attribute [rw] shared_by
|
|
# @return [User] the user who created this share.
|
|
class PartyShare < ApplicationRecord
|
|
# Associations
|
|
belongs_to :party
|
|
belongs_to :shareable, polymorphic: true
|
|
belongs_to :shared_by, class_name: 'User'
|
|
|
|
# Validations
|
|
validates :party_id, uniqueness: {
|
|
scope: [:shareable_type, :shareable_id],
|
|
message: 'has already been shared with this group'
|
|
}
|
|
validate :owner_can_share
|
|
validate :sharer_is_member_of_shareable
|
|
|
|
# Scopes
|
|
scope :for_crew, ->(crew) { where(shareable_type: 'Crew', shareable_id: crew.id) }
|
|
scope :for_crews, ->(crew_ids) { where(shareable_type: 'Crew', shareable_id: crew_ids) }
|
|
scope :for_party, ->(party) { where(party_id: party.id) }
|
|
|
|
##
|
|
# Returns the blueprint class for serialization.
|
|
#
|
|
# @return [Class] the PartyShareBlueprint class.
|
|
def blueprint
|
|
PartyShareBlueprint
|
|
end
|
|
|
|
private
|
|
|
|
##
|
|
# Validates that only the party owner can share the party.
|
|
#
|
|
# @return [void]
|
|
def owner_can_share
|
|
return if party&.user_id == shared_by_id
|
|
|
|
errors.add(:shared_by, 'must be the party owner')
|
|
end
|
|
|
|
##
|
|
# Validates that the sharer is a member of the group they're sharing to.
|
|
#
|
|
# @return [void]
|
|
def sharer_is_member_of_shareable
|
|
return unless shareable_type == 'Crew'
|
|
return if shareable&.active_memberships&.exists?(user_id: shared_by_id)
|
|
|
|
errors.add(:shareable, 'you must be a member of this crew')
|
|
end
|
|
end
|