diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 8d752446..e7e50f4a 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -565,6 +565,7 @@ Style/PercentLiteralDelimiters: - 'app/models/subscription.rb' - 'app/uploaders/picture_uploader.rb' - 'spec/models/program_spec.rb' + - 'app/models/track.rb' # Offense count: 2 # Configuration parameters: NamePrefix, NamePrefixBlacklist, NameWhitelist. diff --git a/app/models/track.rb b/app/models/track.rb index 2b37d1bb..6228ff02 100644 --- a/app/models/track.rb +++ b/app/models/track.rb @@ -1,4 +1,5 @@ class Track < ActiveRecord::Base + include ActiveRecord::Transitions include RevisionCount resourcify :roles, dependent: :delete_all @@ -18,12 +19,49 @@ class Track < ActiveRecord::Base uniqueness: { scope: :program } - validates :state, presence: true, if: :self_organized? + validates :state, + presence: true, + inclusion: { in: %w(new to_accept accepted confirmed to_reject rejected canceled withdrawn) }, + if: :self_organized? validates :cfp_active, inclusion: { in: [true, false] }, if: :self_organized? before_validation :capitalize_color - after_create :create_organizer_role, if: :self_organized? + state_machine initial: :pending do + state :new + state :to_accept + state :accepted + state :confirmed + state :to_reject + state :rejected + state :canceled + state :withdrawn + + event :restart do + transitions to: :new, from: [:rejected, :withdrawn, :canceled] + end + event :readiness_to_accept do + transitions to: :to_accept, from: [:new] + end + event :accept do + transitions to: :accepted, from: [:new, :to_accept], on_transition: :create_organizer_role + end + event :confirm do + transitions to: :confirmed, from: [:accepted], on_transition: :assign_role_to_submitter + end + event :readiness_to_reject do + transitions to: :to_reject, from: [:new] + end + event :reject do + transitions to: :rejected, from: [:new, :to_reject] + end + event :cancel do + transitions to: :canceled, from: [:to_accept, :to_reject, :accepted, :confirmed], on_transition: :revoke_role_and_cleanup + end + event :withdraw do + transitions to: :withdrawn, from: [:new, :to_accept, :to_reject, :accepted, :confirmed], on_transition: :revoke_role_and_cleanup + end + end def conference program.conference @@ -43,6 +81,30 @@ class Track < ActiveRecord::Base short_name end + def transition_possible?(transition) + self.class.state_machine.events_for(current_state).include?(transition) + end + + # Gives the role of the track_organizer to the submitter + def assign_role_to_submitter + submitter.add_role 'track_organizer', self + end + + # Revokes the track organizer role and removes the track from events that have it set + def revoke_role_and_cleanup + role = Role.find_by(name: 'track_organizer', resource: self) + + if role + role.users.each do |user| + user.remove_role 'track_organizer', self + end + end + + events.each do |event| + event.track = nil + end + end + private def generate_guid diff --git a/spec/features/track_organizer_ability_spec.rb b/spec/features/track_organizer_ability_spec.rb index f79eba05..49e46915 100644 --- a/spec/features/track_organizer_ability_spec.rb +++ b/spec/features/track_organizer_ability_spec.rb @@ -5,10 +5,10 @@ feature 'Has correct abilities' do let(:organization) { create(:organization) } let(:conference) { create(:full_conference, organization: organization) } let(:self_organized_track) { create(:track, :self_organized, program: conference.program) } - let(:role_track_organizer) { Role.find_by(name: 'track_organizer', resource: self_organized_track) } + let(:role_track_organizer) { Role.where(name: 'track_organizer', resource: self_organized_track).first_or_create } let(:user_track_organizer) { create(:user, role_ids: [role_track_organizer.id]) } - context 'when user is info desk' do + context 'when user is track organizer' do before do sign_in user_track_organizer end diff --git a/spec/models/admin_ability_spec.rb b/spec/models/admin_ability_spec.rb index 5398b7d2..16456a19 100644 --- a/spec/models/admin_ability_spec.rb +++ b/spec/models/admin_ability_spec.rb @@ -79,7 +79,7 @@ describe 'User with admin role' do context 'accesses track organizers' do before :each do other_self_organized_track = create(:track, :self_organized) - @other_track_organizer_role = Role.find_by(name: 'track_organizer', resource: other_self_organized_track) + @other_track_organizer_role = Role.where(name: 'track_organizer', resource: other_self_organized_track).first_or_create end it{ should_not be_able_to(:toggle_user, @other_track_organizer_role) } @@ -105,7 +105,7 @@ describe 'User with admin role' do context 'accesses track organizers' do before :each do - @track_organizer_role = Role.find_by(name: 'track_organizer', resource: my_self_organized_track) + @track_organizer_role = Role.where(name: 'track_organizer', resource: my_self_organized_track).first_or_create end if role_name == 'track_organizer' @@ -223,7 +223,7 @@ describe 'User with admin role' do context 'can manage track organizers' do before :each do - @track_organizer_role = Role.find_by(name: 'track_organizer', resource: my_self_organized_track) + @track_organizer_role = Role.where(name: 'track_organizer', resource: my_self_organized_track).first_or_create end it{ should be_able_to(:toggle_user, @track_organizer_role) } @@ -441,7 +441,8 @@ describe 'User with admin role' do end context 'when user has the role track_organizer' do - let(:role) { Role.find_by(name: 'track_organizer', resource: my_self_organized_track) } + + let(:role) { Role.where(name: 'track_organizer', resource: my_self_organized_track).first_or_create } let(:user) { create(:user, role_ids: [role.id]) } let(:new_track) { build(:track, program: my_conference.program) }