Apply Layout/LineLength rubocop rule

Note we're excluding a few files:

* Configuration files that weren't generated by us
* Migration files that weren't generated by us
* The Gemfile, since it includes an important comment that must be on
  the same line as the gem declaration
* The Budget::Stats class, since the heading statistics are a mess and
  having shorter lines would require a lot of refactoring
This commit is contained in:
Javi Martín
2023-07-19 21:37:59 +02:00
parent 75d2782061
commit a1439d0790
156 changed files with 1330 additions and 503 deletions

View File

@@ -120,7 +120,14 @@ Layout/LineEndStringConcatenationIndentation:
Layout/LineLength: Layout/LineLength:
Max: 110 Max: 110
Severity: refactor Exclude:
- "Gemfile"
- "config/environments/production.rb"
- "config/environments/staging.rb"
- "config/initializers/devise.rb"
- "config/initializers/backtrace_silencers.rb"
- "db/migrate/*create_delayed_jobs.rb"
- "app/models/budget/stats.rb"
Layout/MultilineArrayBraceLayout: Layout/MultilineArrayBraceLayout:
Enabled: true Enabled: true

View File

@@ -183,7 +183,8 @@ class Admin::MenuComponent < ApplicationComponent
[ [
t("admin.menu.poll_booth_assignments"), t("admin.menu.poll_booth_assignments"),
booth_assignments_admin_polls_path, booth_assignments_admin_polls_path,
controller_name == "polls" && action_name == "booth_assignments" || controller_name == "booth_assignments" && action_name == "manage" controller_name == "polls" && action_name == "booth_assignments" ||
controller_name == "booth_assignments" && action_name == "manage"
] ]
end end
@@ -255,7 +256,8 @@ class Admin::MenuComponent < ApplicationComponent
banners_link, banners_link,
information_texts_link, information_texts_link,
documents_link, documents_link,
class: ("is-active" if customization? && controller.class.module_parent != Admin::Poll::Questions::Answers) class: ("is-active" if customization? &&
controller.class.module_parent != Admin::Poll::Questions::Answers)
) )
end end

View File

@@ -64,7 +64,10 @@ class Budgets::Investments::VotesComponent < ApplicationComponent
t("votes.budget_investments.#{reason}", t("votes.budget_investments.#{reason}",
count: investment.group.max_votable_headings, count: investment.group.max_votable_headings,
verify_account: link_to_verify_account, verify_account: link_to_verify_account,
supported_headings: (current_user && current_user.headings_voted_within_group(investment.group).map(&:name).sort.to_sentence)) supported_headings: (current_user && current_user.headings_voted_within_group(investment.group)
.map(&:name)
.sort
.to_sentence))
end end
end end
end end

View File

@@ -13,6 +13,8 @@ class Relationable::RelatedListComponent < ApplicationComponent
private private
def related_contents def related_contents
@related_contents ||= Kaminari.paginate_array(relationable.relationed_contents).page(params[:page]).per(5) @related_contents ||= Kaminari.paginate_array(relationable.relationed_contents)
.page(params[:page])
.per(5)
end end
end end

View File

@@ -33,7 +33,8 @@ class SDG::FilterLinksComponent < ApplicationComponent
def index_by(advanced_search) def index_by(advanced_search)
if related_model.name == "Legislation::Proposal" if related_model.name == "Legislation::Proposal"
legislation_process_proposals_path(params[:id], advanced_search: advanced_search, filter: params[:filter]) legislation_process_proposals_path(params[:id], advanced_search: advanced_search,
filter: params[:filter])
else else
polymorphic_path(related_model, advanced_search: advanced_search) polymorphic_path(related_model, advanced_search: advanced_search)
end end

View File

@@ -22,7 +22,8 @@ class Admin::Api::StatsController < Admin::Api::BaseController
end end
if params[:user_supported_budgets].present? if params[:user_supported_budgets].present?
ds.add "User supported budgets", Vote.where(votable_type: "Budget::Investment").group_by_day(:updated_at).count ds.add "User supported budgets",
Vote.where(votable_type: "Budget::Investment").group_by_day(:updated_at).count
end end
render json: ds.build render json: ds.build
end end

View File

@@ -10,7 +10,9 @@ module Budgets
authorize_resource :budget authorize_resource :budget
authorize_resource :ballot authorize_resource :ballot
load_and_authorize_resource :line, through: :ballot, find_by: :investment_id, class: "Budget::Ballot::Line" load_and_authorize_resource :line, through: :ballot,
find_by: :investment_id,
class: "Budget::Ballot::Line"
def create def create
load_investment load_investment

View File

@@ -28,7 +28,8 @@ module Budgets
has_orders %w[most_voted newest oldest], only: :show has_orders %w[most_voted newest oldest], only: :show
has_orders ->(c) { c.instance_variable_get(:@budget).investments_orders }, only: :index has_orders ->(c) { c.instance_variable_get(:@budget).investments_orders }, only: :index
has_filters ->(c) { c.instance_variable_get(:@budget).investments_filters }, only: [:index, :show, :suggest] has_filters ->(c) { c.instance_variable_get(:@budget).investments_filters },
only: [:index, :show, :suggest]
invisible_captcha only: [:create, :update], honeypot: :subtitle, scope: :budget_investment invisible_captcha only: [:create, :update], honeypot: :subtitle, scope: :budget_investment
@@ -79,12 +80,14 @@ module Budgets
def destroy def destroy
@investment.destroy! @investment.destroy!
redirect_to user_path(current_user, filter: "budget_investments"), notice: t("flash.actions.destroy.budget_investment") redirect_to user_path(current_user, filter: "budget_investments"),
notice: t("flash.actions.destroy.budget_investment")
end end
def suggest def suggest
@resource_path_method = :namespaced_budget_investment_path @resource_path_method = :namespaced_budget_investment_path
@resource_relation = resource_model.where(budget: @budget).apply_filters_and_search(@budget, params, @current_filter) @resource_relation = resource_model.where(budget: @budget)
.apply_filters_and_search(@budget, params, @current_filter)
super super
end end

View File

@@ -59,7 +59,8 @@ module Admin::BudgetHeadingsActions
end end
def allowed_params def allowed_params
valid_attributes = [:price, :population, :allow_custom_content, :latitude, :longitude, :max_ballot_lines, :geozone_id] valid_attributes = [:price, :population, :allow_custom_content, :latitude, :longitude,
:max_ballot_lines, :geozone_id]
[*valid_attributes, translation_params(Budget::Heading)] [*valid_attributes, translation_params(Budget::Heading)]
end end

View File

@@ -7,7 +7,11 @@ module CommentableActions
def index def index
@resources = resource_model.all @resources = resource_model.all
@resources = @current_order == "recommendations" && current_user.present? ? @resources.recommendations(current_user) : @resources.for_render @resources = if @current_order == "recommendations" && current_user.present?
@resources.recommendations(current_user)
else
@resources.for_render
end
@resources = @resources.search(@search_terms) if @search_terms.present? @resources = @resources.search(@search_terms) if @search_terms.present?
@resources = @resources.filter_by(@advanced_search_terms) @resources = @resources.filter_by(@advanced_search_terms)

View File

@@ -8,7 +8,9 @@ class DirectUploadsController < ApplicationController
helper_method :render_destroy_upload_link helper_method :render_destroy_upload_link
def create def create
@direct_upload = DirectUpload.new(direct_upload_params.merge(user: current_user, attachment: params[:attachment])) @direct_upload = DirectUpload.new(
direct_upload_params.merge(user: current_user, attachment: params[:attachment])
)
if @direct_upload.valid? if @direct_upload.valid?
@direct_upload.save_attachment @direct_upload.save_attachment

View File

@@ -30,7 +30,8 @@ class Legislation::ProposalsController < Legislation::BaseController
@proposal = Legislation::Proposal.new(proposal_params.merge(author: current_user)) @proposal = Legislation::Proposal.new(proposal_params.merge(author: current_user))
if @proposal.save if @proposal.save
redirect_to legislation_process_proposal_path(params[:process_id], @proposal), notice: I18n.t("flash.actions.create.proposal") redirect_to legislation_process_proposal_path(params[:process_id], @proposal),
notice: I18n.t("flash.actions.create.proposal")
else else
render :new render :new
end end

View File

@@ -37,7 +37,10 @@ class Management::Budgets::InvestmentsController < Management::BaseController
end end
def print def print
@investments = @investments.apply_filters_and_search(@budget, params).order(cached_votes_up: :desc).for_render.limit(15) @investments = @investments.apply_filters_and_search(@budget, params)
.order(cached_votes_up: :desc)
.for_render
.limit(15)
end end
private private

View File

@@ -15,7 +15,9 @@ class Management::DocumentVerificationsController < Management::BaseController
elsif @document_verification.user? elsif @document_verification.user?
render :new render :new
elsif @document_verification.in_census? elsif @document_verification.in_census?
redirect_to new_management_email_verification_path(email_verification: document_verification_params.to_h) redirect_to new_management_email_verification_path(
email_verification: document_verification_params.to_h
)
else else
render :invalid_document render :invalid_document
end end
@@ -49,6 +51,8 @@ class Management::DocumentVerificationsController < Management::BaseController
def clean_document_number def clean_document_number
return if params[:document_verification][:document_number].blank? return if params[:document_verification][:document_number].blank?
params[:document_verification][:document_number] = params[:document_verification][:document_number].gsub(/[^a-z0-9]+/i, "").upcase params[:document_verification][:document_number] = params[:document_verification][:document_number]
.gsub(/[^a-z0-9]+/i, "")
.upcase
end end
end end

View File

@@ -31,7 +31,9 @@ class Management::ProposalsController < Management::BaseController
super super
@notifications = @proposal.notifications @notifications = @proposal.notifications
redirect_to management_proposal_path(@proposal), status: :moved_permanently if request.path != management_proposal_path(@proposal) if request.path != management_proposal_path(@proposal)
redirect_to management_proposal_path(@proposal), status: :moved_permanently
end
end end
def vote def vote

View File

@@ -24,7 +24,10 @@ class Management::UsersController < Management::BaseController
end end
def erase def erase
managed_user.erase(t("management.users.erased_by_manager", manager: current_manager["login"])) if current_manager.present? if current_manager.present?
managed_user.erase(t("management.users.erased_by_manager", manager: current_manager["login"]))
end
destroy_session destroy_session
redirect_to management_document_verifications_path, notice: t("management.users.erased_notice") redirect_to management_document_verifications_path, notice: t("management.users.erased_notice")
end end

View File

@@ -10,7 +10,8 @@ class Officing::ResidenceController < Officing::BaseController
def create def create
@residence = Officing::Residence.new(residence_params.merge(officer: current_user.poll_officer)) @residence = Officing::Residence.new(residence_params.merge(officer: current_user.poll_officer))
if @residence.save if @residence.save
redirect_to new_officing_voter_path(id: @residence.user.id), notice: t("officing.residence.flash.create") redirect_to new_officing_voter_path(id: @residence.user.id),
notice: t("officing.residence.flash.create")
else else
render :new render :new
end end

View File

@@ -46,10 +46,12 @@ class Officing::ResultsController < Officing::BaseController
answer = question.question_answers.find_by(given_order: answer_index.to_i + 1).title answer = question.question_answers.find_by(given_order: answer_index.to_i + 1).title
go_back_to_new if question.blank? go_back_to_new if question.blank?
partial_result = ::Poll::PartialResult.find_or_initialize_by(booth_assignment_id: @officer_assignment.booth_assignment_id, partial_result = ::Poll::PartialResult.find_or_initialize_by(
date: Date.current, booth_assignment_id: @officer_assignment.booth_assignment_id,
question_id: question_id, date: Date.current,
answer: answer) question_id: question_id,
answer: answer
)
partial_result.officer_assignment_id = @officer_assignment.id partial_result.officer_assignment_id = @officer_assignment.id
partial_result.amount = count.to_i partial_result.amount = count.to_i
partial_result.author = current_user partial_result.author = current_user
@@ -62,8 +64,10 @@ class Officing::ResultsController < Officing::BaseController
end end
def build_recounts def build_recounts
recount = ::Poll::Recount.find_or_initialize_by(booth_assignment_id: @officer_assignment.booth_assignment_id, recount = ::Poll::Recount.find_or_initialize_by(
date: Date.current) booth_assignment_id: @officer_assignment.booth_assignment_id,
date: Date.current
)
recount.officer_assignment_id = @officer_assignment.id recount.officer_assignment_id = @officer_assignment.id
recount.author = current_user recount.author = current_user
recount.origin = "booth" recount.origin = "booth"
@@ -90,7 +94,9 @@ class Officing::ResultsController < Officing::BaseController
def load_officer_assignment def load_officer_assignment
@officer_assignment = current_user.poll_officer @officer_assignment = current_user.poll_officer
.officer_assignments.final.find_by(id: results_params[:officer_assignment_id]) .officer_assignments
.final
.find_by(id: results_params[:officer_assignment_id])
end end
def load_officer_assignments def load_officer_assignments

View File

@@ -137,7 +137,10 @@ class ProposalsController < ApplicationController
def load_retired def load_retired
if params[:retired].present? if params[:retired].present?
@resources = @resources.retired @resources = @resources.retired
@resources = @resources.where(retired_reason: params[:retired]) if Proposal::RETIRE_OPTIONS.include?(params[:retired])
if Proposal::RETIRE_OPTIONS.include?(params[:retired])
@resources = @resources.where(retired_reason: params[:retired])
end
else else
@resources = @resources.not_retired @resources = @resources.not_retired
end end
@@ -152,7 +155,8 @@ class ProposalsController < ApplicationController
end end
def load_featured def load_featured
return unless !@advanced_search_terms && @search_terms.blank? && params[:retired].blank? && @current_order != "recommendations" return unless !@advanced_search_terms && @search_terms.blank? &&
params[:retired].blank? && @current_order != "recommendations"
if Setting["feature.featured_proposals"] if Setting["feature.featured_proposals"]
@featured_proposals = Proposal.not_archived @featured_proposals = Proposal.not_archived

View File

@@ -43,7 +43,8 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
yield resource if block_given? yield resource if block_given?
# New condition added to if: when no password was given, display the "show" view (which uses "update" above) # New condition added to if: when no password was given, display the "show" view
# (which uses "update" above)
if resource.encrypted_password.blank? if resource.encrypted_password.blank?
respond_with_navigational(resource) { render :show } respond_with_navigational(resource) { render :show }
elsif resource.errors.empty? elsif resource.errors.empty?
@@ -51,9 +52,14 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
if resource.confirm if resource.confirm
set_flash_message(:notice, :confirmed) if is_flashing_format? set_flash_message(:notice, :confirmed) if is_flashing_format?
respond_with_navigational(resource) { redirect_to after_confirmation_path_for(resource_name, resource) }
respond_with_navigational(resource) do
redirect_to after_confirmation_path_for(resource_name, resource)
end
else else
respond_with_navigational(resource.errors, status: :unprocessable_entity) { render :new, status: :unprocessable_entity } respond_with_navigational(resource.errors, status: :unprocessable_entity) do
render :new, status: :unprocessable_entity
end
end end
else else
respond_with_navigational(resource.errors, status: :unprocessable_entity) { render :new } respond_with_navigational(resource.errors, status: :unprocessable_entity) { render :new }

