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:
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:
Enabled: true

View File

@@ -183,7 +183,8 @@ class Admin::MenuComponent < ApplicationComponent
[
t("admin.menu.poll_booth_assignments"),
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
@@ -255,7 +256,8 @@ class Admin::MenuComponent < ApplicationComponent
banners_link,
information_texts_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

View File

@@ -64,7 +64,10 @@ class Budgets::Investments::VotesComponent < ApplicationComponent
t("votes.budget_investments.#{reason}",
count: investment.group.max_votable_headings,
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

View File

@@ -13,6 +13,8 @@ class Relationable::RelatedListComponent < ApplicationComponent
private
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

View File

@@ -33,7 +33,8 @@ class SDG::FilterLinksComponent < ApplicationComponent
def index_by(advanced_search)
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
polymorphic_path(related_model, advanced_search: advanced_search)
end

View File

@@ -22,7 +22,8 @@ class Admin::Api::StatsController < Admin::Api::BaseController
end
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
render json: ds.build
end

View File

@@ -10,7 +10,9 @@ module Budgets
authorize_resource :budget
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
load_investment

View File

@@ -28,7 +28,8 @@ module Budgets
has_orders %w[most_voted newest oldest], only: :show
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
@@ -79,12 +80,14 @@ module Budgets
def 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
def suggest
@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
end

View File

@@ -59,7 +59,8 @@ module Admin::BudgetHeadingsActions
end
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)]
end

View File

@@ -7,7 +7,11 @@ module CommentableActions
def index
@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.filter_by(@advanced_search_terms)

View File

@@ -8,7 +8,9 @@ class DirectUploadsController < ApplicationController
helper_method :render_destroy_upload_link
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?
@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))
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
render :new
end

View File

@@ -37,7 +37,10 @@ class Management::Budgets::InvestmentsController < Management::BaseController
end
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
private

View File

@@ -15,7 +15,9 @@ class Management::DocumentVerificationsController < Management::BaseController
elsif @document_verification.user?
render :new
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
render :invalid_document
end
@@ -49,6 +51,8 @@ class Management::DocumentVerificationsController < Management::BaseController
def clean_document_number
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

View File

@@ -31,7 +31,9 @@ class Management::ProposalsController < Management::BaseController
super
@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
def vote

View File

@@ -24,7 +24,10 @@ class Management::UsersController < Management::BaseController
end
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
redirect_to management_document_verifications_path, notice: t("management.users.erased_notice")
end

View File

@@ -10,7 +10,8 @@ class Officing::ResidenceController < Officing::BaseController
def create
@residence = Officing::Residence.new(residence_params.merge(officer: current_user.poll_officer))
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
render :new
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
go_back_to_new if question.blank?
partial_result = ::Poll::PartialResult.find_or_initialize_by(booth_assignment_id: @officer_assignment.booth_assignment_id,
date: Date.current,
question_id: question_id,
answer: answer)
partial_result = ::Poll::PartialResult.find_or_initialize_by(
booth_assignment_id: @officer_assignment.booth_assignment_id,
date: Date.current,
question_id: question_id,
answer: answer
)
partial_result.officer_assignment_id = @officer_assignment.id
partial_result.amount = count.to_i
partial_result.author = current_user
@@ -62,8 +64,10 @@ class Officing::ResultsController < Officing::BaseController
end
def build_recounts
recount = ::Poll::Recount.find_or_initialize_by(booth_assignment_id: @officer_assignment.booth_assignment_id,
date: Date.current)
recount = ::Poll::Recount.find_or_initialize_by(
booth_assignment_id: @officer_assignment.booth_assignment_id,
date: Date.current
)
recount.officer_assignment_id = @officer_assignment.id
recount.author = current_user
recount.origin = "booth"
@@ -90,7 +94,9 @@ class Officing::ResultsController < Officing::BaseController
def load_officer_assignment
@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
def load_officer_assignments

View File

@@ -137,7 +137,10 @@ class ProposalsController < ApplicationController
def load_retired
if params[:retired].present?
@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
@resources = @resources.not_retired
end
@@ -152,7 +155,8 @@ class ProposalsController < ApplicationController
end
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"]
@featured_proposals = Proposal.not_archived

