Skip to content

Commit 65c8e9f

Browse files
authored
Merge pull request #949 from amatsuda/proposal_state_enum
Define Proposal state transitioning methods as Enum events
2 parents 5cdd6fb + 1a687a3 commit 65c8e9f

4 files changed

Lines changed: 77 additions & 67 deletions

File tree

app/controllers/proposals_controller.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,19 @@ def confirm
5050
end
5151

5252
def withdraw
53-
@proposal.withdraw unless @proposal.confirmed?
53+
@proposal.withdraw! unless @proposal.confirmed?
5454
flash[:info] = "As requested, your talk has been removed for consideration."
5555
redirect_to [@proposal.event, @proposal], status: :see_other
5656
end
5757

5858
def decline
59-
@proposal.decline
59+
@proposal.decline!
6060
flash[:info] = "As requested, your talk has been removed for consideration."
6161
redirect_to [@proposal.event, @proposal], status: :see_other
6262
end
6363

6464
def destroy
65-
@proposal.destroy
65+
@proposal.destroy!
6666
flash[:info] = "Your proposal has been deleted."
6767
redirect_to event_proposals_url(@event), status: :see_other
6868
end
@@ -102,7 +102,7 @@ def edit
102102

103103
def update
104104
if params[:confirm]
105-
@proposal.update(confirmed_at: Time.current)
105+
@proposal.update!(confirmed_at: Time.current)
106106
redirect_to [@event, @proposal], flash: {success: 'Thank you for confirming your participation'}
107107
elsif @proposal.speaker_update_and_notify(proposal_params)
108108
redirect_to [@event, @proposal]

app/controllers/staff/proposals_controller.rb

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,16 @@ def update_state
3737
authorize @proposal, :update_state?
3838
end
3939

40-
@proposal.update_state(params[:new_state])
40+
case params[:new_state]
41+
when 'soft_accepted'
42+
@proposal.soft_accept
43+
when 'soft_waitlisted'
44+
@proposal.soft_waitlist
45+
when 'soft_rejected'
46+
@proposal.soft_reject
47+
when 'submitted'
48+
@proposal.finalized? ? @proposal.hard_reset : @proposal.reset
49+
end
4150

4251
respond_to do |format|
4352
format.html { redirect_to event_staff_program_proposals_path(@proposal.event), status: :see_other }

app/models/proposal.rb

Lines changed: 60 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,67 @@ class Proposal < ApplicationRecord
1111
rejected: 'rejected',
1212
withdrawn: 'withdrawn',
1313
not_accepted: 'not accepted'
14-
}, default: :submitted
14+
}, default: :submitted do
15+
event :soft_accept do
16+
transition :submitted => :soft_accepted
17+
end
1518

16-
SOFT_STATES = [:soft_accepted, :soft_waitlisted, :soft_rejected, :submitted].freeze
17-
FINAL_STATES = [:accepted, :waitlisted, :rejected, :withdrawn, :not_accepted].freeze
19+
event :soft_waitlist do
20+
transition :submitted => :soft_waitlisted
21+
end
22+
23+
event :soft_reject do
24+
transition :submitted => :soft_rejected
25+
end
1826

19-
SOFT_TO_FINAL = {
20-
soft_accepted: :accepted,
21-
soft_rejected: :rejected,
22-
soft_waitlisted: :waitlisted,
23-
submitted: :rejected
24-
}.with_indifferent_access.freeze
27+
event :withdraw do
28+
transition all - [:withdrawn] => :withdrawn
29+
30+
after do
31+
reviewers.each do |reviewer|
32+
Notification.create_for(reviewer, proposal: self, message: "Proposal, #{title}, withdrawn")
33+
end
34+
end
35+
end
36+
37+
event :promote do
38+
transition :waitlisted => :accepted
39+
end
2540