View File

@@ -1,5 +1,6 @@
class Users::RegistrationsController < Devise::RegistrationsController class Users::RegistrationsController < Devise::RegistrationsController
prepend_before_action :authenticate_scope!, only: [:edit, :update, :destroy, :finish_signup, :do_finish_signup] prepend_before_action :authenticate_scope!,
only: [:edit, :update, :destroy, :finish_signup, :do_finish_signup]
before_action :configure_permitted_parameters before_action :configure_permitted_parameters
invisible_captcha only: [:create], honeypot: :address, scope: :user invisible_captcha only: [:create], honeypot: :address, scope: :user
@@ -52,16 +53,21 @@ class Users::RegistrationsController < Devise::RegistrationsController
def check_username def check_username
if User.find_by username: params[:username] if User.find_by username: params[:username]
render json: { available: false, message: t("devise_views.users.registrations.new.username_is_not_available") } render json: { available: false,
message: t("devise_views.users.registrations.new.username_is_not_available") }
else else
render json: { available: true, message: t("devise_views.users.registrations.new.username_is_available") } render json: { available: true,
message: t("devise_views.users.registrations.new.username_is_available") }
end end
end end
private private
def sign_up_params def sign_up_params
params[:user].delete(:redeemable_code) if params[:user].present? && params[:user][:redeemable_code].blank? if params[:user].present? && params[:user][:redeemable_code].blank?
params[:user].delete(:redeemable_code)
end
params.require(:user).permit(allowed_params) params.require(:user).permit(allowed_params)
end end

View File

@@ -22,7 +22,8 @@ class Verification::EmailController < ApplicationController
@email.encrypted_token, @email.encrypted_token,
@verified_user.document_type, @verified_user.document_type,
@verified_user.document_number).deliver_later @verified_user.document_number).deliver_later
redirect_to account_path, notice: t("verification.email.create.flash.success", email: @verified_user.email) redirect_to account_path,
notice: t("verification.email.create.flash.success", email: @verified_user.email)
else else
redirect_to verified_user_path, alert: t("verification.email.create.alert.failure") redirect_to verified_user_path, alert: t("verification.email.create.alert.failure")
end end

View File

@@ -20,8 +20,15 @@ module Types
argument :id, ID, required: true, default_value: false argument :id, ID, required: true, default_value: false
end end
field :proposal_notifications, Types::ProposalNotificationType.connection_type, "Returns all proposal notifications", null: false field :proposal_notifications,
field :proposal_notification, Types::ProposalNotificationType, "Returns proposal notification for ID", null: false do Types::ProposalNotificationType.connection_type,
"Returns all proposal notifications",
null: false
field :proposal_notification,
Types::ProposalNotificationType,
"Returns proposal notification for ID",
null: false do
argument :id, ID, required: true, default_value: false argument :id, ID, required: true, default_value: false
end end

View File

@@ -6,7 +6,10 @@ module AdminHelper
def official_level_options def official_level_options
options = [["", 0]] options = [["", 0]]
(1..5).each do |i| (1..5).each do |i|
options << [[t("admin.officials.level_#{i}"), setting["official_level_#{i}_name"]].compact.join(": "), i] options << [
[t("admin.officials.level_#{i}"), setting["official_level_#{i}_name"]].compact.join(": "),
i
]
end end
options options
end end

View File

@@ -21,9 +21,17 @@ module CommentsHelper
def comment_button_text(parent_id, commentable) def comment_button_text(parent_id, commentable)
if commentable.class == Legislation::Question if commentable.class == Legislation::Question
parent_id.present? ? t("comments_helper.reply_button") : t("legislation.questions.comments.comment_button") if parent_id.present?
t("comments_helper.reply_button")
else
t("legislation.questions.comments.comment_button")
end
else else
parent_id.present? ? t("comments_helper.reply_button") : t("comments_helper.comment_button") if parent_id.present?
t("comments_helper.reply_button")
else
t("comments_helper.comment_button")
end
end end
end end

View File

@@ -8,7 +8,11 @@ module CommunitiesHelper
end end
def community_description(community) def community_description(community)
community.from_proposal? ? t("community.show.description.proposal") : t("community.show.description.investment") if community.from_proposal?
t("community.show.description.proposal")
else
t("community.show.description.investment")
end
end end
def author?(community, participant) def author?(community, participant)
@@ -28,7 +32,11 @@ module CommunitiesHelper
end end
def community_access_text(community) def community_access_text(community)
community.from_proposal? ? t("community.sidebar.description.proposal") : t("community.sidebar.description.investment") if community.from_proposal?
t("community.sidebar.description.proposal")
else
t("community.sidebar.description.investment")
end
end end
def create_topic_link(community) def create_topic_link(community)

View File

@@ -49,7 +49,10 @@ module MailerHelper
end end
def css_for_mailer_button def css_for_mailer_button
mailer_font_family + "background: #004a83;border-radius: 6px;color: #fff!important;display: inline-block;font-weight: bold;margin: 0;min-width: 200px;padding: 10px 15px;text-align: center;text-decoration: none;" mailer_font_family + "background: #004a83;border-radius: 6px;color: #fff!important;" \
"display: inline-block;font-weight: bold;margin: 0;" \
"min-width: 200px;padding: 10px 15px;text-align: center;" \
"text-decoration: none;"
end end
def css_for_mailer_link def css_for_mailer_link

View File

@@ -2,7 +2,8 @@ module ProposalsHelper
def progress_bar_percentage(proposal) def progress_bar_percentage(proposal)
case proposal.cached_votes_up case proposal.cached_votes_up
when 0 then 0 when 0 then 0
when 1..Proposal.votes_needed_for_success then (proposal.total_votes.to_f * 100 / Proposal.votes_needed_for_success).floor when 1..Proposal.votes_needed_for_success
(proposal.total_votes.to_f * 100 / Proposal.votes_needed_for_success).floor
else 100 else 100
end end
end end

View File

@@ -11,7 +11,10 @@ class Mailer < ApplicationMailer
manage_subscriptions_token(@commentable.author) manage_subscriptions_token(@commentable.author)
with_user(@commentable.author) do with_user(@commentable.author) do
subject = t("mailers.comment.subject", commentable: t("activerecord.models.#{@commentable.class.name.underscore}", count: 1).downcase) subject = t(
"mailers.comment.subject",
commentable: t("activerecord.models.#{@commentable.class.name.underscore}", count: 1).downcase
)
mail(to: @email_to, subject: subject) if @commentable.present? && @commentable.author.present? mail(to: @email_to, subject: subject) if @commentable.present? && @commentable.author.present?
end end
end end
@@ -65,7 +68,8 @@ class Mailer < ApplicationMailer
manage_subscriptions_token(user) manage_subscriptions_token(user)
with_user(user) do with_user(user) do
mail(to: @email_to, subject: t("mailers.proposal_notification_digest.title", org_name: Setting["org_name"])) mail(to: @email_to,
subject: t("mailers.proposal_notification_digest.title", org_name: Setting["org_name"]))
end end
end end

View File

@@ -49,8 +49,9 @@ module Abilities
can :mark_featured, Debate can :mark_featured, Debate
can :unmark_featured, Debate can :unmark_featured, Debate
can :comment_as_administrator, [Debate, Comment, Proposal, Poll, Poll::Question, Budget::Investment, can :comment_as_administrator, [Debate, Comment, Proposal, Poll, Poll::Question,
Legislation::Question, Legislation::Proposal, Legislation::Annotation, Topic] Budget::Investment, Legislation::Question,
Legislation::Proposal, Legislation::Annotation, Topic]
can [:search, :create, :index, :destroy, :update], ::Administrator can [:search, :create, :index, :destroy, :update], ::Administrator
can [:search, :create, :index, :destroy], ::Moderator can [:search, :create, :index, :destroy], ::Moderator
@@ -121,7 +122,8 @@ module Abilities
can [:manage], ::Legislation::DraftVersion can [:manage], ::Legislation::DraftVersion
can [:manage], ::Legislation::Question can [:manage], ::Legislation::Question
can [:manage], ::Legislation::Proposal can [:manage], ::Legislation::Proposal
cannot :comment_as_moderator, [::Legislation::Question, Legislation::Annotation, ::Legislation::Proposal] cannot :comment_as_moderator,
[::Legislation::Question, Legislation::Annotation, ::Legislation::Proposal]
can [:create], Document can [:create], Document
can [:destroy], Document do |document| can [:destroy], Document do |document|

View File

@@ -91,10 +91,10 @@ module Abilities
can :vote, Legislation::Proposal can :vote, Legislation::Proposal
can :create, Legislation::Answer can :create, Legislation::Answer
can :create, Budget::Investment, budget: { phase: "accepting" } can :create, Budget::Investment, budget: { phase: "accepting" }
can :update, Budget::Investment, budget: { phase: "accepting" }, author_id: user.id can :update, Budget::Investment, budget: { phase: "accepting" }, author_id: user.id
can :suggest, Budget::Investment, budget: { phase: "accepting" } can :suggest, Budget::Investment, budget: { phase: "accepting" }
can :destroy, Budget::Investment, budget: { phase: ["accepting", "reviewing"] }, author_id: user.id can :destroy, Budget::Investment, budget: { phase: ["accepting", "reviewing"] }, author_id: user.id
can [:create, :destroy], ActsAsVotable::Vote, can [:create, :destroy], ActsAsVotable::Vote,
voter_id: user.id, voter_id: user.id,
votable_type: "Budget::Investment", votable_type: "Budget::Investment",

View File

@@ -5,8 +5,9 @@ module Abilities
def initialize(user) def initialize(user)
merge Abilities::Moderation.new(user) merge Abilities::Moderation.new(user)
can :comment_as_moderator, [Debate, Comment, Proposal, Budget::Investment, Poll, Poll::Question, can :comment_as_moderator, [Debate, Comment, Proposal, Budget::Investment, Poll,
Legislation::Question, Legislation::Annotation, Legislation::Proposal, Topic] Poll::Question, Legislation::Question,
Legislation::Annotation, Legislation::Proposal, Topic]
end end
end end
end end

View File

@@ -21,5 +21,7 @@ class Banner < ApplicationRecord
scope :with_active, -> { where("post_started_at <= :date and post_ended_at >= :date", date: Date.current) } scope :with_active, -> { where("post_started_at <= :date and post_ended_at >= :date", date: Date.current) }
scope :with_inactive, -> { where.not(id: with_active) } scope :with_inactive, -> { where.not(id: with_active) }
scope :in_section, ->(section_name) { joins(:web_sections, :sections).where("web_sections.name ilike ?", section_name) } scope :in_section, ->(section_name) do
joins(:web_sections, :sections).where("web_sections.name ilike ?", section_name)
end
end end

View File

@@ -28,7 +28,8 @@ class Budget
def check_valid_heading def check_valid_heading
return if ballot.valid_heading?(heading) return if ballot.valid_heading?(heading)
errors.add(:heading, "This heading's budget is invalid, or a heading on the same group was already selected") errors.add(:heading,
"This heading's budget is invalid, or a heading on the same group was already selected")
end end
def check_selected def check_selected

View File

@@ -56,7 +56,8 @@ class Budget
class_name: "Comment" class_name: "Comment"
validates_translation :title, presence: true, length: { in: 4..Budget::Investment.title_max_length } validates_translation :title, presence: true, length: { in: 4..Budget::Investment.title_max_length }
validates_translation :description, presence: true, length: { maximum: Budget::Investment.description_max_length } validates_translation :description, presence: true,
length: { maximum: Budget::Investment.description_max_length }
validates :author, presence: true validates :author, presence: true
validates :heading_id, presence: true validates :heading_id, presence: true
@@ -104,7 +105,9 @@ class Budget
scope :by_heading, ->(heading_id) { where(heading_id: heading_id) } scope :by_heading, ->(heading_id) { where(heading_id: heading_id) }
scope :by_admin, ->(admin_id) { where(administrator_id: admin_id) } scope :by_admin, ->(admin_id) { where(administrator_id: admin_id) }
scope :by_tag, ->(tag_name) { tagged_with(tag_name).distinct } scope :by_tag, ->(tag_name) { tagged_with(tag_name).distinct }
scope :visible_to_valuator, ->(valuator) { visible_to_valuators.where(id: valuator&.assigned_investment_ids) } scope :visible_to_valuator, ->(valuator) do
visible_to_valuators.where(id: valuator&.assigned_investment_ids)
end
scope :for_render, -> { includes(:heading) } scope :for_render, -> { includes(:heading) }

View File

@@ -2,8 +2,10 @@ module Filterable
extend ActiveSupport::Concern extend ActiveSupport::Concern
included do included do
scope :by_official_level, ->(official_level) { where(users: { official_level: official_level }).joins(:author) } scope :by_date_range, ->(date_range) { where(created_at: date_range) }
scope :by_date_range, ->(date_range) { where(created_at: date_range) } scope :by_official_level, ->(official_level) do
where(users: { official_level: official_level }).joins(:author)
end
end end
class_methods do class_methods do

View File

@@ -83,9 +83,10 @@ module Globalizable
def validates_translation(method, options = {}) def validates_translation(method, options = {})
validates(method, options.merge(if: lambda { |resource| resource.translations.blank? })) validates(method, options.merge(if: lambda { |resource| resource.translations.blank? }))
if options.include?(:length) if options.include?(:length)
lenght_validate = { length: options[:length] }
translation_class.instance_eval do translation_class.instance_eval do
validates method, lenght_validate.merge(if: lambda { |translation| translation.locale == I18n.default_locale }) validates method,
length: options[:length],
if: lambda { |translation| translation.locale == I18n.default_locale }
end end
if options.count > 1 if options.count > 1
translation_class.instance_eval do translation_class.instance_eval do
@@ -112,7 +113,9 @@ module Globalizable
translations_ids = translation_class translations_ids = translation_class
.select("DISTINCT ON (#{translations_foreign_key}) id") .select("DISTINCT ON (#{translations_foreign_key}) id")
.where(locale: fallbacks) .where(locale: fallbacks)
.joins("LEFT JOIN (VALUES #{fallbacks_with_order}) AS locales(name, ordering) ON locale = locales.name") .joins("LEFT JOIN (VALUES #{fallbacks_with_order}) " \
"AS locales(name, ordering) " \
"ON locale = locales.name")
.order(translations_foreign_key, "locales.ordering") .order(translations_foreign_key, "locales.ordering")
with_translations(fallbacks).where("#{translations_table_name}.id": translations_ids) with_translations(fallbacks).where("#{translations_table_name}.id": translations_ids)

View File