View File

@@ -43,7 +43,8 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
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?
respond_with_navigational(resource) { render :show }
elsif resource.errors.empty?
@@ -51,9 +52,14 @@ class Users::ConfirmationsController < Devise::ConfirmationsController
if resource.confirm
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
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
else
respond_with_navigational(resource.errors, status: :unprocessable_entity) { render :new }

View File

@@ -1,5 +1,6 @@
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
invisible_captcha only: [:create], honeypot: :address, scope: :user
@@ -52,16 +53,21 @@ class Users::RegistrationsController < Devise::RegistrationsController
def check_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
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
private
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)
end

View File

@@ -22,7 +22,8 @@ class Verification::EmailController < ApplicationController
@email.encrypted_token,
@verified_user.document_type,
@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
redirect_to verified_user_path, alert: t("verification.email.create.alert.failure")
end

View File

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

View File

@@ -6,7 +6,10 @@ module AdminHelper
def official_level_options
options = [["", 0]]
(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
options
end

View File

@@ -21,9 +21,17 @@ module CommentsHelper
def comment_button_text(parent_id, commentable)
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
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

View File

@@ -8,7 +8,11 @@ module CommunitiesHelper
end
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
def author?(community, participant)
@@ -28,7 +32,11 @@ module CommunitiesHelper
end
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
def create_topic_link(community)

View File

@@ -49,7 +49,10 @@ module MailerHelper
end
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
def css_for_mailer_link

View File

@@ -2,7 +2,8 @@ module ProposalsHelper
def progress_bar_percentage(proposal)
case proposal.cached_votes_up
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
end
end

View File

@@ -11,7 +11,10 @@ class Mailer < ApplicationMailer
manage_subscriptions_token(@commentable.author)
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?
end
end
@@ -65,7 +68,8 @@ class Mailer < ApplicationMailer
manage_subscriptions_token(user)
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

View File

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

View File

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

View File

@@ -5,8 +5,9 @@ module Abilities
def initialize(user)
merge Abilities::Moderation.new(user)
can :comment_as_moderator, [Debate, Comment, Proposal, Budget::Investment, Poll, Poll::Question,
Legislation::Question, Legislation::Annotation, Legislation::Proposal, Topic]
can :comment_as_moderator, [Debate, Comment, Proposal, Budget::Investment, Poll,
Poll::Question, Legislation::Question,
Legislation::Annotation, Legislation::Proposal, Topic]
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_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

View File

@@ -28,7 +28,8 @@ class Budget
def check_valid_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
def check_selected

View File

@@ -56,7 +56,8 @@ class Budget
class_name: "Comment"
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 :heading_id, presence: true
@@ -104,7 +105,9 @@ class Budget
scope :by_heading, ->(heading_id) { where(heading_id: heading_id) }
scope :by_admin, ->(admin_id) { where(administrator_id: admin_id) }
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) }

View File

@@ -2,8 +2,10 @@ module Filterable
extend ActiveSupport::Concern
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
class_methods do

View File

@@ -83,9 +83,10 @@ module Globalizable
def validates_translation(method, options = {})
validates(method, options.merge(if: lambda { |resource| resource.translations.blank? }))
if options.include?(:length)
lenght_validate = { length: options[:length] }
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
if options.count > 1
translation_class.instance_eval do
@@ -112,7 +113,9 @@ module Globalizable
translations_ids = translation_class
.select("DISTINCT ON (#{translations_foreign_key}) id")
.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")
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 :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 :unverified, -> { residence_or_phone_unverified.where(verified_at: nil, level_two_verified_at: nil) }
scope :incomplete_verification, -> { residence_unverified.where("failed_census_calls_count > ?", 0).or(residence_verified.phone_not_fully_confirmed) }
scope :unverified, -> do
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
def skip_verification?

View File

@@ -160,7 +160,11 @@ class Debate < ApplicationRecord
def self.debates_orders(user)
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
end

View File