26-
BECOMES_PROGRAM_SESSION = [:accepted, :waitlisted].freeze
41+
event :decline do
42+
transition [:accepted, :waitlisted] => :withdrawn
43+
44+
before do
45+
self.confirmed_at = Time.current
46+
end
47+
48+
after do
49+
program_session.update(state: :declined)
50+
end
51+
end
52+
53+
event :finalize do
54+
transition :soft_accepted => :accepted
55+
transition :soft_rejected => :rejected
56+
transition :soft_waitlisted => :waitlisted
57+
transition :submitted => :rejected
58+
59+
after do
60+
ProgramSession.create_from_proposal(self) if becomes_program_session?
61+
end
62+
end
63+
64+
event :reset do
65+
transition [:soft_accepted, :soft_waitlisted, :soft_rejected] => :submitted
66+
end
67+
68+
event :hard_reset do
69+
transition [:accepted, :waitlisted, :rejected] => :submitted
70+
end
71+
end
72+
73+
SOFT_STATES = [:soft_accepted, :soft_waitlisted, :soft_rejected, :submitted].freeze
74+
FINAL_STATES = [:accepted, :waitlisted, :rejected, :withdrawn, :not_accepted].freeze
2775

2876
has_many :public_comments, dependent: :destroy
2977
has_many :internal_comments, dependent: :destroy
@@ -124,46 +172,11 @@ def custom_fields
124172
proposal_data[:custom_fields] || {}
125173
end
126174

127-
def update_state(new_state)
128-
update(state: new_state)
129-
end
130-
131-
def finalize
132-
transaction do
133-
update_state(SOFT_TO_FINAL[state]) if SOFT_TO_FINAL.key?(state)
134-
if becomes_program_session?
135-
ps = ProgramSession.create_from_proposal(self)
136-
ps.persisted?
137-
else
138-
true
139-
end
140-
end
141-
rescue ActiveRecord::RecordInvalid
142-
false
143-
end
144-
145-
def withdraw
146-
withdrawn!
147-
reviewers.each do |reviewer|
148-
Notification.create_for(reviewer, proposal: self,
149-
message: "Proposal, #{title}, withdrawn")
150-
end
151-
end
152-
153175
def confirm
154176
update(confirmed_at: Time.current)
155177
program_session.confirm if program_session.present?
156178
end
157179

158-
def promote
159-
accepted! if waitlisted?
160-
end
161-
162-
def decline
163-
update(state: :withdrawn, confirmed_at: Time.current)
164-
program_session.update(state: :declined)
165-
end
166-
167180
# draft? is an alias for submitted?
168181
def draft?
169182
submitted?
@@ -174,7 +187,7 @@ def finalized?
174187
end
175188

176189
def becomes_program_session?
177-
BECOMES_PROGRAM_SESSION.include?(state.to_sym)
190+
accepted? || waitlisted?
178191
end
179192

180193
def confirmed?
@@ -272,7 +285,7 @@ def changeset_fields
272285
private
273286

274287
def state_must_be_final_for_confirmation
275-
errors.add(:state, "'#{state}' not a confirmable state.") unless FINAL_STATES.include?(state.to_sym)
288+
errors.add(:state, "'#{state}' not a confirmable state.") unless finalized?
276289
end
277290

278291
def abstract_length

spec/models/proposal_spec.rb

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -169,10 +169,10 @@
169169

170170
describe "#finalize" do
171171
it "changes a soft state to a finalized state" do
172-
Proposal::SOFT_TO_FINAL.each do |key, val|
173-
proposal = create(:proposal_with_track, state: key)
172+
{soft_accepted: :accepted, soft_rejected: :rejected, soft_waitlisted: :waitlisted, submitted: :rejected}.each do |from, to|
173+
proposal = create(:proposal_with_track, state: from)
174174
proposal.finalize
175-
expect(proposal.state.to_sym).to eq(val)
175+
expect(proposal.state.to_sym).to eq(to)
176176
end
177177
end
178178

@@ -199,18 +199,6 @@
199199
end
200200
end
201201

202-
describe "#update_state" do
203-
it "updates the state" do
204-
proposal = create(:proposal_with_track, state: :accepted)
205-
proposal.update_state(:waitlisted)
206-
expect(proposal).to be_waitlisted
207-
end
208-
209-
it "rejects invalid states" do
210-
proposal = create(:proposal_with_track, state: :accepted)
211-
expect { proposal.update_state('almonds!') }.to raise_error(ArgumentError)
212-
end
213-
end
214202
end
215203

216204
context "saving tags" do

0 commit comments

Comments
 (0)