@@ -9,10 +9,17 @@ module Verification
scope :phone_not_fully_confirmed, -> { where(unconfirmed_phone: nil).or(where(confirmed_phone: nil)) } scope :phone_not_fully_confirmed, -> { where(unconfirmed_phone: nil).or(where(confirmed_phone: nil)) }
scope :level_three_verified, -> { where.not(verified_at: nil) } scope :level_three_verified, -> { where.not(verified_at: nil) }
scope :level_two_verified, -> { where.not(level_two_verified_at: nil).or(residence_and_phone_verified.where(verified_at: nil)) } scope :level_two_verified, -> do
where.not(level_two_verified_at: nil).or(residence_and_phone_verified.where(verified_at: nil))
end
scope :level_two_or_three_verified, -> { level_two_verified.or(level_three_verified) } scope :level_two_or_three_verified, -> { level_two_verified.or(level_three_verified) }
scope :unverified, -> { residence_or_phone_unverified.where(verified_at: nil, level_two_verified_at: nil) } scope :unverified, -> do
scope :incomplete_verification, -> { residence_unverified.where("failed_census_calls_count > ?", 0).or(residence_verified.phone_not_fully_confirmed) } residence_or_phone_unverified.where(verified_at: nil, level_two_verified_at: nil)
end
scope :incomplete_verification, -> do
residence_unverified.where("failed_census_calls_count > ?", 0)
.or(residence_verified.phone_not_fully_confirmed)
end
end end
def skip_verification? def skip_verification?

View File

@@ -160,7 +160,11 @@ class Debate < ApplicationRecord
def self.debates_orders(user) def self.debates_orders(user)
orders = %w[hot_score confidence_score created_at relevance] orders = %w[hot_score confidence_score created_at relevance]
orders << "recommendations" if Setting["feature.user.recommendations_on_debates"] && user&.recommended_debates
if Setting["feature.user.recommendations_on_debates"] && user&.recommended_debates
orders << "recommendations"
end
orders orders
end end

View File

@@ -16,12 +16,15 @@ class DirectUpload
send("#{name}=", value) send("#{name}=", value)
end end
if @resource_type.present? && @resource_relation.present? && (@attachment.present? || @cached_attachment.present?) if @resource_type.present? &&
@resource_relation.present? &&
(@attachment.present? || @cached_attachment.present?)
@resource = @resource_type.constantize.find_or_initialize_by(id: @resource_id) @resource = @resource_type.constantize.find_or_initialize_by(id: @resource_id)
# Refactor # Refactor
@relation = if @resource.respond_to?(:images) && @relation = if @resource.respond_to?(:images) &&
((@attachment.present? && !@attachment.content_type.match(/pdf/)) || @cached_attachment.present?) (@attachment.present? && !@attachment.content_type.match(/pdf/) ||
@cached_attachment.present?)
@resource.images.send(:build, relation_attributtes) @resource.images.send(:build, relation_attributtes)
elsif @resource.class.reflections[@resource_relation].macro == :has_one elsif @resource.class.reflections[@resource_relation].macro == :has_one
@resource.send("build_#{resource_relation}", relation_attributtes) @resource.send("build_#{resource_relation}", relation_attributtes)

View File

@@ -10,12 +10,19 @@ class Legislation::Question < ApplicationRecord
belongs_to :author, -> { with_hidden }, class_name: "User", inverse_of: :legislation_questions belongs_to :author, -> { with_hidden }, class_name: "User", inverse_of: :legislation_questions
belongs_to :process, foreign_key: "legislation_process_id", inverse_of: :questions belongs_to :process, foreign_key: "legislation_process_id", inverse_of: :questions
has_many :question_options, -> { order(:id) }, class_name: "Legislation::QuestionOption", foreign_key: "legislation_question_id", has_many :question_options, -> { order(:id) }, class_name: "Legislation::QuestionOption",
dependent: :destroy, inverse_of: :question foreign_key: "legislation_question_id",
has_many :answers, class_name: "Legislation::Answer", foreign_key: "legislation_question_id", dependent: :destroy, inverse_of: :question dependent: :destroy,
inverse_of: :question
has_many :answers, class_name: "Legislation::Answer",
foreign_key: "legislation_question_id",
dependent: :destroy,
inverse_of: :question
has_many :comments, as: :commentable, inverse_of: :commentable, dependent: :destroy has_many :comments, as: :commentable, inverse_of: :commentable, dependent: :destroy
accepts_nested_attributes_for :question_options, reject_if: proc { |attributes| attributes.all? { |k, v| v.blank? } }, allow_destroy: true accepts_nested_attributes_for :question_options,
reject_if: proc { |attributes| attributes.all? { |k, v| v.blank? } },
allow_destroy: true
validates :process, presence: true validates :process, presence: true
validates_translation :title, presence: true validates_translation :title, presence: true

View File

@@ -22,13 +22,15 @@ class MachineLearning
return unless run_machine_learning_scripts return unless run_machine_learning_scripts
if updated_file?(MachineLearning.proposals_taggings_filename) && updated_file?(MachineLearning.proposals_tags_filename) if updated_file?(MachineLearning.proposals_taggings_filename) &&
updated_file?(MachineLearning.proposals_tags_filename)
cleanup_proposals_tags! cleanup_proposals_tags!
import_ml_proposals_tags import_ml_proposals_tags
update_machine_learning_info_for("tags") update_machine_learning_info_for("tags")
end end
if updated_file?(MachineLearning.investments_taggings_filename) && updated_file?(MachineLearning.investments_tags_filename) if updated_file?(MachineLearning.investments_taggings_filename) &&
updated_file?(MachineLearning.investments_tags_filename)
cleanup_investments_tags! cleanup_investments_tags!
import_ml_investments_tags import_ml_investments_tags
update_machine_learning_info_for("tags") update_machine_learning_info_for("tags")
@@ -95,14 +97,32 @@ class MachineLearning
def data_output_files def data_output_files
files = { tags: [], related_content: [], comments_summary: [] } files = { tags: [], related_content: [], comments_summary: [] }
files[:tags] << proposals_tags_filename if File.exist?(data_folder.join(proposals_tags_filename)) if File.exist?(data_folder.join(proposals_tags_filename))
files[:tags] << proposals_taggings_filename if File.exist?(data_folder.join(proposals_taggings_filename)) files[:tags] << proposals_tags_filename
files[:tags] << investments_tags_filename if File.exist?(data_folder.join(investments_tags_filename)) end
files[:tags] << investments_taggings_filename if File.exist?(data_folder.join(investments_taggings_filename)) if File.exist?(data_folder.join(proposals_taggings_filename))
files[:related_content] << proposals_related_filename if File.exist?(data_folder.join(proposals_related_filename)) files[:tags] << proposals_taggings_filename
files[:related_content] << investments_related_filename if File.exist?(data_folder.join(investments_related_filename)) end
files[:comments_summary] << proposals_comments_summary_filename if File.exist?(data_folder.join(proposals_comments_summary_filename)) if File.exist?(data_folder.join(investments_tags_filename))
files[:comments_summary] << investments_comments_summary_filename if File.exist?(data_folder.join(investments_comments_summary_filename)) files[:tags] << investments_tags_filename
end
if File.exist?(data_folder.join(investments_taggings_filename))
files[:tags] << investments_taggings_filename
end
if File.exist?(data_folder.join(proposals_related_filename))
files[:related_content] << proposals_related_filename
end
if File.exist?(data_folder.join(investments_related_filename))
files[:related_content] << investments_related_filename
end
if File.exist?(data_folder.join(proposals_comments_summary_filename))
files[:comments_summary] << proposals_comments_summary_filename
end
if File.exist?(data_folder.join(investments_comments_summary_filename))
files[:comments_summary] << investments_comments_summary_filename
end
files files
end end

View File

@@ -12,8 +12,13 @@ class Organization < ApplicationRecord
delegate :email, :phone_number, to: :user delegate :email, :phone_number, to: :user
scope :pending, -> { where(verified_at: nil, rejected_at: nil) } scope :pending, -> { where(verified_at: nil, rejected_at: nil) }
scope :verified, -> { where.not(verified_at: nil).where("(rejected_at IS NULL or rejected_at < organizations.verified_at)") } scope :verified, -> do
scope :rejected, -> { where.not(rejected_at: nil).where("(organizations.verified_at IS NULL or organizations.verified_at < rejected_at)") } where.not(verified_at: nil).where("(rejected_at IS NULL or rejected_at < organizations.verified_at)")
end
scope :rejected, -> do
where.not(rejected_at: nil)
.where("(organizations.verified_at IS NULL or organizations.verified_at < rejected_at)")
end
def verify def verify
update(verified_at: Time.current) update(verified_at: Time.current)
@@ -33,7 +38,8 @@ class Organization < ApplicationRecord
def self.search(text) def self.search(text)
if text.present? if text.present?
joins(:user).where("users.email = ? OR users.phone_number = ? OR organizations.name ILIKE ?", text, text, "%#{text}%") joins(:user).where("users.email = ? OR users.phone_number = ? OR organizations.name ILIKE ?",
text, text, "%#{text}%")
else else
none none
end end

View File

@@ -57,7 +57,8 @@ class Poll < ApplicationRecord
def self.sort_for_list(user = nil) def self.sort_for_list(user = nil)
all.sort do |poll, another_poll| all.sort do |poll, another_poll|
[poll.weight(user), poll.starts_at, poll.name] <=> [another_poll.weight(user), another_poll.starts_at, another_poll.name] [poll.weight(user), poll.starts_at, poll.name] <=>
[another_poll.weight(user), another_poll.starts_at, another_poll.name]
end end
end end

View File

@@ -24,7 +24,9 @@ class Poll
private private
def shifts def shifts
Poll::Shift.where(booth_id: booth_id, officer_id: officer_assignments.pluck(:officer_id), date: officer_assignments.pluck(:date)) Poll::Shift.where(booth_id: booth_id,
officer_id: officer_assignments.pluck(:officer_id),
date: officer_assignments.pluck(:date))
end end
def destroy_poll_shifts def destroy_poll_shifts

View File

@@ -20,7 +20,9 @@ class Poll::Recount < ApplicationRecord
amounts_changed = false amounts_changed = false
[:white, :null, :total].each do |amount| [:white, :null, :total].each do |amount|
next unless send("will_save_change_to_#{amount}_amount?") && send("#{amount}_amount_in_database").present? unless send("will_save_change_to_#{amount}_amount?") && send("#{amount}_amount_in_database").present?
next
end
self["#{amount}_amount_log"] += ":#{send("#{amount}_amount_in_database")}" self["#{amount}_amount_log"] += ":#{send("#{amount}_amount_in_database")}"
amounts_changed = true amounts_changed = true

View File

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

View File

@@ -50,8 +50,12 @@ class Proposal < ApplicationRecord
validates :author, presence: true validates :author, presence: true
validates :responsible_name, presence: true, unless: :skip_user_verification? 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 :responsible_name,
validates :retired_reason, presence: true, inclusion: { in: ->(*) { RETIRE_OPTIONS }}, unless: -> { retired_at.blank? } 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 :terms_of_service, acceptance: { allow_nil: false }, on: :create validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
@@ -236,7 +240,11 @@ class Proposal < ApplicationRecord
def self.proposals_orders(user) def self.proposals_orders(user)
orders = %w[hot_score confidence_score created_at relevance archival_date] orders = %w[hot_score confidence_score created_at relevance archival_date]
orders << "recommendations" if Setting["feature.user.recommendations_on_proposals"] && user&.recommended_proposals
if Setting["feature.user.recommendations_on_proposals"] && user&.recommended_proposals
orders << "recommendations"
end
orders orders
end end

View File

@@ -31,7 +31,11 @@ class ProposalNotification < ApplicationRecord
interval = Setting[:proposal_notification_minimum_interval_in_days] interval = Setting[:proposal_notification_minimum_interval_in_days]
minimum_interval = (Time.current - interval.to_i.days).to_datetime minimum_interval = (Time.current - interval.to_i.days).to_datetime
if proposal.notifications.last.created_at > minimum_interval if proposal.notifications.last.created_at > minimum_interval
errors.add(:title, I18n.t("activerecord.errors.models.proposal_notification.attributes.minimum_interval.invalid", interval: interval)) errors.add(
:title,
I18n.t("activerecord.errors.models.proposal_notification.attributes.minimum_interval.invalid",
interval: interval)
)
end end
end end

View File

@@ -11,7 +11,10 @@ class RelatedContent < ApplicationRecord
has_one :opposite_related_content, class_name: name, foreign_key: :related_content_id has_one :opposite_related_content, class_name: name, foreign_key: :related_content_id
has_many :related_content_scores, dependent: :destroy has_many :related_content_scores, dependent: :destroy
validates :parent_relationable_id, uniqueness: { scope: [:parent_relationable_type, :child_relationable_id, :child_relationable_type] } validates :parent_relationable_id,
uniqueness: {
scope: [:parent_relationable_type, :child_relationable_id, :child_relationable_type]
}
validate :different_parent_and_child validate :different_parent_and_child
after_create :create_opposite_related_content, unless: proc { opposite_related_content.present? } after_create :create_opposite_related_content, unless: proc { opposite_related_content.present? }
@@ -66,7 +69,10 @@ class RelatedContent < ApplicationRecord
def score(value, user) def score(value, user)
score_with_opposite(value, user) score_with_opposite(value, user)
hide_with_opposite if (related_content_scores.sum(:value) / related_content_scores_count) < RELATED_CONTENT_SCORE_THRESHOLD
if (related_content_scores.sum(:value) / related_content_scores_count) < RELATED_CONTENT_SCORE_THRESHOLD
hide_with_opposite
end
end end
def hide_with_opposite def hide_with_opposite

View File

@@ -28,7 +28,9 @@ class Signature < ApplicationRecord
def assign_vote_to_user def assign_vote_to_user
set_user set_user
if signable.is_a? Budget::Investment if signable.is_a? Budget::Investment
signable.vote_by(voter: user, vote: "yes") if [nil, :no_selecting_allowed].include?(signable.reason_for_not_being_selectable_by(user)) if [nil, :no_selecting_allowed].include?(signable.reason_for_not_being_selectable_by(user))
signable.vote_by(voter: user, vote: "yes")
end
else else
signable.register_vote(user, "yes") signable.register_vote(user, "yes")
end end

View File

@@ -53,10 +53,12 @@ class Verification::Management::Email
return if errors.count > 0 return if errors.count > 0
if document_number_mismatch? if document_number_mismatch?
errors.add(:email, errors.add(
I18n.t("management.email_verifications.document_mismatch", :email,
document_type: ApplicationController.helpers.humanize_document_type(user.document_type), I18n.t("management.email_verifications.document_mismatch",
document_number: user.document_number)) document_type: ApplicationController.helpers.humanize_document_type(user.document_type),
document_number: user.document_number)
)
end end
end end

View File