@@ -16,12 +16,15 @@ class DirectUpload
send("#{name}=", value)
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)
# Refactor
@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)
elsif @resource.class.reflections[@resource_relation].macro == :has_one
@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 :process, foreign_key: "legislation_process_id", inverse_of: :questions
has_many :question_options, -> { order(:id) }, class_name: "Legislation::QuestionOption", foreign_key: "legislation_question_id",
dependent: :destroy, inverse_of: :question
has_many :answers, class_name: "Legislation::Answer", foreign_key: "legislation_question_id", dependent: :destroy, inverse_of: :question
has_many :question_options, -> { order(:id) }, class_name: "Legislation::QuestionOption",
foreign_key: "legislation_question_id",
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
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_translation :title, presence: true

View File

@@ -22,13 +22,15 @@ class MachineLearning
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!
import_ml_proposals_tags
update_machine_learning_info_for("tags")
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!
import_ml_investments_tags
update_machine_learning_info_for("tags")
@@ -95,14 +97,32 @@ class MachineLearning
def data_output_files
files = { tags: [], related_content: [], comments_summary: [] }
files[:tags] << 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] << investments_tags_filename if File.exist?(data_folder.join(investments_tags_filename))
files[:tags] << investments_taggings_filename if File.exist?(data_folder.join(investments_taggings_filename))
files[:related_content] << proposals_related_filename if File.exist?(data_folder.join(proposals_related_filename))
files[:related_content] << investments_related_filename if File.exist?(data_folder.join(investments_related_filename))
files[:comments_summary] << proposals_comments_summary_filename if File.exist?(data_folder.join(proposals_comments_summary_filename))
files[:comments_summary] << investments_comments_summary_filename if File.exist?(data_folder.join(investments_comments_summary_filename))
if File.exist?(data_folder.join(proposals_tags_filename))
files[:tags] << proposals_tags_filename
end
if File.exist?(data_folder.join(proposals_taggings_filename))
files[:tags] << proposals_taggings_filename
end
if File.exist?(data_folder.join(investments_tags_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
end

View File

@@ -12,8 +12,13 @@ class Organization < ApplicationRecord
delegate :email, :phone_number, to: :user
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 :rejected, -> { where.not(rejected_at: nil).where("(organizations.verified_at IS NULL or organizations.verified_at < rejected_at)") }
scope :verified, -> do
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
update(verified_at: Time.current)
@@ -33,7 +38,8 @@ class Organization < ApplicationRecord
def self.search(text)
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
none
end

View File

@@ -57,7 +57,8 @@ class Poll < ApplicationRecord
def self.sort_for_list(user = nil)
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

View File

@@ -24,7 +24,9 @@ class Poll
private
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
def destroy_poll_shifts

View File

@@ -20,7 +20,9 @@ class Poll::Recount < ApplicationRecord
amounts_changed = false
[: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")}"
amounts_changed = true

View File

@@ -16,7 +16,10 @@ class ProgressBar < ApplicationRecord
scope: [:progressable_type, :progressable_id],
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?
end

View File

@@ -50,8 +50,12 @@ class Proposal < ApplicationRecord
validates :author, presence: true
validates :responsible_name, presence: true, unless: :skip_user_verification?
validates :responsible_name, length: { in: 6..Proposal.responsible_name_max_length }, unless: :skip_user_verification?
validates :retired_reason, presence: true, inclusion: { in: ->(*) { RETIRE_OPTIONS }}, unless: -> { retired_at.blank? }
validates :responsible_name,
length: { in: 6..Proposal.responsible_name_max_length },
unless: :skip_user_verification?
validates :retired_reason,
presence: true,
inclusion: { in: ->(*) { RETIRE_OPTIONS }}, unless: -> { retired_at.blank? }
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
@@ -236,7 +240,11 @@ class Proposal < ApplicationRecord
def self.proposals_orders(user)
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
end

View File

@@ -31,7 +31,11 @@ class ProposalNotification < ApplicationRecord
interval = Setting[:proposal_notification_minimum_interval_in_days]
minimum_interval = (Time.current - interval.to_i.days).to_datetime
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

View File

@@ -11,7 +11,10 @@ class RelatedContent < ApplicationRecord
has_one :opposite_related_content, class_name: name, foreign_key: :related_content_id
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
after_create :create_opposite_related_content, unless: proc { opposite_related_content.present? }
@@ -66,7 +69,10 @@ class RelatedContent < ApplicationRecord
def score(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
def hide_with_opposite

View File

@@ -28,7 +28,9 @@ class Signature < ApplicationRecord
def assign_vote_to_user
set_user
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
signable.register_vote(user, "yes")
end

View File

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

View File

@@ -48,7 +48,9 @@ class Verification::Residence
end
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
def store_failed_attempt
@@ -74,7 +76,8 @@ class Verification::Residence
end
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
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)
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|
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: polymorphic_url(question, anchor: "comments"), ref: sheet.rows.last.cells.last
sheet.add_hyperlink location: legislation_process_question_url(question.process, question),
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?
question.best_comments.each do |comment|
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
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|
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
end
sheet.add_row ["", ""]
end
if @process.allegations_phase.enabled? && @comments.any?
sheet.add_row [t("legislation.summary.allegations_phase"),
t("legislation.summary.top_comments", count: @comments.count)], style: title
sheet.add_row(
[
t("legislation.summary.allegations_phase"),
t("legislation.summary.top_comments", count: @comments.count)
],
style: title
)
@comments.group_by(&:commentable).each do |annotation, annotation_comments|
sheet.add_row [t("legislation.annotations.index.comments_about")]
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
annotation_comments.each do |comment|

View File

@@ -30,7 +30,8 @@ set :pty, true
set :use_sudo, false
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

View File

@@ -99,7 +99,8 @@ Apartment.configure do |config|
#
# 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.
#
# 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
# you want to switch to.
Rails.application.config.middleware.insert_before Warden::Manager, Apartment::Elevators::Generic, ->(request) do
Tenant.resolve_host(request.host)
end
Rails.application.config.middleware.insert_before Warden::Manager,
Apartment::Elevators::Generic,
->(request) { Tenant.resolve_host(request.host) }
# Rails.application.config.middleware.use Apartment::Elevators::Domain
# Rails.application.config.middleware.use Apartment::Elevators::Subdomain

View File

@@ -63,7 +63,11 @@ module Devise
if !new_record? && !encrypted_password_change.nil? && !erased?
dummy = self.class.new
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)
end
end

View File

@@ -253,9 +253,12 @@ namespace :admin do
end
resources :images, only: [:index, :update, :destroy]
resources :content_blocks, except: [:show]
delete "/heading_content_blocks/:id", to: "content_blocks#delete_heading_content_block", as: "delete_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"
delete "/heading_content_blocks/:id", to: "content_blocks#delete_heading_content_block",
as: "delete_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
post :update, on: :collection
end

View File

@@ -2,23 +2,28 @@ section "Creating Geozones" do
Geozone.create!(name: I18n.t("seeds.geozones.north_district"),
external_code: "001", census_code: "01",
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," \
"66,286,73,258,65,265,57,249,47,207,58,159,84,108,85,72,101,51,114")
"196,233,203,240,215,283,194,329,185,377,184,388,165,369," \
"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"),
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," \
"31,372,52,396,64,432,89,453,116,432,149,419,162,412,165,377,172,357,189,352,228," \
"327,246,313,262,297,234,291,210,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")
"31,372,52,396,64,432,89,453,116,432,149,419,162,412,165," \
"377,172,357,189,352,228,327,246,313,262,297,234,291,210," \
"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"),
external_code: "003", census_code: "03",
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," \
"281,195,239,216,245,221,245,232,261,244,281,238,300,242,304,251,285,262,278,277," \
"267,294,249,312,219,333,198,346,184,353")
"250,409,283,390,298,369,344,363,351,334,356,296,361,267," \
"376,245,378,185,327,188,281,195,239,216,245,221,245,232," \
"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"),
external_code: "004", census_code: "04",
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," \
"243,293,226,289,209,285,195,283,177,297")
"228,202,240,216,241,232,263,243,293,241,301,245,302,254," \
"286,265,274,278,267,296,243,293,226,289,209,285,195,283," \
"177,297")
end

