Add lambda to the validations that use model constants

In this way when we need modify the constants model value in the
model/custom folder, adding lambda it will be possible load the new
values.
This commit is contained in:
taitus
2022-03-21 17:15:43 +01:00
committed by Javi Martín
parent 8c7091612e
commit ecde8c6439
32 changed files with 174 additions and 18 deletions

View File

@@ -4,7 +4,7 @@ class Activity < ApplicationRecord
VALID_ACTIONS = %w[hide block restore valuate email].freeze
validates :action, inclusion: { in: VALID_ACTIONS }
validates :action, inclusion: { in: ->(*) { VALID_ACTIONS }}
scope :on_proposals, -> { where(actionable_type: "Proposal") }
scope :on_debates, -> { where(actionable_type: "Debate") }

View File

@@ -25,10 +25,10 @@ class Budget < ApplicationRecord
validates_translation :name, presence: true
validates_translation :main_link_url, presence: true, unless: -> { main_link_text.blank? }
validates :phase, inclusion: { in: Budget::Phase::PHASE_KINDS }
validates :phase, inclusion: { in: ->(*) { Budget::Phase::PHASE_KINDS }}
validates :currency_symbol, presence: true
validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/
validates :voting_style, inclusion: { in: VOTING_STYLES }
validates :voting_style, inclusion: { in: ->(*) { VOTING_STYLES }}
has_many :investments, dependent: :destroy
has_many :ballots, dependent: :destroy

View File

@@ -19,7 +19,7 @@ class Budget
has_one :prev_phase, class_name: name, foreign_key: :next_phase_id, inverse_of: :next_phase
validates_translation :name, presence: true
validates_translation :description, length: { maximum: DESCRIPTION_MAX_LENGTH }
validates_translation :description, length: { maximum: ->(*) { DESCRIPTION_MAX_LENGTH }}
validates_translation :main_link_url, presence: true, unless: -> { main_link_text.blank? }
validates :budget, presence: true
validates :kind, presence: true, uniqueness: { scope: :budget }, inclusion: { in: ->(*) { PHASE_KINDS }}

View File

@@ -7,6 +7,6 @@ class Budget
validates :user, presence: true
validates :investment, presence: true
validates :reason, inclusion: { in: REASONS, allow_nil: false }
validates :reason, inclusion: { in: ->(*) { REASONS }, allow_nil: false }
end
end

View File

@@ -21,7 +21,7 @@ class Comment < ApplicationRecord
validates_translation :body, presence: true
validates :user, presence: true
validates :commentable_type, inclusion: { in: COMMENTABLE_TYPES }
validates :commentable_type, inclusion: { in: ->(*) { COMMENTABLE_TYPES }}
validate :validate_body_length
validate :comment_valuation, if: -> { valuation }

View File

@@ -17,7 +17,7 @@ class Legislation::DraftVersion < ApplicationRecord
validates_translation :title, presence: true
validates_translation :body, presence: true
validates :status, presence: true, inclusion: { in: VALID_STATUSES }
validates :status, presence: true, inclusion: { in: ->(*) { VALID_STATUSES }}
scope :published, -> { where(status: "published").order("id DESC") }

View File

@@ -55,8 +55,8 @@ class Legislation::Process < ApplicationRecord
end
validate :valid_date_ranges
validates :background_color, format: { allow_blank: true, with: CSS_HEX_COLOR }
validates :font_color, format: { allow_blank: true, with: CSS_HEX_COLOR }
validates :background_color, format: { allow_blank: true, with: ->(*) { CSS_HEX_COLOR }}
validates :font_color, format: { allow_blank: true, with: ->(*) { CSS_HEX_COLOR }}
class << self; undef :open; end
scope :open, -> { where("start_date <= ? and end_date >= ?", Date.current, Date.current) }

View File

@@ -11,7 +11,7 @@ class Poll::PartialResult < ApplicationRecord
validates :answer, presence: true
validates :answer, inclusion: { in: ->(a) { a.question.possible_answers }},
unless: ->(a) { a.question.blank? }
validates :origin, inclusion: { in: VALID_ORIGINS }
validates :origin, inclusion: { in: ->(*) { VALID_ORIGINS }}
scope :by_author, ->(author_id) { where(author_id: author_id) }
scope :by_question, ->(question_id) { where(question_id: question_id) }