@@ -48,7 +48,9 @@ class Verification::Residence
end end
def document_number_uniqueness def document_number_uniqueness
errors.add(:document_number, I18n.t("errors.messages.taken")) if User.active.where(document_number: document_number).any? if User.active.where(document_number: document_number).any?
errors.add(:document_number, I18n.t("errors.messages.taken"))
end
end end
def store_failed_attempt def store_failed_attempt
@@ -74,7 +76,8 @@ class Verification::Residence
end end
def local_postal_code def local_postal_code
errors.add(:postal_code, I18n.t("verification.residence.new.error_not_allowed_postal_code")) unless valid_postal_code? errors.add(:postal_code,
I18n.t("verification.residence.new.error_not_allowed_postal_code")) unless valid_postal_code?
end end
def local_residence def local_residence

View File

@@ -4,11 +4,19 @@ xlsx_package.workbook.add_worksheet(name: "Summary") do |sheet|
link = styles.add_style(fg_color: "0000FF", u: true) link = styles.add_style(fg_color: "0000FF", u: true)
if @process.debate_phase.enabled? && @process.questions.any? if @process.debate_phase.enabled? && @process.questions.any?
sheet.add_row [t("legislation.summary.debate_phase"), t("legislation.summary.debates", count: @process.questions.count)], style: title sheet.add_row(
[
t("legislation.summary.debate_phase"),
t("legislation.summary.debates", count: @process.questions.count)
],
style: title
)
@process.questions.each do |question| @process.questions.each do |question|
sheet.add_row [question.title, t("shared.comments", count: question.comments.count)], style: link sheet.add_row [question.title, t("shared.comments", count: question.comments.count)], style: link
sheet.add_hyperlink location: legislation_process_question_url(question.process, question), ref: sheet.rows.last.cells.first sheet.add_hyperlink location: legislation_process_question_url(question.process, question),
sheet.add_hyperlink location: polymorphic_url(question, anchor: "comments"), ref: sheet.rows.last.cells.last ref: sheet.rows.last.cells.first
sheet.add_hyperlink location: polymorphic_url(question, anchor: "comments"),
ref: sheet.rows.last.cells.last
sheet.add_row [t("legislation.summary.most_voted_comments")] if question.best_comments.any? sheet.add_row [t("legislation.summary.most_voted_comments")] if question.best_comments.any?
question.best_comments.each do |comment| question.best_comments.each do |comment|
sheet.add_row [comment.body, t("legislation.summary.votes", count: comment.votes_score)] sheet.add_row [comment.body, t("legislation.summary.votes", count: comment.votes_score)]
@@ -20,22 +28,37 @@ xlsx_package.workbook.add_worksheet(name: "Summary") do |sheet|
end end
if @process.proposals_phase.enabled? && @proposals.any? if @process.proposals_phase.enabled? && @proposals.any?
sheet.add_row [t("legislation.summary.proposals_phase"), t("legislation.summary.proposals", count: @proposals.count)], style: title sheet.add_row(
[
t("legislation.summary.proposals_phase"),
t("legislation.summary.proposals", count: @proposals.count)
],
style: title
)
@proposals.sort_by_supports.each do |proposal| @proposals.sort_by_supports.each do |proposal|
sheet.add_row [proposal.title, t("legislation.summary.votes", count: proposal.votes_score)] sheet.add_row [proposal.title, t("legislation.summary.votes", count: proposal.votes_score)]
sheet.add_hyperlink location: legislation_process_proposal_url(proposal.legislation_process_id, proposal), ref: sheet.rows.last.cells.first sheet.add_hyperlink(
location: legislation_process_proposal_url(proposal.legislation_process_id, proposal),
ref: sheet.rows.last.cells.first
)
sheet.rows.last.cells.first.style = link sheet.rows.last.cells.first.style = link
end end
sheet.add_row ["", ""] sheet.add_row ["", ""]
end end
if @process.allegations_phase.enabled? && @comments.any? if @process.allegations_phase.enabled? && @comments.any?
sheet.add_row [t("legislation.summary.allegations_phase"), sheet.add_row(
t("legislation.summary.top_comments", count: @comments.count)], style: title [
t("legislation.summary.allegations_phase"),
t("legislation.summary.top_comments", count: @comments.count)
],
style: title
)
@comments.group_by(&:commentable).each do |annotation, annotation_comments| @comments.group_by(&:commentable).each do |annotation, annotation_comments|
sheet.add_row [t("legislation.annotations.index.comments_about")] sheet.add_row [t("legislation.annotations.index.comments_about")]
sheet.add_row [annotation.quote, t("shared.comments", count: annotation.comments.count)] sheet.add_row [annotation.quote, t("shared.comments", count: annotation.comments.count)]
sheet.add_hyperlink location: polymorphic_url(annotation, anchor: "comments"), ref: sheet.rows.last.cells.last sheet.add_hyperlink location: polymorphic_url(annotation, anchor: "comments"),
ref: sheet.rows.last.cells.last
sheet.rows.last.cells.last.style = link sheet.rows.last.cells.last.style = link
annotation_comments.each do |comment| annotation_comments.each do |comment|

View File

@@ -30,7 +30,8 @@ set :pty, true
set :use_sudo, false set :use_sudo, false
set :linked_files, %w[config/database.yml config/secrets.yml] set :linked_files, %w[config/database.yml config/secrets.yml]
set :linked_dirs, %w[.bundle log tmp public/system public/assets public/ckeditor_assets public/machine_learning/data storage] set :linked_dirs, %w[.bundle log tmp public/system public/assets
public/ckeditor_assets public/machine_learning/data storage]
set :keep_releases, 5 set :keep_releases, 5

View File

@@ -99,7 +99,8 @@ Apartment.configure do |config|
# #
# config.pg_excluded_names = ["uuid_generate_v4"] # config.pg_excluded_names = ["uuid_generate_v4"]
# Specifies whether the database and schema (when using PostgreSQL schemas) will prepend in ActiveRecord log. # Specifies whether the database and schema (when using PostgreSQL schemas)
# will prepend in ActiveRecord log.
# Uncomment the line below if you want to enable this behavior. # Uncomment the line below if you want to enable this behavior.
# #
# config.active_record_log = true # config.active_record_log = true
@@ -107,9 +108,9 @@ end
# Setup a custom Tenant switching middleware. The Proc should return the name of the Tenant that # Setup a custom Tenant switching middleware. The Proc should return the name of the Tenant that
# you want to switch to. # you want to switch to.
Rails.application.config.middleware.insert_before Warden::Manager, Apartment::Elevators::Generic, ->(request) do Rails.application.config.middleware.insert_before Warden::Manager,
Tenant.resolve_host(request.host) Apartment::Elevators::Generic,
end ->(request) { Tenant.resolve_host(request.host) }
# Rails.application.config.middleware.use Apartment::Elevators::Domain # Rails.application.config.middleware.use Apartment::Elevators::Domain
# Rails.application.config.middleware.use Apartment::Elevators::Subdomain # Rails.application.config.middleware.use Apartment::Elevators::Subdomain

View File

@@ -63,7 +63,11 @@ module Devise
if !new_record? && !encrypted_password_change.nil? && !erased? if !new_record? && !encrypted_password_change.nil? && !erased?
dummy = self.class.new dummy = self.class.new
dummy.encrypted_password = encrypted_password_change.first dummy.encrypted_password = encrypted_password_change.first
dummy.password_salt = password_salt_change.first if respond_to?(:password_salt_change) && !password_salt_change.nil?
if respond_to?(:password_salt_change) && !password_salt_change.nil?
dummy.password_salt = password_salt_change.first
end
errors.add(:password, :equal_to_current_password) if dummy.valid_password?(password) errors.add(:password, :equal_to_current_password) if dummy.valid_password?(password)
end end
end end

View File

@@ -253,9 +253,12 @@ namespace :admin do
end end
resources :images, only: [:index, :update, :destroy] resources :images, only: [:index, :update, :destroy]
resources :content_blocks, except: [:show] resources :content_blocks, except: [:show]
delete "/heading_content_blocks/:id", to: "content_blocks#delete_heading_content_block", as: "delete_heading_content_block" delete "/heading_content_blocks/:id", to: "content_blocks#delete_heading_content_block",
get "/edit_heading_content_blocks/:id", to: "content_blocks#edit_heading_content_block", as: "edit_heading_content_block" as: "delete_heading_content_block"
put "/update_heading_content_blocks/:id", to: "content_blocks#update_heading_content_block", as: "update_heading_content_block" get "/edit_heading_content_blocks/:id", to: "content_blocks#edit_heading_content_block",
as: "edit_heading_content_block"
put "/update_heading_content_blocks/:id", to: "content_blocks#update_heading_content_block",
as: "update_heading_content_block"
resources :information_texts, only: [:index] do resources :information_texts, only: [:index] do
post :update, on: :collection post :update, on: :collection
end end

View File

@@ -2,23 +2,28 @@ section "Creating Geozones" do
Geozone.create!(name: I18n.t("seeds.geozones.north_district"), Geozone.create!(name: I18n.t("seeds.geozones.north_district"),
external_code: "001", census_code: "01", external_code: "001", census_code: "01",
html_map_coordinates: "30,139,45,153,77,148,107,165,138,201,146,218,186,198,216," \ html_map_coordinates: "30,139,45,153,77,148,107,165,138,201,146,218,186,198,216," \
"196,233,203,240,215,283,194,329,185,377,184,388,165,369,126,333,113,334,84,320," \ "196,233,203,240,215,283,194,329,185,377,184,388,165,369," \
"66,286,73,258,65,265,57,249,47,207,58,159,84,108,85,72,101,51,114") "126,333,113,334,84,320,66,286,73,258,65,265,57,249,47," \
"207,58,159,84,108,85,72,101,51,114")
Geozone.create!(name: I18n.t("seeds.geozones.west_district"), Geozone.create!(name: I18n.t("seeds.geozones.west_district"),
external_code: "002", census_code: "02", external_code: "002", census_code: "02",
html_map_coordinates: "42,153,31,176,24,202,20,221,44,235,59,249,55,320,30,354," \ html_map_coordinates: "42,153,31,176,24,202,20,221,44,235,59,249,55,320,30,354," \
"31,372,52,396,64,432,89,453,116,432,149,419,162,412,165,377,172,357,189,352,228," \ "31,372,52,396,64,432,89,453,116,432,149,419,162,412,165," \
"327,246,313,262,297,234,291,210,284,193,284,176,294,158,303,154,310,146,289,140," \ "377,172,357,189,352,228,327,246,313,262,297,234,291,210," \
"268,138,246,135,236,139,222,151,214,136,197,120,179,99,159,85,149,65,149,56,149") "284,193,284,176,294,158,303,154,310,146,289,140,268,138," \
"246,135,236,139,222,151,214,136,197,120,179,99,159,85," \
"149,65,149,56,149")
Geozone.create!(name: I18n.t("seeds.geozones.east_district"), Geozone.create!(name: I18n.t("seeds.geozones.east_district"),
external_code: "003", census_code: "03", external_code: "003", census_code: "03",
html_map_coordinates: "175,353,162,378,161,407,153,416,167,432,184,447,225,426," \ html_map_coordinates: "175,353,162,378,161,407,153,416,167,432,184,447,225,426," \
"250,409,283,390,298,369,344,363,351,334,356,296,361,267,376,245,378,185,327,188," \ "250,409,283,390,298,369,344,363,351,334,356,296,361,267," \
"281,195,239,216,245,221,245,232,261,244,281,238,300,242,304,251,285,262,278,277," \ "376,245,378,185,327,188,281,195,239,216,245,221,245,232," \
"267,294,249,312,219,333,198,346,184,353") "261,244,281,238,300,242,304,251,285,262,278,277,267,294," \
"249,312,219,333,198,346,184,353")
Geozone.create!(name: I18n.t("seeds.geozones.central_district"), Geozone.create!(name: I18n.t("seeds.geozones.central_district"),
external_code: "004", census_code: "04", external_code: "004", census_code: "04",
html_map_coordinates: "152,308,137,258,133,235,147,216,152,214,186,194,210,196," \ html_map_coordinates: "152,308,137,258,133,235,147,216,152,214,186,194,210,196," \
"228,202,240,216,241,232,263,243,293,241,301,245,302,254,286,265,274,278,267,296," \ "228,202,240,216,241,232,263,243,293,241,301,245,302,254," \
"243,293,226,289,209,285,195,283,177,297") "286,265,274,278,267,296,243,293,226,289,209,285,195,283," \
"177,297")
end end

View File

@@ -10,6 +10,7 @@ class CreateInappropiateFlags < ActiveRecord::Migration[4.2]
end end
add_index :inappropiate_flags, [:flaggable_type, :flaggable_id] add_index :inappropiate_flags, [:flaggable_type, :flaggable_id]
add_index :inappropiate_flags, [:user_id, :flaggable_type, :flaggable_id], name: "access_inappropiate_flags" add_index :inappropiate_flags, [:user_id, :flaggable_type, :flaggable_id],
name: "access_inappropiate_flags"
end end
end end

View File

@@ -1,12 +1,19 @@
class CreateRelatedContent < ActiveRecord::Migration[4.2] class CreateRelatedContent < ActiveRecord::Migration[4.2]
def change def change
create_table :related_contents do |t| create_table :related_contents do |t|
t.references :parent_relationable, polymorphic: true, index: { name: "index_related_contents_on_parent_relationable" } t.references :parent_relationable, polymorphic: true,
t.references :child_relationable, polymorphic: true, index: { name: "index_related_contents_on_child_relationable" } index: { name: "index_related_contents_on_parent_relationable" }
t.references :child_relationable, polymorphic: true,
index: { name: "index_related_contents_on_child_relationable" }
t.references :related_content, index: { name: "opposite_related_content" } t.references :related_content, index: { name: "opposite_related_content" }
t.timestamps t.timestamps
end end
add_index :related_contents, [:parent_relationable_id, :parent_relationable_type, :child_relationable_id, :child_relationable_type], name: "unique_parent_child_related_content", unique: true, using: :btree add_index :related_contents,
[:parent_relationable_id, :parent_relationable_type,
:child_relationable_id, :child_relationable_type],
name: "unique_parent_child_related_content",
unique: true,
using: :btree
end end
end end

View File

@@ -6,6 +6,10 @@ class CreateRelatedContentScores < ActiveRecord::Migration[4.2]
t.integer :value t.integer :value
end end
add_index :related_content_scores, [:user_id, :related_content_id], name: "unique_user_related_content_scoring", unique: true, using: :btree add_index :related_content_scores,
[:user_id, :related_content_id],
name: "unique_user_related_content_scoring",
unique: true,
using: :btree
end end
end end

View File

@@ -1,6 +1,8 @@
class RenameAdministratorTaskToDashboardAdministratorTask < ActiveRecord::Migration[4.2] class RenameAdministratorTaskToDashboardAdministratorTask < ActiveRecord::Migration[4.2]
def change def change
rename_index :administrator_tasks, "index_administrator_tasks_on_source_type_and_source_id", "index_dashboard_administrator_tasks_on_source" rename_index :administrator_tasks,
"index_administrator_tasks_on_source_type_and_source_id",
"index_dashboard_administrator_tasks_on_source"
rename_table :administrator_tasks, :dashboard_administrator_tasks rename_table :administrator_tasks, :dashboard_administrator_tasks
end end
end end