View File

@@ -10,6 +10,7 @@ class CreateInappropiateFlags < ActiveRecord::Migration[4.2]
end
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

View File

@@ -1,12 +1,19 @@
class CreateRelatedContent < ActiveRecord::Migration[4.2]
def change
create_table :related_contents do |t|
t.references :parent_relationable, polymorphic: true, index: { name: "index_related_contents_on_parent_relationable" }
t.references :child_relationable, polymorphic: true, index: { name: "index_related_contents_on_child_relationable" }
t.references :parent_relationable, polymorphic: true,
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.timestamps
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

View File

@@ -6,6 +6,10 @@ class CreateRelatedContentScores < ActiveRecord::Migration[4.2]
t.integer :value
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

View File

@@ -1,6 +1,8 @@
class RenameAdministratorTaskToDashboardAdministratorTask < ActiveRecord::Migration[4.2]
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
end
end

View File

@@ -29,6 +29,9 @@ class CreateLegislationPeopleProposalsTable < ActiveRecord::Migration[4.2]
t.boolean "validated"
t.integer "cached_votes_score", default: 0
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

View File

@@ -4,7 +4,9 @@ class CreateSDGRelations < ActiveRecord::Migration[5.2]
t.references :related_sdg, 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
end

View File

@@ -20,7 +20,9 @@ class CreateActiveStorageTables < ActiveRecord::Migration[5.2]
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
end
end