View File

@@ -6,7 +6,7 @@ class Poll::Recount < ApplicationRecord
belongs_to :officer_assignment
validates :author, presence: true
validates :origin, inclusion: { in: VALID_ORIGINS }
validates :origin, inclusion: { in: ->(*) { VALID_ORIGINS }}
scope :web, -> { where(origin: "web") }
scope :booth, -> { where(origin: "booth") }

View File

@@ -16,7 +16,7 @@ class Poll
validates :document_number, presence: true, unless: :skip_user_verification?
validates :user_id, uniqueness: { scope: [:poll_id], message: :has_voted }
validates :origin, inclusion: { in: VALID_ORIGINS }
validates :origin, inclusion: { in: ->(*) { VALID_ORIGINS }}
before_validation :set_demographic_info, :set_document_info, :set_denormalized_booth_assignment_id

View File

@@ -16,7 +16,7 @@ class ProgressBar < ApplicationRecord
scope: [:progressable_type, :progressable_id],
conditions: -> { primary }
}
validates :percentage, presence: true, inclusion: RANGE, numericality: { only_integer: true }
validates :percentage, presence: true, inclusion: { in: ->(*) { RANGE }}, numericality: { only_integer: true }
validates_translation :title, presence: true, unless: :primary?
end

View File

@@ -51,7 +51,7 @@ class Proposal < ApplicationRecord
validates :responsible_name, presence: true, unless: :skip_user_verification?
validates :responsible_name, length: { in: 6..Proposal.responsible_name_max_length }, unless: :skip_user_verification?
validates :retired_reason, presence: true, inclusion: { in: RETIRE_OPTIONS }, unless: -> { retired_at.blank? }
validates :retired_reason, presence: true, inclusion: { in: ->(*) { RETIRE_OPTIONS }}, unless: -> { retired_at.blank? }
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create

View File

@@ -7,7 +7,7 @@ class SignatureSheet < ApplicationRecord
has_many :signatures
validates :author, presence: true
validates :signable_type, inclusion: { in: VALID_SIGNABLES }
validates :signable_type, inclusion: { in: ->(*) { VALID_SIGNABLES }}
validates :required_fields_to_verify, presence: true
validates :signable, presence: true
validate :signable_found

View File

@@ -2,7 +2,7 @@ class SiteCustomization::ContentBlock < ApplicationRecord
VALID_BLOCKS = %w[top_links footer subnavigation_left subnavigation_right].freeze
validates :locale, presence: true, inclusion: { in: I18n.available_locales.map(&:to_s) }
validates :name, presence: true, uniqueness: { scope: :locale }, inclusion: { in: VALID_BLOCKS }
validates :name, presence: true, uniqueness: { scope: :locale }, inclusion: { in: ->(*) { VALID_BLOCKS }}
def self.block_for(name, locale)
locale ||= I18n.default_locale

View File

@@ -13,7 +13,7 @@ class SiteCustomization::Image < ApplicationRecord
has_attachment :image
validates :name, presence: true, uniqueness: true, inclusion: { in: VALID_IMAGES.keys }
validates :name, presence: true, uniqueness: true, inclusion: { in: ->(*) { VALID_IMAGES.keys }}
validates :image, file_content_type: { allow: ["image/png", "image/jpeg"], if: -> { image.attached? }}
validate :check_image

View File

@@ -10,7 +10,7 @@ class SiteCustomization::Page < ApplicationRecord
validates :slug, presence: true,
uniqueness: { case_sensitive: false },
format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format }
validates :status, presence: true, inclusion: { in: VALID_STATUSES }
validates :status, presence: true, inclusion: { in: ->(*) { VALID_STATUSES }}
scope :published, -> { where(status: "published").sort_desc }
scope :sort_asc, -> { order("id ASC") }

View File