View File

@@ -29,6 +29,9 @@ class CreateLegislationPeopleProposalsTable < ActiveRecord::Migration[4.2]
t.boolean "validated" t.boolean "validated"
t.integer "cached_votes_score", default: 0 t.integer "cached_votes_score", default: 0
end end
add_index "legislation_people_proposals", ["cached_votes_score"], name: "index_legislation_people_proposals_on_cached_votes_score", using: :btree add_index "legislation_people_proposals",
["cached_votes_score"],
name: "index_legislation_people_proposals_on_cached_votes_score",
using: :btree
end end
end end

View File

@@ -4,7 +4,9 @@ class CreateSDGRelations < ActiveRecord::Migration[5.2]
t.references :related_sdg, polymorphic: true t.references :related_sdg, polymorphic: true
t.references :relatable, polymorphic: true t.references :relatable, polymorphic: true
t.index [:related_sdg_id, :related_sdg_type, :relatable_id, :relatable_type], name: "sdg_relations_unique", unique: true t.index [:related_sdg_id, :related_sdg_type, :relatable_id, :relatable_type],
name: "sdg_relations_unique",
unique: true
t.timestamps t.timestamps
end end

View File

@@ -20,7 +20,9 @@ class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
t.datetime :created_at, null: false t.datetime :created_at, null: false
t.index [:record_type, :record_id, :name, :blob_id], name: "index_active_storage_attachments_uniqueness", unique: true t.index [:record_type, :record_id, :name, :blob_id],
name: "index_active_storage_attachments_uniqueness",
unique: true
t.foreign_key :active_storage_blobs, column: :blob_id t.foreign_key :active_storage_blobs, column: :blob_id
end end
end end

View File

@@ -1,6 +1,10 @@
class ManagerAuthenticator class ManagerAuthenticator
def initialize(data = {}) def initialize(data = {})
@manager = { login: data[:login], user_key: data[:clave_usuario], date: data[:fecha_conexion] }.with_indifferent_access @manager = {
login: data[:login],
user_key: data[:clave_usuario],
date: data[:fecha_conexion]
}.with_indifferent_access
end end
def auth def auth
@@ -13,7 +17,11 @@ class ManagerAuthenticator
private private
def manager_exists? def manager_exists?
response = client.call(:get_status_user_data, message: { ub: { user_key: @manager[:user_key], date: @manager[:date] }}).body response = client.call(
:get_status_user_data,
message: { ub: { user_key: @manager[:user_key], date: @manager[:date] }}
).body
parsed_response = parser.parse((response[:get_status_user_data_response][:get_status_user_data_return])) parsed_response = parser.parse((response[:get_status_user_data_response][:get_status_user_data_return]))
@manager[:login] == parsed_response["USUARIO"]["LOGIN"] @manager[:login] == parsed_response["USUARIO"]["LOGIN"]
rescue rescue
@@ -21,13 +29,17 @@ class ManagerAuthenticator
end end
def application_authorized? def application_authorized?
response = client.call(:get_applications_user_list, message: { ub: { user_key: @manager[:user_key] }}).body response = client.call(
:get_applications_user_list,
message: { ub: { user_key: @manager[:user_key] }}
).body
user_list_return = response[:get_applications_user_list_response][:get_applications_user_list_return] user_list_return = response[:get_applications_user_list_response][:get_applications_user_list_return]
parsed_response = parser.parse(user_list_return) parsed_response = parser.parse(user_list_return)
aplication_value = parsed_response["APLICACIONES"]["APLICACION"] aplication_value = parsed_response["APLICACIONES"]["APLICACION"]
# aplication_value from UWEB can be an array of hashes or a hash # aplication_value from UWEB can be an array of hashes or a hash
aplication_value.include?("CLAVE_APLICACION" => application_key) || aplication_value["CLAVE_APLICACION"] == application_key aplication_value.include?("CLAVE_APLICACION" => application_key) ||
aplication_value["CLAVE_APLICACION"] == application_key
rescue rescue
false false
end end

View File

@@ -11,7 +11,8 @@ describe Account::PermissionsListComponent do
it "adds a hint when an action cannot be performed" do it "adds a hint when an action cannot be performed" do
render_inline Account::PermissionsListComponent.new(User.new) render_inline Account::PermissionsListComponent.new(User.new)
expect(page).to have_css "li", exact_text: "Additional verification needed Support proposals", normalize_ws: true expect(page).to have_css "li", exact_text: "Additional verification needed Support proposals",
normalize_ws: true
expect(page).to have_css "li", exact_text: "Participate in debates", normalize_ws: true expect(page).to have_css "li", exact_text: "Participate in debates", normalize_ws: true
end end
end end

View File

@@ -26,7 +26,8 @@ describe Admin::BudgetHeadings::FormComponent do
render_inline component render_inline component
expect(page).to have_select "Scope of operation", options: ["All city", "Under the sea", "Above the skies"] expect(page).to have_select "Scope of operation",
options: ["All city", "Under the sea", "Above the skies"]
end end
end end
end end

View File

@@ -6,7 +6,9 @@ describe Admin::Geozones::IndexComponent, :admin do
geozones = [ geozones = [
create(:geozone, :with_geojson, name: "GeoJSON", external_code: "1", census_code: "2"), create(:geozone, :with_geojson, name: "GeoJSON", external_code: "1", census_code: "2"),
create(:geozone, :with_html_coordinates, name: "HTML", external_code: "3", census_code: "4"), create(:geozone, :with_html_coordinates, name: "HTML", external_code: "3", census_code: "4"),
create(:geozone, :with_geojson, :with_html_coordinates, name: "With both", external_code: "6", census_code: "7"), create(:geozone, :with_geojson, :with_html_coordinates, name: "With both",
external_code: "6",
census_code: "7"),
create(:geozone, name: "With none", external_code: "8", census_code: "9") create(:geozone, name: "With none", external_code: "8", census_code: "9")
] ]

View File

@@ -1,6 +1,7 @@
require "rails_helper" require "rails_helper"
describe Admin::SiteCustomization::Pages::IndexComponent, controller: Admin::SiteCustomization::PagesController do describe Admin::SiteCustomization::Pages::IndexComponent,
controller: Admin::SiteCustomization::PagesController do
before { SiteCustomization::Page.delete_all } before { SiteCustomization::Page.delete_all }
it "shows date in created_at and updated_at fields" do it "shows date in created_at and updated_at fields" do

View File

@@ -32,7 +32,8 @@ describe Budgets::BudgetComponent do
render_inline Budgets::BudgetComponent.new(budget) render_inline Budgets::BudgetComponent.new(budget)
page.find(".budget-header") do |header| page.find(".budget-header") do |header|
expect(header).to have_link "Participate now!", href: "https://consuldemocracy.org", class: "main-link" expect(header).to have_link "Participate now!", href: "https://consuldemocracy.org",
class: "main-link"
end end
end end
end end

View File

@@ -68,7 +68,8 @@ describe SDG::RelatedListSelectorComponent do
expect(page.find_field("Goals and Targets")["data-suggestions-list"]).to eq([{ expect(page.find_field("Goals and Targets")["data-suggestions-list"]).to eq([{
tag: "1.1. Eradicate Extreme Poverty", tag: "1.1. Eradicate Extreme Poverty",
display_text: "1.1", display_text: "1.1",
title: "By 2030, eradicate extreme poverty for all people everywhere, currently measured as people living on less than $1.25 a day", title: "By 2030, eradicate extreme poverty for all people everywhere, " \
"currently measured as people living on less than $1.25 a day",
value: "1.1" value: "1.1"
}].to_json) }].to_json)
end end

View File

@@ -10,7 +10,8 @@ describe DocumentsController do
document = create(:document, documentable: current_answer) document = create(:document, documentable: current_answer)
delete :destroy, params: { id: document } delete :destroy, params: { id: document }
expect(flash[:alert]).to eq "You do not have permission to carry out the action 'destroy' on Document." expect(flash[:alert]).to eq "You do not have permission to " \
"carry out the action 'destroy' on Document."
expect(Document.count).to eq 1 expect(Document.count).to eq 1
end end

View File

@@ -30,7 +30,8 @@ describe Moderation::UsersController do
put :block, params: { id: user } put :block, params: { id: user }
expect(response).to redirect_to proposals_path expect(response).to redirect_to proposals_path
expect(flash[:notice]).to eq "The user has been blocked. All contents authored by this user have been hidden." expect(flash[:notice]).to eq "The user has been blocked. " \
"All contents authored by this user have been hidden."
end end
it "redirects to the index with a nested resource" do it "redirects to the index with a nested resource" do

View File

@@ -19,7 +19,9 @@ FactoryBot.define do
end end
trait :with_geojson do trait :with_geojson do
geojson { '{ "geometry": { "type": "Polygon", "coordinates": [[-0.117,51.513],[-0.118,51.512],[-0.119,51.514]] } }' } geojson do
'{ "geometry": { "type": "Polygon", "coordinates": [[0.117,51.513],[0.118,51.512],[0.119,51.514]] } }'
end
end end
end end

View File

@@ -14,7 +14,8 @@ describe SignatureSheetsHelper do
Setting["remote_census.request.postal_code"] = nil Setting["remote_census.request.postal_code"] = nil
text_help_1 = "To verify a user, your application needs: Document number" text_help_1 = "To verify a user, your application needs: Document number"
text_help_2 = "Required fields for each user must be separated by commas and each user must be separated by semicolons." text_help_2 = "Required fields for each user must be separated by commas " \
"and each user must be separated by semicolons."
text_example = "Example: 12345678Z; 87654321Y" text_example = "Example: 12345678Z; 87654321Y"
expect(required_fields_to_verify_text_help).to include(text_help_1) expect(required_fields_to_verify_text_help).to include(text_help_1)
@@ -25,8 +26,10 @@ describe SignatureSheetsHelper do
it "returns text help when date_of_birth is required" do it "returns text help when date_of_birth is required" do
Setting["remote_census.request.postal_code"] = nil Setting["remote_census.request.postal_code"] = nil
text_help_1 = "To verify a user, your application needs: Document number, Day of birth (dd/mm/yyyy)" text_help_1 = "To verify a user, your application needs: " \
text_help_2 = "Required fields for each user must be separated by commas and each user must be separated by semicolons." "Document number, Day of birth (dd/mm/yyyy)"
text_help_2 = "Required fields for each user must be separated by commas " \
"and each user must be separated by semicolons."
text_example = "Example: 12345678Z, 01/01/1980; 87654321Y, 01/02/1990" text_example = "Example: 12345678Z, 01/01/1980; 87654321Y, 01/02/1990"
expect(required_fields_to_verify_text_help).to include(text_help_1) expect(required_fields_to_verify_text_help).to include(text_help_1)
@@ -37,8 +40,10 @@ describe SignatureSheetsHelper do
it "returns text help when postal_code is required" do it "returns text help when postal_code is required" do
Setting["remote_census.request.date_of_birth"] = nil Setting["remote_census.request.date_of_birth"] = nil
text_help_1 = "To verify a user, your application needs: Document number and Postal Code" text_help_1 = "To verify a user, your application needs: " \
text_help_2 = "Required fields for each user must be separated by commas and each user must be separated by semicolons." "Document number and Postal Code"
text_help_2 = "Required fields for each user must be separated by commas " \
"and each user must be separated by semicolons."
text_example = "Example: 12345678Z, 28001; 87654321Y, 28002" text_example = "Example: 12345678Z, 28001; 87654321Y, 28002"
expect(required_fields_to_verify_text_help).to include(text_help_1) expect(required_fields_to_verify_text_help).to include(text_help_1)
@@ -47,8 +52,10 @@ describe SignatureSheetsHelper do
end end
it "returns text help when date_of_birth and postal_code are required" do it "returns text help when date_of_birth and postal_code are required" do
text_help_1 = "To verify a user, your application needs: Document number, Day of birth (dd/mm/yyyy) and Postal Code" text_help_1 = "To verify a user, your application needs: " \
text_help_2 = "Required fields for each user must be separated by commas and each user must be separated by semicolons." "Document number, Day of birth (dd/mm/yyyy) and Postal Code"
text_help_2 = "Required fields for each user must be separated by commas " \
"and each user must be separated by semicolons."
text_example = "Example: 12345678Z, 01/01/1980, 28001; 87654321Y, 01/02/1990, 28002" text_example = "Example: 12345678Z, 01/01/1980, 28001; 87654321Y, 01/02/1990, 28002"
expect(required_fields_to_verify_text_help).to include(text_help_1) expect(required_fields_to_verify_text_help).to include(text_help_1)

View File

@@ -16,8 +16,10 @@ describe UsersHelper do
debate.hide debate.hide
expect(comment_commentable_title(comment)).to eq("<del>" + comment.commentable.title + expect(comment_commentable_title(comment)).to eq "<del>#{comment.commentable.title}</del> " \
'</del> <span class="small">(This debate has been deleted)</span>') '<span class="small">' \
"(This debate has been deleted)" \
"</span>"
end end
it "returns the appropriate message for deleted proposals" do it "returns the appropriate message for deleted proposals" do
@@ -26,8 +28,10 @@ describe UsersHelper do
proposal.hide proposal.hide
expect(comment_commentable_title(comment)).to eq("<del>" + comment.commentable.title + expect(comment_commentable_title(comment)).to eq "<del>#{comment.commentable.title}</del> " \
'</del> <span class="small">(This proposal has been deleted)</span>') '<span class="small">' \
"(This proposal has been deleted)" \
"</span>"
end end
it "returns the appropriate message for deleted budget investment" do it "returns the appropriate message for deleted budget investment" do
@@ -36,8 +40,10 @@ describe UsersHelper do
investment.hide investment.hide
expect(comment_commentable_title(comment)).to eq("<del>" + comment.commentable.title + expect(comment_commentable_title(comment)).to eq "<del>#{comment.commentable.title}</del> " \
'</del> <span class="small">(This investment project has been deleted)</span>') '<span class="small">' \
"(This investment project has been deleted)" \
"</span>"
end end
end end
@@ -50,8 +56,10 @@ describe UsersHelper do
it "returns a hint if the commentable has been deleted" do it "returns a hint if the commentable has been deleted" do
comment = create(:comment) comment = create(:comment)
comment.commentable.hide comment.commentable.hide
expect(comment_commentable_title(comment)).to eq("<del>" + comment.commentable.title + expect(comment_commentable_title(comment)).to eq "<del>#{comment.commentable.title}</del> " \
'</del> <span class="small">(This debate has been deleted)</span>') '<span class="small">' \
"(This debate has been deleted)" \
"</span>"
end end
end end
end end

View File