View File

@@ -1,6 +1,10 @@
class ManagerAuthenticator
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
def auth
@@ -13,7 +17,11 @@ class ManagerAuthenticator
private
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]))
@manager[:login] == parsed_response["USUARIO"]["LOGIN"]
rescue
@@ -21,13 +29,17 @@ class ManagerAuthenticator
end
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]
parsed_response = parser.parse(user_list_return)
aplication_value = parsed_response["APLICACIONES"]["APLICACION"]
# 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
false
end

View File

@@ -11,7 +11,8 @@ describe Account::PermissionsListComponent do
it "adds a hint when an action cannot be performed" do
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
end
end

View File

@@ -26,7 +26,8 @@ describe Admin::BudgetHeadings::FormComponent do
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

View File

@@ -6,7 +6,9 @@ describe Admin::Geozones::IndexComponent, :admin do
geozones = [
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_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")
]

View File

@@ -1,6 +1,7 @@
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 }
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)
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

View File

@@ -68,7 +68,8 @@ describe SDG::RelatedListSelectorComponent do
expect(page.find_field("Goals and Targets")["data-suggestions-list"]).to eq([{
tag: "1.1. Eradicate Extreme Poverty",
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"
}].to_json)
end

View File

@@ -10,7 +10,8 @@ describe DocumentsController do
document = create(:document, documentable: current_answer)
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
end

View File

@@ -30,7 +30,8 @@ describe Moderation::UsersController do
put :block, params: { id: user }
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
it "redirects to the index with a nested resource" do

View File

@@ -19,7 +19,9 @@ FactoryBot.define do
end
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

View File

@@ -14,7 +14,8 @@ describe SignatureSheetsHelper do
Setting["remote_census.request.postal_code"] = nil
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"
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
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_2 = "Required fields for each user must be separated by commas and each user must be separated by semicolons."
text_help_1 = "To verify a user, your application needs: " \
"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"
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
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_2 = "Required fields for each user must be separated by commas and each user must be separated by semicolons."
text_help_1 = "To verify a user, your application needs: " \
"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"
expect(required_fields_to_verify_text_help).to include(text_help_1)
@@ -47,8 +52,10 @@ describe SignatureSheetsHelper do
end
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_2 = "Required fields for each user must be separated by commas and each user must be separated by semicolons."
text_help_1 = "To verify a user, your application needs: " \
"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"
expect(required_fields_to_verify_text_help).to include(text_help_1)

View File

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

View File

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

View File

@@ -21,12 +21,16 @@ describe DocumentParser do
end
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, "00123456")).to eq(["123456", "0123456", "00123456"])
expect(DocumentParser.get_document_number_variants(1, "0123456"))
.to eq(["123456", "0123456", "00123456"])
expect(DocumentParser.get_document_number_variants(1, "00123456"))
.to eq(["123456", "0123456", "00123456"])
end
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

