From a24bbc105aef54d6dbbcda4eae5a8df4b49c374d Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 23 Dec 2025 11:43:09 +0900 Subject: [PATCH 1/5] Inline Invitable module in Invitation model because the module is used only there --- app/models/concerns/invitable.rb | 47 -------------------------------- app/models/invitation.rb | 38 +++++++++++++++++++++++++- 2 files changed, 37 insertions(+), 48 deletions(-) delete mode 100644 app/models/concerns/invitable.rb diff --git a/app/models/concerns/invitable.rb b/app/models/concerns/invitable.rb deleted file mode 100644 index 7b3a4a3c7..000000000 --- a/app/models/concerns/invitable.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -module Invitable - extend ActiveSupport::Concern - - included do - module State - unless const_defined?(:DECLINED) - DECLINED = 'declined' - PENDING = 'pending' - ACCEPTED = 'accepted' - end - end - - scope :pending, -> { where(state: State::PENDING) } - scope :declined, -> { where(state: State::DECLINED) } - scope :not_accepted, -> { where(state: [State::DECLINED, State::PENDING]) } - - before_create :set_default_state - before_create :set_slug - - validates :email, presence: true - validates_format_of :email, with: /@/ - end - - def decline - update(state: State::DECLINED) - end - - def pending? - state == State::PENDING - end - - def declined? - state == State::DECLINED - end - - private - - def set_slug - self.slug = Digest::SHA1.hexdigest([email, rand(1000)].map(&:to_s).join('-'))[0, 10] - end - - def set_default_state - self.state = State::PENDING if state.nil? - end -end diff --git a/app/models/invitation.rb b/app/models/invitation.rb index 49d763a3c..e20e9c478 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -1,9 +1,23 @@ class Invitation < ApplicationRecord - include Invitable + module State + DECLINED = 'declined' + PENDING = 'pending' + ACCEPTED = 'accepted' + end belongs_to :proposal belongs_to :user, optional: true + scope :pending, -> { where(state: State::PENDING) } + scope :declined, -> { where(state: State::DECLINED) } + scope :not_accepted, -> { where(state: [State::DECLINED, State::PENDING]) } + + before_create :set_default_state + before_create :set_slug + + validates :email, presence: true + validates_format_of :email, with: /@/ + def accept(user) transaction do self.user = user @@ -12,6 +26,28 @@ def accept(user) save end end + + def decline + update(state: State::DECLINED) + end + + def pending? + state == State::PENDING + end + + def declined? + state == State::DECLINED + end + + private + + def set_slug + self.slug = Digest::SHA1.hexdigest([email, rand(1000)].map(&:to_s).join('-'))[0, 10] + end + + def set_default_state + self.state = State::PENDING if state.nil? + end end # == Schema Information From 8518f19ea8cf36f005eb043cf16d56d58fab4bfe Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 23 Dec 2025 11:48:02 +0900 Subject: [PATCH 2/5] Define Invitation#state enum --- app/models/invitation.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/models/invitation.rb b/app/models/invitation.rb index e20e9c478..fedd26c0e 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -4,6 +4,7 @@ module State PENDING = 'pending' ACCEPTED = 'accepted' end + enum :state, {pending: 'pending', accepted: 'accepted', declined: 'declined'} belongs_to :proposal belongs_to :user, optional: true From ceefcc6b3a78e057bce6be2b5ca7ec2f2c1ecf2a Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 23 Dec 2025 11:49:48 +0900 Subject: [PATCH 3/5] Access Invitation#state with labels --- app/models/invitation.rb | 8 ++++---- spec/models/invitation_spec.rb | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/models/invitation.rb b/app/models/invitation.rb index fedd26c0e..dfd90b15e 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -11,7 +11,7 @@ module State scope :pending, -> { where(state: State::PENDING) } scope :declined, -> { where(state: State::DECLINED) } - scope :not_accepted, -> { where(state: [State::DECLINED, State::PENDING]) } + scope :not_accepted, -> { where(state: [:pending, :declined]) } before_create :set_default_state before_create :set_slug @@ -22,14 +22,14 @@ module State def accept(user) transaction do self.user = user - self.state = State::ACCEPTED + self.state = :accepted proposal.speakers.create(user: user, event: proposal.event, skip_name_email_validation: true) save end end def decline - update(state: State::DECLINED) + update(state: :declined) end def pending? @@ -47,7 +47,7 @@ def set_slug end def set_default_state - self.state = State::PENDING if state.nil? + self.state = :pending if state.nil? end end diff --git a/spec/models/invitation_spec.rb b/spec/models/invitation_spec.rb index ddefd9c29..04e049515 100644 --- a/spec/models/invitation_spec.rb +++ b/spec/models/invitation_spec.rb @@ -42,24 +42,24 @@ describe "#pending?" do it "returns true if invitation is pending" do - invitation = create(:invitation, state: Invitation::State::PENDING, proposal: proposal, user: user) + invitation = create(:invitation, state: :pending, proposal: proposal, user: user) expect(invitation).to be_pending end it "returns false if invitation is not pending" do - invitation = create(:invitation, state: Invitation::State::ACCEPTED, proposal: proposal, user: user) + invitation = create(:invitation, state: :accepted, proposal: proposal, user: user) expect(invitation).to_not be_pending end end describe "#declined?" do it "returns true if invitation was declined" do - invitation = create(:invitation, state: Invitation::State::DECLINED, proposal: proposal, user: user) + invitation = create(:invitation, state: :declined, proposal: proposal, user: user) expect(invitation).to be_declined end it "returns false if invitation was not declined" do - invitation = create(:invitation, state: Invitation::State::ACCEPTED, proposal: proposal, user: user) + invitation = create(:invitation, state: :accepted, proposal: proposal, user: user) expect(invitation).to_not be_declined end end From 0b58b08f919a4abd1440be4cd3a63a6ee5a0d447 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 23 Dec 2025 11:56:13 +0900 Subject: [PATCH 4/5] AR Enum defines them --- app/decorators/invitation_decorator.rb | 6 +++--- app/models/invitation.rb | 10 ---------- spec/models/invitation_spec.rb | 4 ++-- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/app/decorators/invitation_decorator.rb b/app/decorators/invitation_decorator.rb index e2b3f177a..0066ff9d3 100644 --- a/app/decorators/invitation_decorator.rb +++ b/app/decorators/invitation_decorator.rb @@ -3,9 +3,9 @@ class InvitationDecorator < Draper::Decorator decorates_association :proposal STATE_LABEL_MAP = { - Invitation::State::PENDING => 'label-default', - Invitation::State::DECLINED => 'label-danger', - Invitation::State::ACCEPTED => 'label-success' + Invitation.states[:pending] => 'label-default', + Invitation.states[:declined] => 'label-danger', + Invitation.states[:accepted] => 'label-success' } def decline_button(small: false) diff --git a/app/models/invitation.rb b/app/models/invitation.rb index dfd90b15e..a5102e5bf 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -9,8 +9,6 @@ module State belongs_to :proposal belongs_to :user, optional: true - scope :pending, -> { where(state: State::PENDING) } - scope :declined, -> { where(state: State::DECLINED) } scope :not_accepted, -> { where(state: [:pending, :declined]) } before_create :set_default_state @@ -32,14 +30,6 @@ def decline update(state: :declined) end - def pending? - state == State::PENDING - end - - def declined? - state == State::DECLINED - end - private def set_slug diff --git a/spec/models/invitation_spec.rb b/spec/models/invitation_spec.rb index 04e049515..e979a0f90 100644 --- a/spec/models/invitation_spec.rb +++ b/spec/models/invitation_spec.rb @@ -19,14 +19,14 @@ it "sets state as declined" do invitation = create(:invitation, state: nil, proposal: proposal, user: user) invitation.decline - expect(invitation.state).to eq(Invitation::State::DECLINED) + expect(invitation).to be_declined end end describe "#accept" do it "sets state as accepted" do invitation.accept(user) - expect(invitation.state).to eq(Invitation::State::ACCEPTED) + expect(invitation).to be_accepted end it "sets the user on the invitation" do From 0d5cccabbd407765085928649ada6ecc191f7d25 Mon Sep 17 00:00:00 2001 From: Akira Matsuda Date: Tue, 23 Dec 2025 11:57:48 +0900 Subject: [PATCH 5/5] Unused constants and module --- app/models/invitation.rb | 5 ----- 1 file changed, 5 deletions(-) diff --git a/app/models/invitation.rb b/app/models/invitation.rb index a5102e5bf..995616faf 100644 --- a/app/models/invitation.rb +++ b/app/models/invitation.rb @@ -1,9 +1,4 @@ class Invitation < ApplicationRecord - module State - DECLINED = 'declined' - PENDING = 'pending' - ACCEPTED = 'accepted' - end enum :state, {pending: 'pending', accepted: 'accepted', declined: 'declined'} belongs_to :proposal