Create reports
This table will store which reports (stats, results, ...) will be shown for a certain process (polls, budgets, ...). Note Rails fails to save a poll and its report when both are new records if we add a `validate :process, presence: true` rule. Since it caused a lot of trouble when creating records for tests during factories rule completely. Instead, I've created the `results_enabled=` and `stats_enabled=` methods, so tests are easier to set up, while also automatically creating a report if it doesn't already exist. This also decouples form structure and database implemenation. Originally I named this table `enabled_reports` and instead of having `stats` and `results` columns, it had an `enabled` column and a `kind` column, which would be set to "stats" or "results". However, although that table would allow us to add arbitrary reports easily, I found the way we had to handle the `has_many` relationship was a bit too complex.
This commit is contained in:
@@ -15,8 +15,7 @@ class Dashboard::PollsController < Dashboard::BaseController
|
|||||||
def create
|
def create
|
||||||
authorize! :manage_polls, proposal
|
authorize! :manage_polls, proposal
|
||||||
|
|
||||||
@poll = Poll.new(poll_params.merge(author: current_user, related: proposal,
|
@poll = Poll.new(poll_params.merge(author: current_user, related: proposal))
|
||||||
stats_enabled: false))
|
|
||||||
if @poll.save
|
if @poll.save
|
||||||
redirect_to proposal_dashboard_polls_path(proposal), notice: t("flash.actions.create.poll")
|
redirect_to proposal_dashboard_polls_path(proposal), notice: t("flash.actions.create.poll")
|
||||||
else
|
else
|
||||||
@@ -54,7 +53,7 @@ class Dashboard::PollsController < Dashboard::BaseController
|
|||||||
end
|
end
|
||||||
|
|
||||||
def poll_attributes
|
def poll_attributes
|
||||||
[:name, :starts_at, :ends_at, :description, :results_enabled, :stats_enabled,
|
[:name, :starts_at, :ends_at, :description, :results_enabled,
|
||||||
questions_attributes: question_attributes]
|
questions_attributes: question_attributes]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
30
app/models/concerns/reportable.rb
Normal file
30
app/models/concerns/reportable.rb
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
module Reportable
|
||||||
|
extend ActiveSupport::Concern
|
||||||
|
|
||||||
|
included do
|
||||||
|
has_one :report, as: :process, dependent: :destroy
|
||||||
|
accepts_nested_attributes_for :report
|
||||||
|
end
|
||||||
|
|
||||||
|
def report
|
||||||
|
super || build_report
|
||||||
|
end
|
||||||
|
|
||||||
|
def results_enabled?
|
||||||
|
report&.results?
|
||||||
|
end
|
||||||
|
alias_method :results_enabled, :results_enabled?
|
||||||
|
|
||||||
|
def stats_enabled?
|
||||||
|
report&.stats?
|
||||||
|
end
|
||||||
|
alias_method :stats_enabled, :stats_enabled?
|
||||||
|
|
||||||
|
def results_enabled=(enabled)
|
||||||
|
report.results = enabled
|
||||||
|
end
|
||||||
|
|
||||||
|
def stats_enabled=(enabled)
|
||||||
|
report.stats = enabled
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -7,6 +7,7 @@ class Poll < ApplicationRecord
|
|||||||
include Notifiable
|
include Notifiable
|
||||||
include Sluggable
|
include Sluggable
|
||||||
include StatsVersionable
|
include StatsVersionable
|
||||||
|
include Reportable
|
||||||
|
|
||||||
translates :name, touch: true
|
translates :name, touch: true
|
||||||
translates :summary, touch: true
|
translates :summary, touch: true
|
||||||
|
|||||||
3
app/models/report.rb
Normal file
3
app/models/report.rb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
class Report < ApplicationRecord
|
||||||
|
belongs_to :process, polymorphic: true
|
||||||
|
end
|
||||||
@@ -1,12 +1,11 @@
|
|||||||
<%= form_for [:admin, @poll], action: "update" do |f| %>
|
<%= form_for [:admin, @poll], action: "update" do |f| %>
|
||||||
<fieldset class="fieldset">
|
<fieldset class="fieldset">
|
||||||
<legend><%= t("admin.polls.new.show_results_and_stats") %></legend>
|
<legend><%= t("admin.polls.new.show_results_and_stats") %></legend>
|
||||||
<%= f.check_box :results_enabled, checked: @poll.results_enabled?, label: t("admin.polls.new.show_results") %>
|
<%= f.check_box :results_enabled %>
|
||||||
<%= f.check_box :stats_enabled, checked: @poll.stats_enabled?, label: t("admin.polls.new.show_stats") %>
|
<%= f.check_box :stats_enabled %>
|
||||||
<p class="small"><%= t("admin.polls.new.results_and_stats_reminder") %></p>
|
<p class="small"><%= t("admin.polls.new.results_and_stats_reminder") %></p>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
||||||
|
|
||||||
<div class="small-12 medium-4 large-2">
|
<div class="small-12 medium-4 large-2">
|
||||||
<%= f.submit t("admin.polls.#{admin_submit_action(@poll)}.submit_button"),
|
<%= f.submit t("admin.polls.#{admin_submit_action(@poll)}.submit_button"),
|
||||||
class: "button success expanded" %>
|
class: "button success expanded" %>
|
||||||
|
|||||||
@@ -212,6 +212,8 @@ en:
|
|||||||
geozone_restricted: "Restricted by geozone"
|
geozone_restricted: "Restricted by geozone"
|
||||||
summary: "Summary"
|
summary: "Summary"
|
||||||
description: "Description"
|
description: "Description"
|
||||||
|
results_enabled: "Show results"
|
||||||
|
stats_enabled: "Show stats"
|
||||||
poll/translation:
|
poll/translation:
|
||||||
name: "Name"
|
name: "Name"
|
||||||
summary: "Summary"
|
summary: "Summary"
|
||||||
|
|||||||
@@ -1049,8 +1049,6 @@ en:
|
|||||||
new:
|
new:
|
||||||
title: "New poll"
|
title: "New poll"
|
||||||
show_results_and_stats: "Show results and stats"
|
show_results_and_stats: "Show results and stats"
|
||||||
show_results: "Show results"
|
|
||||||
show_stats: "Show stats"
|
|
||||||
results_and_stats_reminder: "Marking these checkboxes the results and/or stats of this poll will be publicly available and every user will see them."
|
results_and_stats_reminder: "Marking these checkboxes the results and/or stats of this poll will be publicly available and every user will see them."
|
||||||
submit_button: "Create poll"
|
submit_button: "Create poll"
|
||||||
edit:
|
edit:
|
||||||
|
|||||||
@@ -212,6 +212,8 @@ es:
|
|||||||
geozone_restricted: "Restringida por zonas"
|
geozone_restricted: "Restringida por zonas"
|
||||||
summary: "Resumen"
|
summary: "Resumen"
|
||||||
description: "Descripción"
|
description: "Descripción"
|
||||||
|
results_enabled: "Mostrar resultados"
|
||||||
|
stats_enabled: "Mostrar estadísticas"
|
||||||
poll/translation:
|
poll/translation:
|
||||||
name: "Nombre"
|
name: "Nombre"
|
||||||
summary: "Resumen"
|
summary: "Resumen"
|
||||||
|
|||||||
@@ -1048,8 +1048,6 @@ es:
|
|||||||
new:
|
new:
|
||||||
title: "Nueva votación"
|
title: "Nueva votación"
|
||||||
show_results_and_stats: "Mostrar resultados y estadísticas"
|
show_results_and_stats: "Mostrar resultados y estadísticas"
|
||||||
show_results: "Mostrar resultados"
|
|
||||||
show_stats: "Mostrar estadísticas"
|
|
||||||
results_and_stats_reminder: "Si marcas estas casillas los resultados y/o estadísticas de esta votación serán públicos y podrán verlos todos los usuarios."
|
results_and_stats_reminder: "Si marcas estas casillas los resultados y/o estadísticas de esta votación serán públicos y podrán verlos todos los usuarios."
|
||||||
submit_button: "Crear votación"
|
submit_button: "Crear votación"
|
||||||
edit:
|
edit:
|
||||||
|
|||||||
11
db/migrate/20190424114803_create_reports.rb
Normal file
11
db/migrate/20190424114803_create_reports.rb
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
class CreateReports < ActiveRecord::Migration[5.0]
|
||||||
|
def change
|
||||||
|
create_table :reports do |t|
|
||||||
|
t.boolean :stats
|
||||||
|
t.boolean :results
|
||||||
|
t.references :process, polymorphic: true
|
||||||
|
|
||||||
|
t.timestamps null: false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
12
db/schema.rb
12
db/schema.rb
@@ -10,7 +10,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: 20190411090023) do
|
ActiveRecord::Schema.define(version: 20190424114803) 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"
|
||||||
@@ -1234,6 +1234,16 @@ ActiveRecord::Schema.define(version: 20190411090023) do
|
|||||||
t.index ["related_content_id"], name: "opposite_related_content", using: :btree
|
t.index ["related_content_id"], name: "opposite_related_content", using: :btree
|
||||||
end
|
end
|
||||||
|
|
||||||
|
create_table "reports", force: :cascade do |t|
|
||||||
|
t.boolean "stats"
|
||||||
|
t.boolean "results"
|
||||||
|
t.string "process_type"
|
||||||
|
t.integer "process_id"
|
||||||
|
t.datetime "created_at", null: false
|
||||||
|
t.datetime "updated_at", null: false
|
||||||
|
t.index ["process_type", "process_id"], name: "index_reports_on_process_type_and_process_id", using: :btree
|
||||||
|
end
|
||||||
|
|
||||||
create_table "settings", force: :cascade do |t|
|
create_table "settings", force: :cascade do |t|
|
||||||
t.string "key"
|
t.string "key"
|
||||||
t.string "value"
|
t.string "value"
|
||||||
|
|||||||
71
spec/models/concerns/reportable.rb
Normal file
71
spec/models/concerns/reportable.rb
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
shared_examples "reportable" do
|
||||||
|
let(:reportable) { create(model_name(described_class)) }
|
||||||
|
|
||||||
|
describe "#results_enabled" do
|
||||||
|
it "can write and read the attribute" do
|
||||||
|
reportable.results_enabled = true
|
||||||
|
|
||||||
|
expect(reportable.results_enabled?).to be true
|
||||||
|
expect(reportable.results_enabled).to be true
|
||||||
|
|
||||||
|
reportable.results_enabled = false
|
||||||
|
|
||||||
|
expect(reportable.results_enabled?).to be false
|
||||||
|
expect(reportable.results_enabled).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can save the value to the database" do
|
||||||
|
reportable.update(results_enabled: true)
|
||||||
|
saved_reportable = described_class.last
|
||||||
|
|
||||||
|
expect(saved_reportable.results_enabled?).to be true
|
||||||
|
expect(saved_reportable.results_enabled).to be true
|
||||||
|
|
||||||
|
reportable.update(results_enabled: false)
|
||||||
|
saved_reportable = described_class.last
|
||||||
|
|
||||||
|
expect(saved_reportable.results_enabled?).to be false
|
||||||
|
expect(saved_reportable.results_enabled).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uses the `has_one` relation instead of the original column" do
|
||||||
|
reportable.update(results_enabled: true)
|
||||||
|
|
||||||
|
expect(reportable.read_attribute(:results_enabled)).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe "#stats_enabled" do
|
||||||
|
it "can write and read the attribute" do
|
||||||
|
reportable.stats_enabled = true
|
||||||
|
|
||||||
|
expect(reportable.stats_enabled?).to be true
|
||||||
|
expect(reportable.stats_enabled).to be true
|
||||||
|
|
||||||
|
reportable.stats_enabled = false
|
||||||
|
|
||||||
|
expect(reportable.stats_enabled?).to be false
|
||||||
|
expect(reportable.stats_enabled).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can save the attribute to the database" do
|
||||||
|
reportable.update(stats_enabled: true)
|
||||||
|
saved_reportable = described_class.last
|
||||||
|
|
||||||
|
expect(saved_reportable.stats_enabled?).to be true
|
||||||
|
expect(saved_reportable.stats_enabled).to be true
|
||||||
|
|
||||||
|
reportable.update(stats_enabled: false)
|
||||||
|
saved_reportable = described_class.last
|
||||||
|
|
||||||
|
expect(saved_reportable.stats_enabled?).to be false
|
||||||
|
expect(saved_reportable.stats_enabled).to be false
|
||||||
|
end
|
||||||
|
|
||||||
|
it "uses the `has_one` relation instead of the original column" do
|
||||||
|
reportable.update(stats_enabled: true)
|
||||||
|
|
||||||
|
expect(reportable.read_attribute(:stats_enabled)).to be false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -6,6 +6,7 @@ describe Poll do
|
|||||||
|
|
||||||
describe "Concerns" do
|
describe "Concerns" do
|
||||||
it_behaves_like "notifiable"
|
it_behaves_like "notifiable"
|
||||||
|
it_behaves_like "reportable"
|
||||||
end
|
end
|
||||||
|
|
||||||
describe "validations" do
|
describe "validations" do
|
||||||
|
|||||||
Reference in New Issue
Block a user