View File

@@ -185,7 +185,8 @@ describe "Consul Schema" do
it "returns nested votes for a proposal" do
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"]
expect(votes.count).to eq(2)

View File

@@ -1,21 +1,38 @@
require "rails_helper"
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
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
end
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
end
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
end
end
@@ -53,7 +70,8 @@ describe ManagerAuthenticator do
it "calls the permissions check method" do
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
end
end

View File

@@ -80,14 +80,16 @@ describe RemoteTranslations::Microsoft::Client do
response_another_start_text = [another_start_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)
.exactly(1)
.times
.and_return(response_another_start_text)
expect_any_instance_of(BingTranslator).to receive(:translate_array).with([end_another_text_en], to: :es)
.exactly(1)
.times
.and_return(response_another_end_text)
expect_any_instance_of(BingTranslator).to(receive(:translate_array)
.with([start_another_text_en], to: :es)
.exactly(1)
.times
.and_return(response_another_start_text))
expect_any_instance_of(BingTranslator).to(receive(:translate_array)
.with([end_another_text_en], to: :es)
.exactly(1)
.times
.and_return(response_another_end_text))
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, :finished, :with_winner)) }
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, :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_selecting_budget) { create(:budget_investment, budget: selecting_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_reviewing_budget) { create(:budget_investment, budget: reviewing_budget, author: user) }
let(:own_investment_in_selecting_budget) { create(:budget_investment, budget: selecting_budget, author: user) }
let(:own_investment_in_balloting_budget) { create(:budget_investment, budget: balloting_budget, author: user) }
let(:own_investment_in_accepting_budget) do
create(:budget_investment, budget: accepting_budget, author: user)
end
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_selecting_budget) { create(:budget_ballot, budget: selecting_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_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_other_geozone) { create(:poll_question, poll: expired_poll_from_other_geozone) }
let(:expired_poll_question_from_all_geozones) { create(:poll_question, poll: expired_poll) }
let(:expired_poll_question_from_own_geozone) do
create(:poll_question, poll: expired_poll_from_own_geozone)
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(:proposal_document) { build(:document, documentable: proposal) }

View File

@@ -8,9 +8,15 @@ describe Abilities::Valuator do
let(:group) { create(:valuator_group) }
let(:valuator) { create(:valuator, valuator_group: group, can_edit_dossier: true, can_comment: true) }
let(:non_assigned_investment) { create(:budget_investment) }
let(:assigned_investment) { create(:budget_investment, budget: create(:budget, :valuating), valuators: [valuator]) }
let(:group_assigned_investment) { create(:budget_investment, budget: create(:budget, :valuating), valuator_groups: [group]) }
let(:finished_assigned_investment) { create(:budget_investment, budget: create(:budget, :finished), valuators: [valuator]) }
let(:assigned_investment) do
create(:budget_investment, budget: create(:budget, :valuating), 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
assigned_investment.update!(valuation_finished: true)

View File

@@ -30,7 +30,9 @@ describe Ahoy::DataSource do
ds = Ahoy::DataSource.new
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
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

View File

@@ -714,7 +714,8 @@ describe Budget::Investment do
unselected_undecided_investment = create(:budget_investment, :unselected, :undecided)
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
it "does not return selected investments" do
@@ -732,8 +733,17 @@ describe Budget::Investment do
describe "sort_by_title" 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, title_en: "DDDD", title_es: "AAAA", description_en: "DDDD", description_es: "AAAA")
create(:budget_investment,
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]
end

View File

@@ -44,7 +44,9 @@ describe Budget::Result do
it "removes winners and recalculates" do
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, :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: 100, ballot_lines_count: 50)

View File

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

View File

@@ -62,12 +62,14 @@ describe Debate do
describe "#tag_list" 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
end
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
end
end
@@ -314,7 +316,9 @@ describe Debate do
describe "#confidence_score" 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)
debate = create(:debate, :with_confidence_score, cached_votes_up: 0, cached_votes_total: 100)