@@ -7,13 +7,13 @@ describe "I18n" do
let(:unused_keys) { i18n.unused_keys } let(:unused_keys) { i18n.unused_keys }
it "does not have missing keys" do it "does not have missing keys" do
expect(missing_keys).to be_empty, expect(missing_keys).to be_empty, "Missing #{missing_keys.leaves.count} i18n keys, " \
"Missing #{missing_keys.leaves.count} i18n keys, run `i18n-tasks missing' to show them" "run `i18n-tasks missing' to show them"
end end
it "does not have unused keys" do it "does not have unused keys" do
expect(unused_keys).to be_empty, expect(unused_keys).to be_empty, "#{unused_keys.leaves.count} unused i18n keys, " \
"#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them" "run `i18n-tasks unused' to show them"
end end
context "Plurals" do context "Plurals" do

View File

@@ -21,12 +21,16 @@ describe DocumentParser do
end end
it "tries all the dni variants padding with zeroes" do it "tries all the dni variants padding with zeroes" do
expect(DocumentParser.get_document_number_variants(1, "0123456")).to eq(["123456", "0123456", "00123456"]) expect(DocumentParser.get_document_number_variants(1, "0123456"))
expect(DocumentParser.get_document_number_variants(1, "00123456")).to eq(["123456", "0123456", "00123456"]) .to eq(["123456", "0123456", "00123456"])
expect(DocumentParser.get_document_number_variants(1, "00123456"))
.to eq(["123456", "0123456", "00123456"])
end end
it "adds upper and lowercase letter when the letter is present" do it "adds upper and lowercase letter when the letter is present" do
expect(DocumentParser.get_document_number_variants(1, "1234567A")).to eq(%w[1234567 01234567 1234567a 1234567A 01234567a 01234567A]) expect(DocumentParser.get_document_number_variants(1, "1234567A"))
.to eq(%w[1234567 01234567 1234567a 1234567A 01234567a 01234567A])
end end
end end
end end

View File

@@ -185,7 +185,8 @@ describe "Consul Schema" do
it "returns nested votes for a proposal" do it "returns nested votes for a proposal" do
proposal = create(:proposal, voters: [create(:user), create(:user)]) proposal = create(:proposal, voters: [create(:user), create(:user)])
response = execute("{ proposal(id: #{proposal.id}) { votes_for { edges { node { public_created_at } } } } }") response = execute("{ proposal(id: #{proposal.id}) " \
"{ votes_for { edges { node { public_created_at } } } } }")
votes = response["data"]["proposal"]["votes_for"]["edges"] votes = response["data"]["proposal"]["votes_for"]["edges"]
expect(votes.count).to eq(2) expect(votes.count).to eq(2)

View File

@@ -1,21 +1,38 @@
require "rails_helper" require "rails_helper"
describe ManagerAuthenticator do describe ManagerAuthenticator do
let(:authenticator) { ManagerAuthenticator.new(login: "JJB033", clave_usuario: "31415926", fecha_conexion: "20151031135905") } let(:authenticator) do
ManagerAuthenticator.new(login: "JJB033", clave_usuario: "31415926", fecha_conexion: "20151031135905")
end
describe "initialization params" do describe "initialization params" do
it "causes auth to return false if blank login" do it "causes auth to return false if blank login" do
blank_login_authenticator = ManagerAuthenticator.new(login: "", clave_usuario: "31415926", fecha_conexion: "20151031135905") blank_login_authenticator = ManagerAuthenticator.new(
login: "",
clave_usuario: "31415926",
fecha_conexion: "20151031135905"
)
expect(blank_login_authenticator.auth).to be false expect(blank_login_authenticator.auth).to be false
end end
it "causes auth to return false if blank user_key" do it "causes auth to return false if blank user_key" do
blank_user_key_authenticator = ManagerAuthenticator.new(login: "JJB033", clave_usuario: "", fecha_conexion: "20151031135905") blank_user_key_authenticator = ManagerAuthenticator.new(
login: "JJB033",
clave_usuario: "",
fecha_conexion: "20151031135905"
)
expect(blank_user_key_authenticator.auth).to be false expect(blank_user_key_authenticator.auth).to be false
end end
it "causes auth to return false if blank date" do it "causes auth to return false if blank date" do
blank_date_authenticator = ManagerAuthenticator.new(login: "JJB033", clave_usuario: "31415926", fecha_conexion: "") blank_date_authenticator = ManagerAuthenticator.new(
login: "JJB033",
clave_usuario: "31415926",
fecha_conexion: ""
)
expect(blank_date_authenticator.auth).to be false expect(blank_date_authenticator.auth).to be false
end end
end end
@@ -53,7 +70,8 @@ describe ManagerAuthenticator do
it "calls the permissions check method" do it "calls the permissions check method" do
allow(authenticator).to receive(:manager_exists?).and_return(true) allow(authenticator).to receive(:manager_exists?).and_return(true)
allow(authenticator.send(:client)).to receive(:call).with(:get_applications_user_list, message: { ub: { user_key: "31415926" }}) allow(authenticator.send(:client)).to receive(:call).with(:get_applications_user_list,
message: { ub: { user_key: "31415926" }})
authenticator.auth authenticator.auth
end end
end end

View File

@@ -80,14 +80,16 @@ describe RemoteTranslations::Microsoft::Client do
response_another_start_text = [another_start_translated_text_es] response_another_start_text = [another_start_translated_text_es]
response_another_end_text = [another_end_translated_text_es] response_another_end_text = [another_end_translated_text_es]
expect_any_instance_of(BingTranslator).to receive(:translate_array).with([start_another_text_en], to: :es) expect_any_instance_of(BingTranslator).to(receive(:translate_array)
.exactly(1) .with([start_another_text_en], to: :es)
.times .exactly(1)
.and_return(response_another_start_text) .times
expect_any_instance_of(BingTranslator).to receive(:translate_array).with([end_another_text_en], to: :es) .and_return(response_another_start_text))
.exactly(1) expect_any_instance_of(BingTranslator).to(receive(:translate_array)
.times .with([end_another_text_en], to: :es)
.and_return(response_another_end_text) .exactly(1)
.times
.and_return(response_another_end_text))
result = client.call([text_en, another_text_en], :es) result = client.call([text_en, another_text_en], :es)

View File

@@ -95,7 +95,11 @@ describe Abilities::Administrator do
it { should be_able_to(:read_results, create(:budget, :reviewing_ballots, :with_winner)) } it { should be_able_to(:read_results, create(:budget, :reviewing_ballots, :with_winner)) }
it { should be_able_to(:read_results, create(:budget, :finished, :with_winner)) } it { should be_able_to(:read_results, create(:budget, :finished, :with_winner)) }
it { should be_able_to(:read_results, create(:budget, :finished, results_enabled: true)) } it { should be_able_to(:read_results, create(:budget, :finished, results_enabled: true)) }
it { should_not be_able_to(:read_results, create(:budget, :balloting, :with_winner, results_enabled: true)) }
it do
should_not be_able_to(:read_results, create(:budget, :balloting, :with_winner, results_enabled: true))
end
it { should_not be_able_to(:read_results, create(:budget, :reviewing_ballots, results_enabled: true)) } it { should_not be_able_to(:read_results, create(:budget, :reviewing_ballots, results_enabled: true)) }
it { should_not be_able_to(:read_results, create(:budget, :finished, results_enabled: false)) } it { should_not be_able_to(:read_results, create(:budget, :finished, results_enabled: false)) }

View File

@@ -25,10 +25,18 @@ describe Abilities::Common do
let(:investment_in_reviewing_budget) { create(:budget_investment, budget: reviewing_budget) } let(:investment_in_reviewing_budget) { create(:budget_investment, budget: reviewing_budget) }
let(:investment_in_selecting_budget) { create(:budget_investment, budget: selecting_budget) } let(:investment_in_selecting_budget) { create(:budget_investment, budget: selecting_budget) }
let(:investment_in_balloting_budget) { create(:budget_investment, budget: balloting_budget) } let(:investment_in_balloting_budget) { create(:budget_investment, budget: balloting_budget) }
let(:own_investment_in_accepting_budget) { create(:budget_investment, budget: accepting_budget, author: user) } let(:own_investment_in_accepting_budget) do
let(:own_investment_in_reviewing_budget) { create(:budget_investment, budget: reviewing_budget, author: user) } create(:budget_investment, budget: accepting_budget, author: user)
let(:own_investment_in_selecting_budget) { create(:budget_investment, budget: selecting_budget, author: user) } end
let(:own_investment_in_balloting_budget) { create(:budget_investment, budget: balloting_budget, author: user) } let(:own_investment_in_reviewing_budget) do
create(:budget_investment, budget: reviewing_budget, author: user)
end
let(:own_investment_in_selecting_budget) do
create(:budget_investment, budget: selecting_budget, author: user)
end
let(:own_investment_in_balloting_budget) do
create(:budget_investment, budget: balloting_budget, author: user)
end
let(:ballot_in_accepting_budget) { create(:budget_ballot, budget: accepting_budget) } let(:ballot_in_accepting_budget) { create(:budget_ballot, budget: accepting_budget) }
let(:ballot_in_selecting_budget) { create(:budget_ballot, budget: selecting_budget) } let(:ballot_in_selecting_budget) { create(:budget_ballot, budget: selecting_budget) }
let(:ballot_in_balloting_budget) { create(:budget_ballot, budget: balloting_budget) } let(:ballot_in_balloting_budget) { create(:budget_ballot, budget: balloting_budget) }
@@ -45,9 +53,13 @@ describe Abilities::Common do
let(:poll_question_from_other_geozone) { create(:poll_question, poll: poll_from_other_geozone) } let(:poll_question_from_other_geozone) { create(:poll_question, poll: poll_from_other_geozone) }
let(:poll_question_from_all_geozones) { create(:poll_question, poll: poll) } let(:poll_question_from_all_geozones) { create(:poll_question, poll: poll) }
let(:expired_poll_question_from_own_geozone) { create(:poll_question, poll: expired_poll_from_own_geozone) } let(:expired_poll_question_from_own_geozone) do
let(:expired_poll_question_from_other_geozone) { create(:poll_question, poll: expired_poll_from_other_geozone) } create(:poll_question, poll: expired_poll_from_own_geozone)
let(:expired_poll_question_from_all_geozones) { create(:poll_question, poll: expired_poll) } end
let(:expired_poll_question_from_other_geozone) do
create(:poll_question, poll: expired_poll_from_other_geozone)
end
let(:expired_poll_question_from_all_geozones) { create(:poll_question, poll: expired_poll) }
let(:own_proposal_document) { build(:document, documentable: own_proposal) } let(:own_proposal_document) { build(:document, documentable: own_proposal) }
let(:proposal_document) { build(:document, documentable: proposal) } let(:proposal_document) { build(:document, documentable: proposal) }

View File

@@ -8,9 +8,15 @@ describe Abilities::Valuator do
let(:group) { create(:valuator_group) } let(:group) { create(:valuator_group) }
let(:valuator) { create(:valuator, valuator_group: group, can_edit_dossier: true, can_comment: true) } let(:valuator) { create(:valuator, valuator_group: group, can_edit_dossier: true, can_comment: true) }
let(:non_assigned_investment) { create(:budget_investment) } let(:non_assigned_investment) { create(:budget_investment) }
let(:assigned_investment) { create(:budget_investment, budget: create(:budget, :valuating), valuators: [valuator]) } let(:assigned_investment) do
let(:group_assigned_investment) { create(:budget_investment, budget: create(:budget, :valuating), valuator_groups: [group]) } create(:budget_investment, budget: create(:budget, :valuating), valuators: [valuator])
let(:finished_assigned_investment) { create(:budget_investment, budget: create(:budget, :finished), valuators: [valuator]) } end
let(:group_assigned_investment) do
create(:budget_investment, budget: create(:budget, :valuating), valuator_groups: [group])
end
let(:finished_assigned_investment) do
create(:budget_investment, budget: create(:budget, :finished), valuators: [valuator])
end
it "cannot valuate an assigned investment with a finished valuation" do it "cannot valuate an assigned investment with a finished valuation" do
assigned_investment.update!(valuation_finished: true) assigned_investment.update!(valuation_finished: true)

View File

@@ -30,7 +30,9 @@ describe Ahoy::DataSource do
ds = Ahoy::DataSource.new ds = Ahoy::DataSource.new
ds.add "foo", Ahoy::Event.where(name: "foo").group_by_day(:time).count ds.add "foo", Ahoy::Event.where(name: "foo").group_by_day(:time).count
ds.add "bar", Ahoy::Event.where(name: "bar").group_by_day(:time).count ds.add "bar", Ahoy::Event.where(name: "bar").group_by_day(:time).count
expect(ds.build).to eq :x => ["2015-01-01", "2015-01-02", "2015-01-03"], "foo" => [2, 1, 0], "bar" => [1, 0, 2] expect(ds.build).to eq :x => ["2015-01-01", "2015-01-02", "2015-01-03"],
"foo" => [2, 1, 0],
"bar" => [1, 0, 2]
end end
end end
end end

View File

@@ -714,7 +714,8 @@ describe Budget::Investment do
unselected_undecided_investment = create(:budget_investment, :unselected, :undecided) unselected_undecided_investment = create(:budget_investment, :unselected, :undecided)
unselected_feasible_investment = create(:budget_investment, :unselected, :feasible) unselected_feasible_investment = create(:budget_investment, :unselected, :feasible)
expect(Budget::Investment.unselected).to match_array [unselected_undecided_investment, unselected_feasible_investment] expect(Budget::Investment.unselected).to match_array [unselected_undecided_investment,
unselected_feasible_investment]
end end
it "does not return selected investments" do it "does not return selected investments" do
@@ -732,8 +733,17 @@ describe Budget::Investment do
describe "sort_by_title" do describe "sort_by_title" do
it "sorts using the title in the current locale" do it "sorts using the title in the current locale" do
create(:budget_investment, title_en: "CCCC", title_es: "BBBB", description_en: "CCCC", description_es: "BBBB") create(:budget_investment,
create(:budget_investment, title_en: "DDDD", title_es: "AAAA", description_en: "DDDD", description_es: "AAAA") title_en: "CCCC",
title_es: "BBBB",
description_en: "CCCC",
description_es: "BBBB")
create(:budget_investment,
title_en: "DDDD",
title_es: "AAAA",
description_en: "DDDD",
description_es: "AAAA")
expect(Budget::Investment.sort_by_title.map(&:title)).to eq %w[CCCC DDDD] expect(Budget::Investment.sort_by_title.map(&:title)).to eq %w[CCCC DDDD]
end end

View File

@@ -44,7 +44,9 @@ describe Budget::Result do
it "removes winners and recalculates" do it "removes winners and recalculates" do
create(:budget_investment, :selected, heading: heading, price: 200, ballot_lines_count: 90) create(:budget_investment, :selected, heading: heading, price: 200, ballot_lines_count: 90)
create(:budget_investment, :winner, heading: heading, price: 300, ballot_lines_count: 80) create(:budget_investment, :winner, heading: heading, price: 300, ballot_lines_count: 80)
create(:budget_investment, :winner, :incompatible, heading: heading, price: 500, ballot_lines_count: 70) create(:budget_investment, :winner, :incompatible, heading: heading,
price: 500,
ballot_lines_count: 70)
create(:budget_investment, :winner, heading: heading, price: 500, ballot_lines_count: 60) create(:budget_investment, :winner, heading: heading, price: 500, ballot_lines_count: 60)
create(:budget_investment, :winner, heading: heading, price: 100, ballot_lines_count: 50) create(:budget_investment, :winner, heading: heading, price: 100, ballot_lines_count: 50)

