Add progress bar model
This commit is contained in:
@@ -5,5 +5,7 @@ module Milestoneable
|
|||||||
has_many :milestones, as: :milestoneable, dependent: :destroy
|
has_many :milestones, as: :milestoneable, dependent: :destroy
|
||||||
|
|
||||||
scope :with_milestones, -> { joins(:milestones).distinct }
|
scope :with_milestones, -> { joins(:milestones).distinct }
|
||||||
|
|
||||||
|
has_many :progress_bars, as: :progressable
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
28
app/models/progress_bar.rb
Normal file
28
app/models/progress_bar.rb
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
class ProgressBar < ActiveRecord::Base
|
||||||
|
self.inheritance_column = nil
|
||||||
|
RANGE = 0..100
|
||||||
|
|
||||||
|
enum kind: %i[primary secondary]
|
||||||
|
|
||||||
|
belongs_to :progressable, polymorphic: true
|
||||||
|
|
||||||
|
translates :title, touch: true
|
||||||
|
include Globalizable
|
||||||
|
|
||||||
|
validates :progressable, presence: true
|
||||||
|
validates :kind, presence: true,
|
||||||
|
uniqueness: {
|
||||||
|
scope: [:progressable_type, :progressable_id],
|
||||||
|
conditions: -> { primary }
|
||||||
|
}
|
||||||
|
validates :percentage, presence: true, inclusion: RANGE, numericality: { only_integer: true }
|
||||||
|
|
||||||
|
before_validation :assign_progress_bar_to_translations
|
||||||
|
validates_translation :title, presence: true, unless: :primary?
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def assign_progress_bar_to_translations
|
||||||
|
translations.each { |translation| translation.globalized_model = self }
|
||||||
|
end
|
||||||
|
end
|
||||||
3
app/models/progress_bar/translation.rb
Normal file
3
app/models/progress_bar/translation.rb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
class ProgressBar::Translation < Globalize::ActiveRecord::Translation
|
||||||
|
delegate :primary?, to: :globalized_model
|
||||||
|
end
|
||||||
@@ -16,6 +16,9 @@ en:
|
|||||||
milestone/status:
|
milestone/status:
|
||||||
one: "Milestone Status"
|
one: "Milestone Status"
|
||||||
other: "Milestone Statuses"
|
other: "Milestone Statuses"
|
||||||
|
progress_bar:
|
||||||
|
one: "Progress bar"
|
||||||
|
other: "Progress bars"
|
||||||
comment:
|
comment:
|
||||||
one: "Comment"
|
one: "Comment"
|
||||||
other: "Comments"
|
other: "Comments"
|
||||||
@@ -136,6 +139,13 @@ en:
|
|||||||
milestone/status:
|
milestone/status:
|
||||||
name: "Name"
|
name: "Name"
|
||||||
description: "Description (optional)"
|
description: "Description (optional)"
|
||||||
|
progress_bar:
|
||||||
|
kind: "Type"
|
||||||
|
title: "Title"
|
||||||
|
percentage: "Current progress"
|
||||||
|
progress_bar/kind:
|
||||||
|
primary: "Primary"
|
||||||
|
secondary: "Secondary"
|
||||||
budget/heading:
|
budget/heading:
|
||||||
name: "Heading name"
|
name: "Heading name"
|
||||||
price: "Price"
|
price: "Price"
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ es:
|
|||||||
milestone/status:
|
milestone/status:
|
||||||
one: "Estado de seguimiento"
|
one: "Estado de seguimiento"
|
||||||
other: "Estados de seguimiento"
|
other: "Estados de seguimiento"
|
||||||
|
progress_bar:
|
||||||
|
one: "Barra de progreso"
|
||||||
|
other: "Barras de progreso"
|
||||||
comment:
|
comment:
|
||||||
one: "Comentario"
|
one: "Comentario"
|
||||||
other: "Comentarios"
|
other: "Comentarios"
|
||||||
@@ -136,6 +139,13 @@ es:
|
|||||||
milestone/status:
|
milestone/status:
|
||||||
name: "Nombre"
|
name: "Nombre"
|
||||||
description: "Descripción (opcional)"
|
description: "Descripción (opcional)"
|
||||||
|
progress_bar:
|
||||||
|
kind: "Tipo"
|
||||||
|
title: "Título"
|
||||||
|
percentage: "Progreso"
|
||||||
|
progress_bar/kind:
|
||||||
|
primary: "Principal"
|
||||||
|
secondary: "Secundaria"
|
||||||
budget/heading:
|
budget/heading:
|
||||||
name: "Nombre de la partida"
|
name: "Nombre de la partida"
|
||||||
price: "Cantidad"
|
price: "Cantidad"
|
||||||
|
|||||||
23
db/migrate/20190103132925_create_progress_bars.rb
Normal file
23
db/migrate/20190103132925_create_progress_bars.rb
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
class CreateProgressBars < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
create_table :progress_bars do |t|
|
||||||
|
t.integer :kind
|
||||||
|
t.integer :percentage
|
||||||
|
t.references :progressable, polymorphic: true
|
||||||
|
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
|
||||||
|
reversible do |change|
|
||||||
|
change.up do
|
||||||
|
ProgressBar.create_translation_table!({
|
||||||
|
title: :string
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
change.down do
|
||||||
|
ProgressBar.drop_translation_table!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
22
db/schema.rb
22
db/schema.rb
@@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
# It's strongly recommended that you check this file into your version control system.
|
# It's strongly recommended that you check this file into your version control system.
|
||||||
|
|
||||||
ActiveRecord::Schema.define(version: 20181206153510) do
|
ActiveRecord::Schema.define(version: 20190103132925) do
|
||||||
|
|
||||||
# These are extensions that must be enabled in order to support this database
|
# These are extensions that must be enabled in order to support this database
|
||||||
enable_extension "plpgsql"
|
enable_extension "plpgsql"
|
||||||
@@ -1088,6 +1088,26 @@ ActiveRecord::Schema.define(version: 20181206153510) do
|
|||||||
|
|
||||||
add_index "polls", ["starts_at", "ends_at"], name: "index_polls_on_starts_at_and_ends_at", using: :btree
|
add_index "polls", ["starts_at", "ends_at"], name: "index_polls_on_starts_at_and_ends_at", using: :btree
|
||||||
|
|
||||||
|
create_table "progress_bar_translations", force: :cascade do |t|
|
||||||
|
t.integer "progress_bar_id", null: false
|
||||||
|
t.string "locale", null: false
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.string "title"
|
||||||
|
end
|
||||||
|
|
||||||
|
add_index "progress_bar_translations", ["locale"], name: "index_progress_bar_translations_on_locale", using: :btree
|
||||||
|
add_index "progress_bar_translations", ["progress_bar_id"], name: "index_progress_bar_translations_on_progress_bar_id", using: :btree
|
||||||
|
|
||||||
|
create_table "progress_bars", force: :cascade do |t|
|
||||||
|
t.integer "kind"
|
||||||
|
t.integer "percentage"
|
||||||
|
t.integer "progressable_id"
|
||||||
|
t.string "progressable_type"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
end
|
||||||
|
|
||||||
create_table "proposal_notifications", force: :cascade do |t|
|
create_table "proposal_notifications", force: :cascade do |t|
|
||||||
t.string "title"
|
t.string "title"
|
||||||
t.text "body"
|
t.text "body"
|
||||||
|
|||||||
@@ -11,4 +11,15 @@ FactoryBot.define do
|
|||||||
description "Milestone description"
|
description "Milestone description"
|
||||||
publication_date { Date.current }
|
publication_date { Date.current }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
factory :progress_bar do
|
||||||
|
association :progressable, factory: :budget_investment
|
||||||
|
percentage { rand(0..100) }
|
||||||
|
kind :primary
|
||||||
|
|
||||||
|
trait(:secondary) do
|
||||||
|
kind :secondary
|
||||||
|
sequence(:title) { |n| "Progress bar #{n} title" }
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
97
spec/models/progress_bar_spec.rb
Normal file
97
spec/models/progress_bar_spec.rb
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
require "rails_helper"
|
||||||
|
|
||||||
|
describe ProgressBar do
|
||||||
|
let(:progress_bar) { build(:progress_bar) }
|
||||||
|
|
||||||
|
it "is valid" do
|
||||||
|
expect(progress_bar).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is valid without a title" do
|
||||||
|
progress_bar.title = nil
|
||||||
|
|
||||||
|
expect(progress_bar).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid with a custom type" do
|
||||||
|
expect { progress_bar.kind = "terciary" }.to raise_exception(ArgumentError)
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid without a percentage" do
|
||||||
|
progress_bar.percentage = nil
|
||||||
|
|
||||||
|
expect(progress_bar).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid with a non-numeric percentage" do
|
||||||
|
progress_bar.percentage = "High"
|
||||||
|
|
||||||
|
expect(progress_bar).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid with a non-integer percentage" do
|
||||||
|
progress_bar.percentage = 22.83
|
||||||
|
|
||||||
|
expect(progress_bar).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid with a negative percentage" do
|
||||||
|
progress_bar.percentage = -1
|
||||||
|
|
||||||
|
expect(progress_bar).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid with a percentage bigger than 100" do
|
||||||
|
progress_bar.percentage = 101
|
||||||
|
|
||||||
|
expect(progress_bar).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is valid with an integer percentage within the limits" do
|
||||||
|
progress_bar.percentage = 0
|
||||||
|
|
||||||
|
expect(progress_bar).to be_valid
|
||||||
|
|
||||||
|
progress_bar.percentage = 100
|
||||||
|
|
||||||
|
expect(progress_bar).to be_valid
|
||||||
|
|
||||||
|
progress_bar.percentage = 83
|
||||||
|
|
||||||
|
expect(progress_bar).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is not valid without a progressable" do
|
||||||
|
progress_bar.progressable = nil
|
||||||
|
|
||||||
|
expect(progress_bar).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "cannot have another primary progress bar for the same progressable" do
|
||||||
|
progress_bar.save
|
||||||
|
duplicate = build(:progress_bar, progressable: progress_bar.progressable)
|
||||||
|
|
||||||
|
expect(duplicate).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "secondary progress bar" do
|
||||||
|
let(:progress_bar) { build(:progress_bar, :secondary) }
|
||||||
|
|
||||||
|
it "is valid" do
|
||||||
|
expect(progress_bar).to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "is invalid without a title" do
|
||||||
|
progress_bar.title = nil
|
||||||
|
|
||||||
|
expect(progress_bar).not_to be_valid
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can have another secondary progress bar for the same progressable" do
|
||||||
|
progress_bar.save
|
||||||
|
duplicate = build(:progress_bar, progressable: progress_bar.progressable)
|
||||||
|
|
||||||
|
expect(duplicate).to be_valid
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user