View File

@@ -10,10 +10,25 @@ describe DirectUpload do
end
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, :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
expect(build(:direct_upload,
:proposal,
:documents,
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
it "is not valid without resource_type" do

View File

@@ -10,16 +10,19 @@ RSpec.describe Legislation::Annotation, type: :model do
end
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" \
" erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut aliquip ex" \
" ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel illum" \
" dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril" \
" delenit augue duis dolore te feugait nulla facilisi." \
"\n\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. 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" \
quote = "ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh " \
"euismod tincidunt ut laoreet dolore magna aliquam erat volutpat. Ut wisi " \
"enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit " \
"lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum " \
"iriure dolor in hendrerit in vulputate velit esse molestie consequat, vel " \
"illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto " \
"odio dignissim qui blandit praesent luptatum zzril delenit augue duis " \
"dolore te feugait nulla facilisi.\n\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. 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"
annotation = create(
:legislation_annotation,
@@ -28,25 +31,37 @@ RSpec.describe Legislation::Annotation, type: :model do
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" \
" ut laoreet dolore magna aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper" \
" suscipit lobortis nisl ut aliquip ex ea commodo consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate velit" \
" esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui" \
" blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\n\nExpetenda 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. Usu nullam dolorum quaestio ei, sit vidit facilisis ea. Per ne impedit" \
" iracundia neglegentur. Consetetur neglegentur eum ut, vis animal legimus inimicus id.\n\nHis 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."
context = "Lorem " \
"<span class=annotator-hl>ipsum dolor sit amet, consectetuer adipiscing " \
"elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna " \
"aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci " \
"tation ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo " \
"consequat. Duis autem vel eum iriure dolor in hendrerit in vulputate " \
"velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis " \
"at vero eros et accumsan et iusto odio dignissim qui blandit praesent " \
"luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\n\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. 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)
end
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" \
" facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit augue duis dolore" \
" te feugait nulla facilisi.\r\n\r\nExpetenda 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"
quote = "Duis autem vel eum iriure dolor in hendrerit in vulputate velit esse " \
"molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero " \
"eros et accumsan et iusto odio dignissim qui 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"
annotation = create(
:legislation_annotation,
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 }]
)
context = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna" \
" aliquam erat volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation ullamcorper suscipit lobortis nisl ut" \
" aliquip ex ea commodo consequat. <span class=annotator-hl>Duis autem vel eum iriure dolor in hendrerit in vulputate velit" \
" esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui" \
" blandit praesent luptatum zzril delenit augue duis dolore te feugait nulla facilisi.\r\n\r\nExpetenda 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."
context = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam " \
"nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat " \
"volutpat. Ut wisi enim ad minim veniam, quis nostrud exerci tation " \
"ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat. " \
"<span class=annotator-hl>Duis autem vel eum iriure dolor in hendrerit " \
"in vulputate velit esse molestie consequat, vel illum dolore eu feugiat " \
"nulla facilisis at vero eros et accumsan et iusto odio dignissim qui " \
"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)
end
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" \
" to ensure cooperation with the community in the case of network server software.\r\n\r\nThe licenses for most software and" \
" other practical works are designed to take away your freedom to share and change the works. By contrast, our General Public" \
" Licenses are intended to guarantee your freedom to share 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 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), 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.\r\n\r\nDevelopers that use our General Public Licenses" \
" protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License which gives you" \
" legal permission to copy, distribute and/or modify the software.\r\n\r\nA secondary benefit of defending all users' freedom" \
" is that improvements made in alternate versions of the program, if they receive widespread use, become available for other" \
" developers to incorporate. Many developers of free software 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\nThe 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\nAn 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."
body = "The GNU Affero General Public License is a free, copyleft license for " \
"software and other kinds of works, specifically designed to ensure " \
"cooperation with the community in the case of network server software.\r\n\r\n" \
"The licenses for most software and other practical works are designed to " \
"take away your freedom to share and change the works. By contrast, our " \
"General Public Licenses are intended to guarantee your freedom to share and " \
"change all versions of a program--to make sure it remains free software for " \
"all its users.\r\n\r\n" \
"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), " \
"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.\r\n\r\n" \
"Developers that use our General Public Licenses protect your rights with two " \
"steps: (1) assert copyright on the software, and (2) offer you this License which " \
"gives you legal permission to copy, distribute and/or modify the software.\r\n\r\n" \
"A secondary benefit of defending all users' freedom is that improvements made in " \
"alternate versions of the program, if they receive widespread use, become " \
"available for other developers to incorporate. Many developers of free software " \
"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)
quote = "By contrast, our General Public Licenses are intended to guarantee your freedom to share 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 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)"
quote = "By contrast, our General Public Licenses are intended to guarantee your " \
"freedom to share and change all versions of a program--to make sure it " \
"remains free software for all its users.\r\n\r\n" \
"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(
:legislation_annotation,
@@ -101,13 +140,17 @@ RSpec.describe Legislation::Annotation, type: :model do
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" \
" works. <span class=annotator-hl>By contrast, our General Public Licenses are intended to guarantee your freedom to share" \
" 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" \
" 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)</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."
context = "The licenses for most software and other practical works are designed to " \
"take away your freedom to share and change the works. " \
"<span class=annotator-hl>By contrast, our General Public Licenses are " \
"intended to guarantee your freedom to share and change all versions of " \
"a program--to make sure it remains free software for all its users.\r\n\r\n" \
"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)" \
"</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)
end