View File

@@ -76,8 +76,9 @@ describe Budget::Stats do
end end
it "doesn't count nil user ids" do it "doesn't count nil user ids" do
create(:budget_ballot_line, investment: investment, create(:budget_ballot_line,
ballot: create(:budget_ballot, budget: budget.reload, user: nil, physical: true)) investment: investment,
ballot: create(:budget_ballot, budget: budget.reload, user: nil, physical: true))
expect(stats.total_participants_vote_phase).to be 0 expect(stats.total_participants_vote_phase).to be 0
end end

View File

@@ -62,12 +62,14 @@ describe Debate do
describe "#tag_list" do describe "#tag_list" do
it "is not valid with a tag list of more than 6 elements" do it "is not valid with a tag list of more than 6 elements" do
debate.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción", "Fiestas populares", "Prensa", "Huelgas"] debate.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción",
"Fiestas populares", "Prensa", "Huelgas"]
expect(debate).not_to be_valid expect(debate).not_to be_valid
end end
it "is valid with a tag list of 6 elements" do it "is valid with a tag list of 6 elements" do
debate.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción", "Fiestas populares", "Prensa"] debate.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción",
"Fiestas populares", "Prensa"]
expect(debate).to be_valid expect(debate).to be_valid
end end
end end
@@ -314,7 +316,9 @@ describe Debate do
describe "#confidence_score" do describe "#confidence_score" do
it "takes into account percentage of total votes and total_positive and total negative votes" do it "takes into account percentage of total votes and total_positive and total negative votes" do
debate = create(:debate, :with_confidence_score, cached_votes_up: 100, cached_votes_score: 100, cached_votes_total: 100) debate = create(:debate, :with_confidence_score, cached_votes_up: 100,
cached_votes_score: 100,
cached_votes_total: 100)
expect(debate.confidence_score).to eq(10000) expect(debate.confidence_score).to eq(10000)
debate = create(:debate, :with_confidence_score, cached_votes_up: 0, cached_votes_total: 100) debate = create(:debate, :with_confidence_score, cached_votes_up: 0, cached_votes_total: 100)

View File

@@ -10,10 +10,25 @@ describe DirectUpload do
end end
it "is not valid for different kind of combinations with invalid atttachment content types" do it "is not valid for different kind of combinations with invalid atttachment content types" do
expect(build(:direct_upload, :proposal, :documents, attachment: fixture_file_upload("clippy.png"))).not_to be_valid expect(build(:direct_upload,
expect(build(:direct_upload, :proposal, :image, attachment: fixture_file_upload("empty.pdf"))).not_to be_valid :proposal,
expect(build(:direct_upload, :budget_investment, :documents, attachment: fixture_file_upload("clippy.png"))).not_to be_valid :documents,
expect(build(:direct_upload, :budget_investment, :image, attachment: fixture_file_upload("empty.pdf"))).not_to be_valid attachment: fixture_file_upload("clippy.png"))).not_to be_valid
expect(build(:direct_upload,
:proposal,
:image,
attachment: fixture_file_upload("empty.pdf"))).not_to be_valid
expect(build(:direct_upload,
:budget_investment,
:documents,
attachment: fixture_file_upload("clippy.png"))).not_to be_valid
expect(build(:direct_upload,
:budget_investment,
:image,
attachment: fixture_file_upload("empty.pdf"))).not_to be_valid
end end
it "is not valid without resource_type" do it "is not valid without resource_type" do

View File

@@ -10,16 +10,19 @@ RSpec.describe Legislation::Annotation, type: :model do
end end
it "calculates the context for multinode annotations" do it "calculates the context for multinode annotations" do
quote = "ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam" \ quote = "ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh " \
" erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex" \ "euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi " \
" ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum" \ "enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit " \
" dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril" \ "lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum " \
" delenit augue duis dolore te feugait nulla facilisi." \ "iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel " \
"\n\n" \ "illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto " \
"Expetenda tincidunt in sed, ex partem placerat sea, porro commodo ex eam. His putant aeterno interesset at. Usu ea mundi" \ "odio dignissim qui blandit praesent luptatum zzril delenit augue duis " \
" tincidunt, omnium virtute aliquando ius ex. Ea aperiri sententiae duo. Usu nullam dolorum quaestio ei, sit vidit facilisis" \ "dolore te feugait nulla facilisi.\n\n" \
" ea. Per ne impedit iracundia neglegentur. Consetetur neglegentur eum ut, vis animal legimus inimicus id." \ "Expetenda tincidunt in sed, ex partem placerat sea, porro commodo ex eam. " \
"\n\n" \ "His putant aeterno interesset at. Usu ea mundi tincidunt, omnium virtute " \
"aliquando ius ex. Ea aperiri sententiae duo. Usu nullam dolorum quaestio " \
"ei, sit vidit facilisis ea. Per ne impedit iracundia neglegentur. " \
"Consetetur neglegentur eum ut, vis animal legimus inimicus id.\n\n" \
"His audiam" "His audiam"
annotation = create( annotation = create(
:legislation_annotation, :legislation_annotation,
@@ -28,25 +31,37 @@ RSpec.describe Legislation::Annotation, type: :model do
ranges: [{ "start" => "/p[1]", "startOffset" => 6, "end" => "/p[3]", "endOffset" => 11 }] ranges: [{ "start" => "/p[1]", "startOffset" => 6, "end" => "/p[3]", "endOffset" => 11 }]
) )
context = "Lorem <span class=annotator-hl>ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt" \ context = "Lorem " \
" ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper" \ "<span class=annotator-hl>ipsum dolor sit amet, consectetuer adipiscing " \
" suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit" \ "elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna " \
" esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui" \ "aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci " \
" blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\n\nExpetenda tincidunt in sed, ex" \ "tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo " \
" partem placerat sea, porro commodo ex eam. His putant aeterno interesset at. Usu ea mundi tincidunt, omnium virtute" \ "consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate " \
" aliquando ius ex. Ea aperiri sententiae duo. Usu nullam dolorum quaestio ei, sit vidit facilisis ea. Per ne impedit" \ "velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis " \
" iracundia neglegentur. Consetetur neglegentur eum ut, vis animal legimus inimicus id.\n\nHis audiam</span>deserunt in, eum" \ "at vero eros et accumsan et iusto odio dignissim qui blandit praesent " \
" ubique voluptatibus te. In reque dicta usu. Ne rebum dissentiet eam, vim omnis deseruisse id. Ullum deleniti vituperata at" \ "luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\n\n" \
" quo, insolens complectitur te eos, ea pri dico munere propriae. Vel ferri facilis ut, qui paulo ridens praesent ad. Possim" \ "Expetenda tincidunt in sed, ex partem placerat sea, porro commodo ex " \
" alterum qui cu. Accusamus consulatu ius te, cu decore soleat appareat usu." "eam. His putant aeterno interesset at. Usu ea mundi tincidunt, omnium " \
"virtute aliquando ius ex. Ea aperiri sententiae duo. Usu nullam dolorum " \
"quaestio ei, sit vidit facilisis ea. Per ne impedit iracundia neglegentur. " \
"Consetetur neglegentur eum ut, vis animal legimus inimicus id.\n\n" \
"His audiam" \
"</span>deserunt in, eum ubique voluptatibus te. In reque dicta usu. Ne " \
"rebum dissentiet eam, vim omnis deseruisse id. Ullum deleniti vituperata " \
"at quo, insolens complectitur te eos, ea pri dico munere propriae. Vel " \
"ferri facilis ut, qui paulo ridens praesent ad. Possim alterum qui cu. " \
"Accusamus consulatu ius te, cu decore soleat appareat usu."
expect(annotation.context).to eq(context) expect(annotation.context).to eq(context)
end end
it "calculates the context for multinode annotations 2" do it "calculates the context for multinode annotations 2" do
quote = "Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla" \ quote = "Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse " \
" facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore" \ "molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero " \
" te feugait nulla facilisi.\r\n\r\nExpetenda tincidunt in sed, ex partem placerat sea, porro commodo ex eam. His putant" \ "eros et accumsan et iusto odio dignissim qui blandit praesent luptatum " \
" aeterno interesset at. Usu ea mundi tincidunt, omnium virtute aliquando ius ex. Ea aperiri sententiae duo" "zzril delenit augue duis dolore te feugait nulla facilisi.\r\n\r\n" \
"Expetenda tincidunt in sed, ex partem placerat sea, porro commodo ex eam. " \
"His putant aeterno interesset at. Usu ea mundi tincidunt, omnium virtute " \
"aliquando ius ex. Ea aperiri sententiae duo"
annotation = create( annotation = create(
:legislation_annotation, :legislation_annotation,
draft_version: draft_version, draft_version: draft_version,
@@ -54,45 +69,69 @@ RSpec.describe Legislation::Annotation, type: :model do
ranges: [{ "start" => "/p[1]", "startOffset" => 273, "end" => "/p[2]", "endOffset" => 190 }] ranges: [{ "start" => "/p[1]", "startOffset" => 273, "end" => "/p[2]", "endOffset" => 190 }]
) )
context = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna" \ context = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam " \
" aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut" \ "nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat " \
" aliquip ex ea commodo consequat. <span class=annotator-hl>Duis autem vel eum iriure dolor in hendrerit in vulputate velit" \ "volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation " \
" esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui" \ "ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. " \
" blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\r\n\r\nExpetenda tincidunt in sed, ex" \ "<span class=annotator-hl>Duis autem vel eum iriure dolor in hendrerit " \
" partem placerat sea, porro commodo ex eam. His putant aeterno interesset at. Usu ea mundi tincidunt, omnium virtute" \ "in vulputate velit esse molestie consequat, vel illum dolore eu feugiat " \
" aliquando ius ex. Ea aperiri sententiae duo</span>. Usu nullam dolorum quaestio ei, sit vidit facilisis ea. Per ne impedit" \ "nulla facilisis at vero eros et accumsan et iusto odio dignissim qui " \
" iracundia neglegentur. Consetetur neglegentur eum ut, vis animal legimus inimicus id." "blandit praesent luptatum zzril delenit augue duis dolore te feugait " \
"nulla facilisi.\r\n\r\n" \
"Expetenda tincidunt in sed, ex partem placerat sea, porro commodo ex " \
"eam. His putant aeterno interesset at. Usu ea mundi tincidunt, omnium " \
"virtute aliquando ius ex. Ea aperiri sententiae duo" \
"</span>. Usu nullam dolorum quaestio ei, sit vidit facilisis ea. Per " \
"ne impedit iracundia neglegentur. Consetetur neglegentur eum ut, vis " \
"animal legimus inimicus id."
expect(annotation.context).to eq(context) expect(annotation.context).to eq(context)
end end
it "calculates the context for multinode annotations 3" do it "calculates the context for multinode annotations 3" do
body = "The GNU Affero General Public License is a free, copyleft license for software and other kinds of works, specifically designed" \ body = "The GNU Affero General Public License is a free, copyleft license for " \
" to ensure cooperation with the community in the case of network server software.\r\n\r\nThe licenses for most software and" \ "software and other kinds of works, specifically designed to ensure " \
" other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public" \ "cooperation with the community in the case of network server software.\r\n\r\n" \
" Licenses are intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free" \ "The licenses for most software and other practical works are designed to " \
" software for all its users.\r\n\r\nWhen we speak of free software, we are referring to freedom, not price. Our General" \ "take away your freedom to share and change the works. By contrast, our " \
" Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for" \ "General Public Licenses are intended to guarantee your freedom to share and " \
" them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces" \ "change all versions of a program--to make sure it remains free software for " \
" of it in new free programs, and that you know you can do these things.\r\n\r\nDevelopers that use our General Public Licenses" \ "all its users.\r\n\r\n" \
" protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you" \ "When we speak of free software, we are referring to freedom, not price. " \
" legal permission to copy, distribute and/or modify the software.\r\n\r\nA secondary benefit of defending all users' freedom" \ "Our General Public Licenses are designed to make sure that you have the " \
" is that improvements made in alternate versions of the program, if they receive widespread use, become available for other" \ "freedom to distribute copies of free software (and charge for them if you wish), " \
" developers to incorporate. Many developers of free software are heartened and encouraged by the resulting cooperation." \ "that you receive source code or can get it if you want it, that you can change " \
" However, in the case of software used on network servers, this result may fail to come about. The GNU General Public License" \ "the software or use pieces of it in new free programs, and that you know you " \
" permits making a modified version and letting the public access it on a server without ever releasing its source code to the" \ "can do these things.\r\n\r\n" \
" public.\r\n\r\nThe GNU Affero General Public License is designed specifically to ensure that, in such cases, the modified" \ "Developers that use our General Public Licenses protect your rights with two " \
" source code becomes available to the community. It requires the operator of a network server to provide the source code of" \ "steps: (1) assert copyright on the software, and (2) offer you this License which " \
" the modified version running there to the users of that server. Therefore, public use of a modified version, on a publicly" \ "gives you legal permission to copy, distribute and/or modify the software.\r\n\r\n" \
" accessible server, gives the public access to the source code of the modified version.\r\n\r\nAn older license, called the" \ "A secondary benefit of defending all users' freedom is that improvements made in " \
" Affero General Public License and published by Affero, was designed to accomplish similar goals. This is a different license," \ "alternate versions of the program, if they receive widespread use, become " \
" not a version of the Affero GPL, but Affero has released a new version of the Affero GPL which permits relicensing under this" \ "available for other developers to incorporate. Many developers of free software " \
" license." "are heartened and encouraged by the resulting cooperation. " \
"However, in the case of software used on network servers, this result may fail " \
"to come about. The GNU General Public License permits making a modified version " \
"and letting the public access it on a server without ever releasing its source " \
"code to the public.\r\n\r\n" \
"The GNU Affero General Public License is designed specifically to ensure that, " \
"in such cases, the modified source code becomes available to the community. " \
"It requires the operator of a network server to provide the source code of " \
"the modified version running there to the users of that server. Therefore, " \
"public use of a modified version, on a publicly accessible server, gives the " \
"public access to the source code of the modified version.\r\n\r\n" \
"An older license, called the Affero General Public License and published by " \
"Affero, was designed to accomplish similar goals. This is a different license, " \
"not a version of the Affero GPL, but Affero has released a new version of the " \
"Affero GPL which permits relicensing under this license."
draft_version = create(:legislation_draft_version, body: body) draft_version = create(:legislation_draft_version, body: body)
quote = "By contrast, our General Public Licenses are intended to guarantee your freedom to share and change all versions of a" \ quote = "By contrast, our General Public Licenses are intended to guarantee your " \
" program--to make sure it remains free software for all its users.\r\n\r\nWhen we speak of free software, we are referring to" \ "freedom to share and change all versions of a program--to make sure it " \
" freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of" \ "remains free software for all its users.\r\n\r\n" \
" free software (and charge for them if you wish)" "When we speak of free software, we are referring to freedom, not price. " \
"Our General Public Licenses are designed to make sure that you have the " \
"freedom to distribute copies of free software (and charge for them if you wish)"
annotation = create( annotation = create(
:legislation_annotation, :legislation_annotation,
@@ -101,13 +140,17 @@ RSpec.describe Legislation::Annotation, type: :model do
ranges: [{ "start" => "/p[2]", "startOffset" => 127, "end" => "/p[3]", "endOffset" => 223 }] ranges: [{ "start" => "/p[2]", "startOffset" => 127, "end" => "/p[3]", "endOffset" => 223 }]
) )
context = "The licenses for most software and other practical works are designed to take away your freedom to share and change the" \ context = "The licenses for most software and other practical works are designed to " \
" works. <span class=annotator-hl>By contrast, our General Public Licenses are intended to guarantee your freedom to share" \ "take away your freedom to share and change the works. " \
" and change all versions of a program--to make sure it remains free software for all its users.\r\n\r\nWhen we speak of" \ "<span class=annotator-hl>By contrast, our General Public Licenses are " \
" free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have" \ "intended to guarantee your freedom to share and change all versions of " \
" the freedom to distribute copies of free software (and charge for them if you wish)</span>, that you receive source code" \ "a program--to make sure it remains free software for all its users.\r\n\r\n" \
" or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know" \ "When we speak of free software, we are referring to freedom, not price. " \
" you can do these things." "Our General Public Licenses are designed to make sure that you have the " \
"freedom to distribute copies of free software (and charge for them if you wish)" \
"</span>, that you receive source code or can get it if you want it, that " \
"you can change the software or use pieces of it in new free programs, " \
"and that you know you can do these things."
expect(annotation.context).to eq(context) expect(annotation.context).to eq(context)
end end

