Allow only creation of polls with dates that are not in the past
This commit is contained in:
committed by
Javi Martín
parent
05dbae5a3c
commit
855fedc025
@@ -37,6 +37,8 @@ class Poll < ApplicationRecord
|
|||||||
|
|
||||||
validates_translation :name, presence: true
|
validates_translation :name, presence: true
|
||||||
validate :date_range
|
validate :date_range
|
||||||
|
validate :start_date_is_not_past_date, on: :create
|
||||||
|
validate :start_date_change, on: :update
|
||||||
validate :only_one_active, unless: :public?
|
validate :only_one_active, unless: :public?
|
||||||
|
|
||||||
accepts_nested_attributes_for :questions, reject_if: :all_blank, allow_destroy: true
|
accepts_nested_attributes_for :questions, reject_if: :all_blank, allow_destroy: true
|
||||||
@@ -143,6 +145,18 @@ class Poll < ApplicationRecord
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def start_date_is_not_past_date
|
||||||
|
if starts_at.present? && starts_at < Time.current
|
||||||
|
errors.add(:starts_at, I18n.t("errors.messages.past_date"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def start_date_change
|
||||||
|
if will_save_change_to_starts_at? && starts_at < Time.current
|
||||||
|
errors.add(:starts_at, I18n.t("errors.messages.past_date"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def generate_slug?
|
def generate_slug?
|
||||||
slug.nil?
|
slug.nil?
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ en:
|
|||||||
allowed_file_content_types: "content type must be one of %{types}"
|
allowed_file_content_types: "content type must be one of %{types}"
|
||||||
user_not_found: User not found
|
user_not_found: User not found
|
||||||
invalid_date_range: "Invalid date range"
|
invalid_date_range: "Invalid date range"
|
||||||
|
past_date: "Must not be a past date"
|
||||||
form:
|
form:
|
||||||
accept_terms: I agree to the %{policy} and the %{conditions}
|
accept_terms: I agree to the %{policy} and the %{conditions}
|
||||||
accept_terms_title: I agree to the Privacy Policy and the Terms and conditions of use
|
accept_terms_title: I agree to the Privacy Policy and the Terms and conditions of use
|
||||||
|
|||||||
@@ -137,6 +137,7 @@ es:
|
|||||||
allowed_file_content_types: "el tipo de contenido debe ser uno de los siguientes: %{types}"
|
allowed_file_content_types: "el tipo de contenido debe ser uno de los siguientes: %{types}"
|
||||||
user_not_found: Usuario no encontrado
|
user_not_found: Usuario no encontrado
|
||||||
invalid_date_range: "El rango de fechas no es válido"
|
invalid_date_range: "El rango de fechas no es válido"
|
||||||
|
past_date: "No puede ser una fecha pasada"
|
||||||
form:
|
form:
|
||||||
accept_terms: Acepto la %{policy} y las %{conditions}
|
accept_terms: Acepto la %{policy} y las %{conditions}
|
||||||
accept_terms_title: Acepto la Política de privacidad y las Condiciones de uso
|
accept_terms_title: Acepto la Política de privacidad y las Condiciones de uso
|
||||||
|
|||||||
@@ -2,30 +2,38 @@ require_dependency "poll/answer"
|
|||||||
require_dependency "poll/question/answer"
|
require_dependency "poll/question/answer"
|
||||||
|
|
||||||
section "Creating polls" do
|
section "Creating polls" do
|
||||||
Poll.create!(name: I18n.t("seeds.polls.current_poll"),
|
def create_poll!(attributes)
|
||||||
|
poll = Poll.create!(attributes.merge(starts_at: 1.day.from_now, ends_at: 2.days.from_now))
|
||||||
|
poll.update_columns(
|
||||||
|
starts_at: attributes[:starts_at].beginning_of_minute,
|
||||||
|
ends_at: attributes[:ends_at].beginning_of_minute
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
create_poll!(name: I18n.t("seeds.polls.current_poll"),
|
||||||
slug: I18n.t("seeds.polls.current_poll").parameterize,
|
slug: I18n.t("seeds.polls.current_poll").parameterize,
|
||||||
starts_at: 7.days.ago,
|
starts_at: 7.days.ago,
|
||||||
ends_at: 7.days.from_now,
|
ends_at: 7.days.from_now,
|
||||||
geozone_restricted: false)
|
geozone_restricted: false)
|
||||||
|
|
||||||
Poll.create!(name: I18n.t("seeds.polls.current_poll_geozone_restricted"),
|
create_poll!(name: I18n.t("seeds.polls.current_poll_geozone_restricted"),
|
||||||
slug: I18n.t("seeds.polls.current_poll_geozone_restricted").parameterize,
|
slug: I18n.t("seeds.polls.current_poll_geozone_restricted").parameterize,
|
||||||
starts_at: 5.days.ago,
|
starts_at: 5.days.ago,
|
||||||
ends_at: 5.days.from_now,
|
ends_at: 5.days.from_now,
|
||||||
geozone_restricted: true,
|
geozone_restricted: true,
|
||||||
geozones: Geozone.sample(3))
|
geozones: Geozone.sample(3))
|
||||||
|
|
||||||
Poll.create!(name: I18n.t("seeds.polls.recounting_poll"),
|
create_poll!(name: I18n.t("seeds.polls.recounting_poll"),
|
||||||
slug: I18n.t("seeds.polls.recounting_poll").parameterize,
|
slug: I18n.t("seeds.polls.recounting_poll").parameterize,
|
||||||
starts_at: 15.days.ago,
|
starts_at: 15.days.ago,
|
||||||
ends_at: 2.days.ago)
|
ends_at: 2.days.ago)
|
||||||
|
|
||||||
Poll.create!(name: I18n.t("seeds.polls.expired_poll_without_stats"),
|
create_poll!(name: I18n.t("seeds.polls.expired_poll_without_stats"),
|
||||||
slug: I18n.t("seeds.polls.expired_poll_without_stats").parameterize,
|
slug: I18n.t("seeds.polls.expired_poll_without_stats").parameterize,
|
||||||
starts_at: 2.months.ago,
|
starts_at: 2.months.ago,
|
||||||
ends_at: 1.month.ago)
|
ends_at: 1.month.ago)
|
||||||
|
|
||||||
Poll.create!(name: I18n.t("seeds.polls.expired_poll_with_stats"),
|
create_poll!(name: I18n.t("seeds.polls.expired_poll_with_stats"),
|
||||||
slug: I18n.t("seeds.polls.expired_poll_with_stats").parameterize,
|
slug: I18n.t("seeds.polls.expired_poll_with_stats").parameterize,
|
||||||
starts_at: 2.months.ago,
|
starts_at: 2.months.ago,
|
||||||
ends_at: 1.month.ago,
|
ends_at: 1.month.ago,
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ FactoryBot.define do
|
|||||||
|
|
||||||
starts_at { 1.month.ago }
|
starts_at { 1.month.ago }
|
||||||
ends_at { 1.month.from_now }
|
ends_at { 1.month.from_now }
|
||||||
|
to_create { |poll| poll.save(validate: false) }
|
||||||
|
|
||||||
trait :expired do
|
trait :expired do
|
||||||
starts_at { 1.month.ago }
|
starts_at { 1.month.ago }
|
||||||
@@ -17,6 +18,10 @@ FactoryBot.define do
|
|||||||
ends_at { 2.months.ago }
|
ends_at { 2.months.ago }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :future do
|
||||||
|
starts_at { 1.day.from_now }
|
||||||
|
end
|
||||||
|
|
||||||
trait :published do
|
trait :published do
|
||||||
published { true }
|
published { true }
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
require "rails_helper"
|
require "rails_helper"
|
||||||
|
|
||||||
describe Poll do
|
describe Poll do
|
||||||
let(:poll) { build(:poll) }
|
let(:poll) { build(:poll, :future) }
|
||||||
|
|
||||||
describe "Concerns" do
|
describe "Concerns" do
|
||||||
it_behaves_like "notifiable"
|
it_behaves_like "notifiable"
|
||||||
@@ -22,7 +22,9 @@ describe Poll do
|
|||||||
|
|
||||||
it "is not valid without a start date" do
|
it "is not valid without a start date" do
|
||||||
poll.starts_at = nil
|
poll.starts_at = nil
|
||||||
|
|
||||||
expect(poll).not_to be_valid
|
expect(poll).not_to be_valid
|
||||||
|
expect(poll.errors[:starts_at]).to eq ["Invalid date range"]
|
||||||
end
|
end
|
||||||
|
|
||||||
it "is not valid without an end date" do
|
it "is not valid without an end date" do
|
||||||
@@ -35,11 +37,37 @@ describe Poll do
|
|||||||
poll.ends_at = 2.months.ago
|
poll.ends_at = 2.months.ago
|
||||||
expect(poll).not_to be_valid
|
expect(poll).not_to be_valid
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "is valid if start date is greater than current time" do
|
||||||
|
poll.starts_at = 1.minute.from_now
|
||||||
|
expect(poll).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid if start date is a past date" do
|
||||||
|
poll.starts_at = 1.minute.ago
|
||||||
|
|
||||||
|
expect(poll).not_to be_valid
|
||||||
|
expect(poll.errors[:starts_at]).to eq ["Must not be a past date"]
|
||||||
|
end
|
||||||
|
|
||||||
|
context "persisted poll" do
|
||||||
|
let(:poll) { create(:poll, :future) }
|
||||||
|
|
||||||
|
it "is valid if the start date changes to a future date" do
|
||||||
|
poll.starts_at = 1.minute.from_now
|
||||||
|
expect(poll).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid if the start date changes to a past date" do
|
||||||
|
poll.starts_at = 1.minute.ago
|
||||||
|
expect(poll).not_to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "proposal polls specific validations" do
|
describe "proposal polls specific validations" do
|
||||||
let(:proposal) { create(:proposal) }
|
let(:proposal) { create(:proposal) }
|
||||||
let(:poll) { build(:poll, related: proposal) }
|
let(:poll) { build(:poll, :future, related: proposal) }
|
||||||
|
|
||||||
it "is valid when overlapping but different proposals" do
|
it "is valid when overlapping but different proposals" do
|
||||||
other_proposal = create(:proposal)
|
other_proposal = create(:proposal)
|
||||||
|
|||||||
Reference in New Issue
Block a user