View File

@@ -46,7 +46,9 @@ describe Legislation::Question do
describe "#next_question_id" do
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
expect(question1.next_question_id).to eq(question2.id)
@@ -59,7 +61,9 @@ describe Legislation::Question do
describe "#first_question_id" do
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
expect(question1.first_question_id).to eq(question1.id)

View File

@@ -196,7 +196,11 @@ describe Officing::Residence do
end
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
residence = build(:officing_residence, document_number: "12345678Z", year_of_birth: 1980)
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(:poll) { create(:poll, budget: budget) }
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) }
describe "#verify" do

View File

@@ -5,7 +5,9 @@ describe Poll::Shift do
let(:booth) { create(:poll_booth) }
let(:user) { create(:user, username: "Ana", email: "ana@example.com") }
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
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
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
it "is valid with same booth, officer and date but different task" do
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
it "is valid with same booth, officer and task but different date" do
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
@@ -58,7 +69,9 @@ describe Poll::Shift do
booth_assignment1 = 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
oa1 = officer_assignments.first
@@ -74,7 +87,9 @@ describe Poll::Shift do
expect(oa2.booth_assignment).to eq(booth_assignment2)
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)
end

View File

@@ -110,12 +110,14 @@ describe Proposal do
describe "tag_list" 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
end
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
end
end
@@ -256,7 +258,9 @@ describe Proposal do
user = create(:user, verified_at: Time.current)
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
@@ -623,7 +627,8 @@ describe Proposal 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)
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")
@@ -683,9 +688,9 @@ describe Proposal do
end
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)
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)
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)
some_comments = create(:proposal, title: "stop corruption", cached_votes_up: 3, comments_count: 10)
results = Proposal.search("stop corruption")

View File

@@ -10,9 +10,11 @@ describe RelatedContent do
end
it "allows relationables from various classes" do
expect(build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable)).to be_valid
expect(build(:related_content, parent_relationable: parent_relationable, child_relationable: child_relationable)).to be_valid
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
end
end
it "does not allow empty relationables" do
@@ -21,8 +23,15 @@ describe RelatedContent do
end
it "does not allow repeated related contents" do
related_content = create(:related_content, 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)
related_content = create(:related_content,
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
end
@@ -61,7 +70,12 @@ describe RelatedContent do
describe "create_opposite_related_content" do
let(:parent_relationable) { create(:proposal) }
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
expect { related_content.save }.to change { RelatedContent.count }.by(2)
@@ -72,8 +86,14 @@ describe RelatedContent do
describe "#relationed_contents" do
before do
related_content = create(:related_content, 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))
related_content = create(:related_content,
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
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])
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
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])
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
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