Modify CFP to accept proposals for other things

Add field cfp_type and relevant validations
Add Program#cfp to preserve backwards compatibility
Add 'for_events' scope to the cfp, in order for it to be used like
program.cfps.events
Add useful methods
Add rspec test for the new code
The supported cfp types can be viewed via Cfp::TYPES
This commit is contained in:
AEtherC0r3 2017-05-30 20:54:48 +03:00 committed by Stella Rouzi
parent 7fd738bc7d
commit c3eb178546
8 changed files with 120 additions and 5 deletions

View file

@ -645,6 +645,7 @@ Style/PercentLiteralDelimiters:
- 'app/models/contact.rb'
- 'app/models/registration.rb'
- 'app/models/subscription.rb'
- 'app/models/cfp.rb'
- 'app/uploaders/picture_uploader.rb'
- 'spec/models/ability_spec.rb'
- 'spec/models/program_spec.rb'

View file

@ -2,7 +2,7 @@ module Admin
class CfpsController < Admin::BaseController
load_and_authorize_resource :conference, find_by: :short_title
load_and_authorize_resource :program, through: :conference, singleton: true
load_and_authorize_resource through: :program, singleton: true
load_and_authorize_resource through: :program
def show; end
@ -27,7 +27,6 @@ module Admin
end
def update
@cfp = @program.cfp
@cfp.assign_attributes(cfp_params)
send_mail_on_cfp_dates_updates = @cfp.notify_on_cfp_date_update?

View file

@ -1,6 +1,10 @@
# cannot delete program if there are events submitted
class Cfp < ActiveRecord::Base
TYPES = %w(events).freeze
scope :for_events, (-> { find_by(cfp_type: 'events') })
has_paper_trail ignore: [:updated_at], meta: { conference_id: :conference_id }
belongs_to :program
@ -8,6 +12,15 @@ class Cfp < ActiveRecord::Base
validates :start_date, :end_date, presence: true
validate :before_end_of_conference
validate :start_after_end_date
validates :cfp_type,
presence: true,
inclusion: {
in: TYPES
},
uniqueness: {
scope: :program,
case_sensitive: false
}
##
# Checks whether cfp date is updated
@ -55,6 +68,16 @@ class Cfp < ActiveRecord::Base
result > 0 ? result : 0
end
##
# Checks if the call for papers is currently open
#
# ====Returns
# * +false+ -> If the CFP is not set or today isn't in the CFP period.
# * +true+ -> If today is in the CFP period.
def open?
(start_date..end_date).cover?(Date.current)
end
private
def before_end_of_conference

View file

@ -5,7 +5,7 @@ class Program < ActiveRecord::Base
belongs_to :conference
has_one :cfp, dependent: :destroy
has_many :cfps, dependent: :destroy
has_many :event_types, dependent: :destroy
has_many :tracks, dependent: :destroy
has_many :difficulty_levels, dependent: :destroy
@ -135,7 +135,7 @@ class Program < ActiveRecord::Base
# * +false+ -> If the CFP is not set or today isn't in the CFP period.
# * +true+ -> If today is in the CFP period.
def cfp_open?
cfp = self.cfp
cfp = cfps.events
cfp.present? && (cfp.start_date..cfp.end_date).cover?(Date.current)
end
@ -163,6 +163,23 @@ class Program < ActiveRecord::Base
EventSchedule.where(schedule: selected_schedule).where(start_time: parsed_date..(parsed_date + 1)).any?
end
##
# Provides backwards compatibility for when the program had one cfp
#
# ====Returns
# * +ActiveRecord+ -> The program's cfp with cfp_type == 'events'
def cfp
return nil if cfps.for_events.blank?
cfps.for_events
end
##
# ====Returns
# * +Array+ -> The types of cfps for which a cfp doesn't exist yet
def remaining_cfp_types
Cfp::TYPES - cfps.pluck(:cfp_type)
end
private
##

View file

@ -0,0 +1,15 @@
class AddTypeToCfps < ActiveRecord::Migration
class TmpCfp < ActiveRecord::Base
self.table_name = 'cfps'
end
def change
add_column :cfps, :cfp_type, :string
TmpCfp.reset_column_information
TmpCfp.find_each do |cfp|
cfp.cfp_type = 'events'
cfp.save!
end
end
end

View file

@ -52,6 +52,7 @@ ActiveRecord::Schema.define(version: 20170603095900) do
t.datetime "created_at"
t.datetime "updated_at"
t.integer "program_id"
t.string "cfp_type"
end
create_table "comments", force: :cascade do |t|

View file

@ -1,8 +1,24 @@
require 'spec_helper'
describe Cfp do
subject { create(:cfp) }
let!(:conference) { create(:conference, end_date: Date.today) }
let!(:cfp) { build(:cfp, start_date: Date.today - 2, end_date: Date.today - 1, program_id: conference.program.id) }
let!(:cfp) { create(:cfp, start_date: Date.today - 2, end_date: Date.today - 1, program_id: conference.program.id) }
describe 'scope' do
describe '#for_events' do
it 'returns the cfp for events' do
expect(conference.program.cfps.for_events).to be_a Cfp
expect(conference.program.cfps.for_events.cfp_type).to eq('events')
end
end
end
describe 'validations' do
it { is_expected.to validate_presence_of(:cfp_type) }
it { is_expected.to validate_inclusion_of(:cfp_type).in_array(Cfp::TYPES) }
it { is_expected.to validate_uniqueness_of(:cfp_type).scoped_to(:program_id).case_insensitive }
end
describe '#before_end_of_conference' do
describe 'fails to save cfp' do
@ -97,4 +113,28 @@ describe Cfp do
end
end
end
describe '#open?' do
context 'returns false' do
it 'when start and end dates are in the past' do
cfp.start_date = Date.current - 3
cfp.end_date = Date.current - 1
expect(cfp.open?).to eq(false)
end
it 'when start and end dates are in the future' do
cfp.start_date = Date.current + 1
cfp.end_date = Date.current + 3
expect(cfp.open?).to eq(false)
end
end
context 'returns true' do
it 'when start date is in the past and end date is in the future' do
cfp.start_date = Date.current - 1
cfp.end_date = Date.current + 1
expect(cfp.open?).to eq(true)
end
end
end
end

View file

@ -240,4 +240,23 @@ describe Program do
end
end
describe '#cfp' do
it 'returns the cfp for events' do
create(:cfp, cfp_type: 'events', program: program, end_date: Date.current + 1)
expect(program.cfp).to be_a Cfp
expect(program.cfp.cfp_type).to eq('events')
end
it 'returns nil if the program doesn\'t have a cfp' do
expect(program.cfp).to eq(nil)
end
end
describe '#remaining_cfp_types' do
it 'returns an array with the types for which a cfp doesn\'t exist' do
expect(program.remaining_cfp_types).to eq(Cfp::TYPES)
create(:cfp, cfp_type: 'events', program: program, end_date: Date.current + 1)
expect(program.remaining_cfp_types).to eq([])
end
end
end