@@ -17,6 +17,13 @@ describe Activity do
expect(build(:activity, action: "dissapear")).not_to be_valid
end
it "dynamically validates valid actions" do
stub_const("#{Activity}::VALID_ACTIONS", %w[custom])
expect(build(:activity, action: "custom")).to be_valid
expect(build(:activity, action: "hide")).not_to be_valid
end
describe "log" do
it "creates an activity entry" do
user = create(:user)

View File

@@ -28,6 +28,16 @@ describe Budget::Phase do
end
end
describe "description validations" do
it "dynamically validates the maximum length" do
stub_const("#{Budget::Phase}::DESCRIPTION_MAX_LENGTH", 3)
informing_phase.description_en = "long"
expect(informing_phase).not_to be_valid
end
end
describe "#dates_range_valid?" do
it "is valid when start & end dates are different & consecutive" do
informing_phase.assign_attributes(starts_at: Date.current, ends_at: Date.tomorrow)

View File

@@ -34,5 +34,15 @@ describe Budget::ReclassifiedVote do
reclassified_vote.reason = "unfeasible"
expect(reclassified_vote).to be_valid
end
it "dynamically validates the reasons" do
stub_const("#{Budget::ReclassifiedVote}::REASONS", %w[custom])
reclassified_vote.reason = "custom"
expect(reclassified_vote).to be_valid
reclassified_vote.reason = "unfeasible"
expect(reclassified_vote).not_to be_valid
end
end
end

View File

@@ -148,6 +148,16 @@ describe Budget do
expect(budget).not_to be_valid
end
it "dynamically validates the phases" do
stub_const("#{Budget::Phase}::PHASE_KINDS", %w[accepting custom])
budget.phase = "custom"
expect(budget).to be_valid
budget.phase = "reviewing"
expect(budget).not_to be_valid
end
it "produces auxiliary methods" do
budget.phase = "accepting"
expect(budget).to be_accepting
@@ -444,6 +454,13 @@ describe Budget do
it { expect(build(:budget, :approval)).to be_valid }
it { expect(build(:budget, :knapsack)).to be_valid }
it { expect(build(:budget, voting_style: "Oups!")).not_to be_valid }
it "dynamically validates the voting styles" do
stub_const("#{Budget}::VOTING_STYLES", %w[custom])
expect(build(:budget, voting_style: "custom")).to be_valid
expect(build(:budget, voting_style: "knapsack")).not_to be_valid
end
end
context "Related supportive methods" do

View File

@@ -11,6 +11,13 @@ describe Comment do
expect(comment).to be_valid
end
it "dynamically validates the commentable types" do
stub_const("#{Comment}::COMMENTABLE_TYPES", %w[Debate])
expect(build(:comment, commentable: create(:debate))).to be_valid
expect(build(:comment, commentable: create(:proposal))).not_to be_valid
end
it "updates cache_counter in debate after hide and restore" do
debate = create(:debate)
comment = create(:comment, commentable: debate)

View File

@@ -10,6 +10,16 @@ describe Legislation::DraftVersion do
expect(legislation_draft_version).to be_valid
end
it "dynamically validates the valid statuses" do
stub_const("#{Legislation::DraftVersion}::VALID_STATUSES", %w[custom])
legislation_draft_version.status = "custom"
expect(legislation_draft_version).to be_valid
legislation_draft_version.status = "published"
expect(legislation_draft_version).not_to be_valid
end
it "renders the html from the markdown body field" do
legislation_draft_version.body = body_markdown

View File

@@ -10,6 +10,13 @@ describe Legislation::Process do
expect(process).to be_valid
end
it "dynamically validates the color format" do
stub_const("#{Legislation::Process}::CSS_HEX_COLOR", /[G-H]{2}/)
expect(build(:legislation_process, font_color: "GG", background_color: "GH")).to be_valid
expect(build(:legislation_process, font_color: "#ff0", background_color: "#00f")).not_to be_valid
end
it "assigns default values to new processes" do
process = Legislation::Process.new

View File

@@ -14,6 +14,13 @@ describe Poll::PartialResult do
expect(build(:poll_partial_result, question: question, answer: "Four")).not_to be_valid
end
it "dynamically validates the valid origins" do
stub_const("#{Poll::PartialResult}::VALID_ORIGINS", %w[custom])
expect(build(:poll_partial_result, origin: "custom")).to be_valid
expect(build(:poll_partial_result, origin: "web")).not_to be_valid
end
end
describe "logging changes" do