View File

@@ -46,7 +46,9 @@ describe Legislation::Question do
describe "#next_question_id" do describe "#next_question_id" do
let!(:question1) { create(:legislation_question) } let!(:question1) { create(:legislation_question) }
let!(:question2) { create(:legislation_question, legislation_process_id: question1.legislation_process_id) } let!(:question2) do
create(:legislation_question, legislation_process_id: question1.legislation_process_id)
end
it "returns the next question" do it "returns the next question" do
expect(question1.next_question_id).to eq(question2.id) expect(question1.next_question_id).to eq(question2.id)
@@ -59,7 +61,9 @@ describe Legislation::Question do
describe "#first_question_id" do describe "#first_question_id" do
let!(:question1) { create(:legislation_question) } let!(:question1) { create(:legislation_question) }
let!(:question2) { create(:legislation_question, legislation_process_id: question1.legislation_process_id) } let!(:question2) do
create(:legislation_question, legislation_process_id: question1.legislation_process_id)
end
it "returns the first question" do it "returns the first question" do
expect(question1.first_question_id).to eq(question1.id) expect(question1.first_question_id).to eq(question1.id)

View File

@@ -196,7 +196,11 @@ describe Officing::Residence do
end end
it "makes half-verified users fully verified" do it "makes half-verified users fully verified" do
user = create(:user, residence_verified_at: Time.current, document_type: "1", document_number: "12345678Z") user = create(:user,
residence_verified_at: Time.current,
document_type: "1",
document_number: "12345678Z")
expect(user).to be_unverified expect(user).to be_unverified
residence = build(:officing_residence, document_number: "12345678Z", year_of_birth: 1980) residence = build(:officing_residence, document_number: "12345678Z", year_of_birth: 1980)
expect(residence).to be_valid expect(residence).to be_valid

View File

@@ -7,7 +7,9 @@ describe Poll::Ballot do
let(:investment) { create(:budget_investment, :selected, price: 5000000, heading: heading) } let(:investment) { create(:budget_investment, :selected, price: 5000000, heading: heading) }
let(:poll) { create(:poll, budget: budget) } let(:poll) { create(:poll, budget: budget) }
let(:poll_ballot_sheet) { create(:poll_ballot_sheet, poll: poll) } let(:poll_ballot_sheet) { create(:poll_ballot_sheet, poll: poll) }
let(:poll_ballot) { create(:poll_ballot, ballot_sheet: poll_ballot_sheet, external_id: 1, data: investment.id) } let(:poll_ballot) do
create(:poll_ballot, ballot_sheet: poll_ballot_sheet, external_id: 1, data: investment.id)
end
before { create(:budget_ballot, budget: budget, physical: true, poll_ballot: poll_ballot) } before { create(:budget_ballot, budget: budget, physical: true, poll_ballot: poll_ballot) }
describe "#verify" do describe "#verify" do

View File

@@ -5,7 +5,9 @@ describe Poll::Shift do
let(:booth) { create(:poll_booth) } let(:booth) { create(:poll_booth) }
let(:user) { create(:user, username: "Ana", email: "ana@example.com") } let(:user) { create(:user, username: "Ana", email: "ana@example.com") }
let(:officer) { create(:poll_officer, user: user) } let(:officer) { create(:poll_officer, user: user) }
let(:recount_shift) { build(:poll_shift, booth: booth, officer: officer, date: Date.current, task: :recount_scrutiny) } let(:recount_shift) do
build(:poll_shift, booth: booth, officer: officer, date: Date.current, task: :recount_scrutiny)
end
describe "validations" do describe "validations" do
let(:shift) { build(:poll_shift) } let(:shift) { build(:poll_shift) }
@@ -37,19 +39,28 @@ describe Poll::Shift do
it "is not valid with same booth, officer, date and task" do it "is not valid with same booth, officer, date and task" do
recount_shift.save! recount_shift.save!
expect(build(:poll_shift, booth: booth, officer: officer, date: Date.current, task: :recount_scrutiny)).not_to be_valid expect(build(:poll_shift, booth: booth,
officer: officer,
date: Date.current,
task: :recount_scrutiny)).not_to be_valid
end end
it "is valid with same booth, officer and date but different task" do it "is valid with same booth, officer and date but different task" do
recount_shift.save! recount_shift.save!
expect(build(:poll_shift, booth: booth, officer: officer, date: Date.current, task: :vote_collection)).to be_valid expect(build(:poll_shift, booth: booth,
officer: officer,
date: Date.current,
task: :vote_collection)).to be_valid
end end
it "is valid with same booth, officer and task but different date" do it "is valid with same booth, officer and task but different date" do
recount_shift.save! recount_shift.save!
expect(build(:poll_shift, booth: booth, officer: officer, date: Date.tomorrow, task: :recount_scrutiny)).to be_valid expect(build(:poll_shift, booth: booth,
officer: officer,
date: Date.tomorrow,
task: :recount_scrutiny)).to be_valid
end end
end end
@@ -58,7 +69,9 @@ describe Poll::Shift do
booth_assignment1 = create(:poll_booth_assignment, booth: booth) booth_assignment1 = create(:poll_booth_assignment, booth: booth)
booth_assignment2 = create(:poll_booth_assignment, booth: booth) booth_assignment2 = create(:poll_booth_assignment, booth: booth)
expect { create(:poll_shift, booth: booth, officer: officer, date: Date.current) }.to change { Poll::OfficerAssignment.all.count }.by(2) expect do
create(:poll_shift, booth: booth, officer: officer, date: Date.current)
end.to change { Poll::OfficerAssignment.all.count }.by(2)
officer_assignments = Poll::OfficerAssignment.all officer_assignments = Poll::OfficerAssignment.all
oa1 = officer_assignments.first oa1 = officer_assignments.first
@@ -74,7 +87,9 @@ describe Poll::Shift do
expect(oa2.booth_assignment).to eq(booth_assignment2) expect(oa2.booth_assignment).to eq(booth_assignment2)
expect(oa2.final).to be_falsey expect(oa2.final).to be_falsey
create(:poll_officer_assignment, officer: officer, booth_assignment: booth_assignment1, date: Date.tomorrow) create(:poll_officer_assignment, officer: officer,
booth_assignment: booth_assignment1,
date: Date.tomorrow)
expect { Poll::Shift.last.destroy }.to change { Poll::OfficerAssignment.all.count }.by(-2) expect { Poll::Shift.last.destroy }.to change { Poll::OfficerAssignment.all.count }.by(-2)
end end

View File

@@ -110,12 +110,14 @@ describe Proposal do
describe "tag_list" do describe "tag_list" do
it "is not valid with a tag list of more than 6 elements" do it "is not valid with a tag list of more than 6 elements" do
proposal.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción", "Fiestas populares", "Prensa", "Huelgas"] proposal.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción",
"Fiestas populares", "Prensa", "Huelgas"]
expect(proposal).not_to be_valid expect(proposal).not_to be_valid
end end
it "is valid with a tag list of up to 6 elements" do it "is valid with a tag list of up to 6 elements" do
proposal.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción", "Fiestas populares", "Prensa"] proposal.tag_list = ["Hacienda", "Economía", "Medio Ambiente", "Corrupción",
"Fiestas populares", "Prensa"]
expect(proposal).to be_valid expect(proposal).to be_valid
end end
end end
@@ -256,7 +258,9 @@ describe Proposal do
user = create(:user, verified_at: Time.current) user = create(:user, verified_at: Time.current)
archived_proposal = create(:proposal, :archived) archived_proposal = create(:proposal, :archived)
expect { archived_proposal.register_vote(user, "yes") }.to change { proposal.reload.votes_for.size }.by(0) expect do
archived_proposal.register_vote(user, "yes")
end.to change { proposal.reload.votes_for.size }.by(0)
end end
end end
@@ -623,7 +627,8 @@ describe Proposal do
it "gives much more weight to word matches than votes" do it "gives much more weight to word matches than votes" do
exact_title_few_votes = create(:proposal, title: "stop corruption", cached_votes_up: 5) exact_title_few_votes = create(:proposal, title: "stop corruption", cached_votes_up: 5)
similar_title_many_votes = create(:proposal, title: "stop some of the corruption", cached_votes_up: 500) similar_title_many_votes = create(:proposal, title: "stop some of the corruption",
cached_votes_up: 500)
results = Proposal.search("stop corruption") results = Proposal.search("stop corruption")
@@ -683,9 +688,9 @@ describe Proposal do
end end
it "is able to reorder by most commented after searching" do it "is able to reorder by most commented after searching" do
least_commented = create(:proposal, title: "stop corruption", cached_votes_up: 1, comments_count: 1) least_commented = create(:proposal, title: "stop corruption", cached_votes_up: 1, comments_count: 1)
most_commented = create(:proposal, title: "stop corruption", cached_votes_up: 2, comments_count: 100) most_commented = create(:proposal, title: "stop corruption", cached_votes_up: 2, comments_count: 100)
some_comments = create(:proposal, title: "stop corruption", cached_votes_up: 3, comments_count: 10) some_comments = create(:proposal, title: "stop corruption", cached_votes_up: 3, comments_count: 10)
results = Proposal.search("stop corruption") results = Proposal.search("stop corruption")

View File

@@ -10,9 +10,11 @@ describe RelatedContent do
end end
it "allows relationables from various classes" do it "allows relationables from various classes" do
expect(build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable)).to be_valid 3.times do
expect(build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable)).to be_valid expect(build(:related_content,
expect(build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable)).to be_valid parent_relationable: parent_relationable,
child_relationable: child_relationable)).to be_valid
end
end end
it "does not allow empty relationables" do it "does not allow empty relationables" do
@@ -21,8 +23,15 @@ describe RelatedContent do
end end
it "does not allow repeated related contents" do it "does not allow repeated related contents" do
related_content = create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable, author: build(:user)) related_content = create(:related_content,
new_related_content = build(:related_content, parent_relationable: related_content.parent_relationable, child_relationable: related_content.child_relationable) parent_relationable: parent_relationable,
child_relationable: child_relationable,
author: build(:user))
new_related_content = build(:related_content,
parent_relationable: related_content.parent_relationable,
child_relationable: related_content.child_relationable)
expect(new_related_content).not_to be_valid expect(new_related_content).not_to be_valid
end end
@@ -61,7 +70,12 @@ describe RelatedContent do
describe "create_opposite_related_content" do describe "create_opposite_related_content" do
let(:parent_relationable) { create(:proposal) } let(:parent_relationable) { create(:proposal) }
let(:child_relationable) { create(:debate) } let(:child_relationable) { create(:debate) }
let(:related_content) { build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable, author: build(:user)) } let(:related_content) do
build(:related_content,
parent_relationable: parent_relationable,
child_relationable: child_relationable,
author: build(:user))
end
it "creates an opposite related_content" do it "creates an opposite related_content" do
expect { related_content.save }.to change { RelatedContent.count }.by(2) expect { related_content.save }.to change { RelatedContent.count }.by(2)
@@ -72,8 +86,14 @@ describe RelatedContent do
describe "#relationed_contents" do describe "#relationed_contents" do
before do before do
related_content = create(:related_content, parent_relationable: parent_relationable, child_relationable: create(:proposal), author: build(:user)) related_content = create(:related_content,
create(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable, author: build(:user)) parent_relationable: parent_relationable,
child_relationable: create(:proposal),
author: build(:user))
create(:related_content,
parent_relationable: parent_relationable,
child_relationable: child_relationable,
author: build(:user))
2.times do 2.times do
related_content.send(:score_positive, build(:user)) related_content.send(:score_positive, build(:user))

View File

@@ -25,14 +25,18 @@ describe SDG::LocalTarget do
local_target = build(:sdg_local_target, code: "1.6.1", target: SDG::Target[1.1]) local_target = build(:sdg_local_target, code: "1.6.1", target: SDG::Target[1.1])
expect(local_target).not_to be_valid expect(local_target).not_to be_valid
expect(local_target.errors.full_messages).to include "Code must start with the same code as its target followed by a dot and end with a number" expect(local_target.errors.full_messages).to include "Code must start with the same " \
"code as its target followed by " \
"a dot and end with a number"
end end
it "is not valid when local target code part is not a number" do it "is not valid when local target code part is not a number" do
local_target = build(:sdg_local_target, code: "1.1.A", target: SDG::Target[1.1]) local_target = build(:sdg_local_target, code: "1.1.A", target: SDG::Target[1.1])
expect(local_target).not_to be_valid expect(local_target).not_to be_valid
expect(local_target.errors.full_messages).to include "Code must start with the same code as its target followed by a dot and end with a number" expect(local_target.errors.full_messages).to include "Code must start with the same " \
"code as its target followed by " \
"a dot and end with a number"
end end
it "is not valid if code is not unique" do it "is not valid if code is not unique" do

Some files were not shown because too many files have changed in this diff Show More