View File

@@ -1,6 +1,15 @@
require "rails_helper"
describe Poll::Recount do
describe "validations" do
it "dynamically validates the valid origins" do
stub_const("#{Poll::Recount}::VALID_ORIGINS", %w[custom])
expect(build(:poll_recount, origin: "custom")).to be_valid
expect(build(:poll_recount, origin: "web")).not_to be_valid
end
end
describe "logging changes" do
let(:author) { create(:user) }
let(:officer_assignment) { create(:poll_officer_assignment) }

View File

@@ -117,6 +117,13 @@ describe Poll::Voter do
voter.origin = "web"
expect(voter).to be_valid
end
it "dynamically validates the valid origins" do
stub_const("#{Poll::Voter}::VALID_ORIGINS", %w[custom])
expect(build(:poll_voter, origin: "custom")).to be_valid
expect(build(:poll_voter, origin: "web")).not_to be_valid
end
end
context "assignments" do

View File

@@ -64,6 +64,18 @@ describe ProgressBar do
expect(progress_bar).to be_valid
end
it "dynamically validates the percentage range" do
stub_const("#{ProgressBar}::RANGE", (-99..99))
progress_bar.percentage = -99
expect(progress_bar).to be_valid
progress_bar.percentage = 100
expect(progress_bar).not_to be_valid
end
it "is not valid without a progressable" do
progress_bar.progressable = nil

View File

@@ -171,6 +171,19 @@ describe Proposal do
proposal.retired_reason = nil
expect(proposal).not_to be_valid
end
it "dynamically validates the retired reason" do
stub_const("#{Proposal}::RETIRE_OPTIONS", %w[custom])
proposal.retired_at = Time.current
proposal.retired_explanation = "My custom reason"
proposal.retired_reason = "custom"
expect(proposal).to be_valid
proposal.retired_reason = "duplicated"
expect(proposal).not_to be_valid
end
end
describe "#editable?" do

View File

@@ -26,6 +26,16 @@ describe SignatureSheet do
expect(signature_sheet).not_to be_valid
end
it "dynamically validates the valid signables" do
stub_const("#{SignatureSheet}::VALID_SIGNABLES", %w[Comment])
signature_sheet.signable = create(:comment)
expect(signature_sheet).to be_valid
signature_sheet.signable = create(:proposal)
expect(signature_sheet).not_to be_valid
end
it "is not valid without document numbers" do
signature_sheet.required_fields_to_verify = nil
expect(signature_sheet).not_to be_valid

View File

@@ -17,4 +17,14 @@ RSpec.describe SiteCustomization::ContentBlock, type: :model do
valid_block = build(:site_customization_content_block, name: "top_links", locale: "es")
expect(valid_block).to be_valid
end
it "dynamically validates the valid blocks" do
stub_const("#{SiteCustomization::ContentBlock}::VALID_BLOCKS", %w[custom])
block.name = "custom"
expect(block).to be_valid
block.name = "top_links"
expect(block).not_to be_valid
end
end

View File

@@ -33,5 +33,15 @@ describe SiteCustomization::Image do
expect(image).not_to be_valid
end
it "dynamically validates the valid images" do
stub_const("#{SiteCustomization::Image}::VALID_IMAGES", { "custom" => [223, 80] })
custom = build(:site_customization_image, name: "custom", image: fixture_file_upload("logo_header.png"))
expect(custom).to be_valid
map = build(:site_customization_image, name: "map", image: fixture_file_upload("custom_map.jpg"))
expect(map).not_to be_valid
end
end
end

View File

@@ -13,4 +13,14 @@ RSpec.describe SiteCustomization::Page, type: :model do
custom_page = build(:site_customization_page, slug: "as/as*la")
expect(custom_page).to be_invalid
end
it "dynamically validates the valid statuses" do
stub_const("#{SiteCustomization::Page}::VALID_STATUSES", %w[custom])
custom_page.status = "custom"
expect(custom_page).to be_valid
custom_page.status = "published"
expect(custom_page).not_to be_valid
end
end