').text(error));
+ $("#tools input,textarea,button,select", form).removeAttr("disabled");
+}
+
+function update_tabs(from, to) {
+ $(".page-indicator div.page" + from).removeClass('active');
+ $(".page-indicator div.page" + to).addClass('active');
+}
\ No newline at end of file
diff --git a/app/assets/stylesheets/action_page.scss b/app/assets/stylesheets/action_page.scss
index 6ace3a726..7a30dde8c 100644
--- a/app/assets/stylesheets/action_page.scss
+++ b/app/assets/stylesheets/action_page.scss
@@ -1236,25 +1236,6 @@ html.js #affiliations {
}
}
-.partner-logos {
- display: flex;
- align-items: center;
- justify-content: space-evenly;
- flex-wrap: wrap;
- @media screen and (min-width: $lg) {
- flex-wrap: nowrap;
- }
- img {
- width: 100%;
- height: auto;
- max-width: 200px;
- padding: 1em;
- @media screen and (min-width: $md) {
- padding: 0 1em;
- }
- }
-}
-
#congress-message-create {
position: relative;
diff --git a/app/controllers/action_page_controller.rb b/app/controllers/action_page_controller.rb
index 8daf812f5..d1612a1aa 100644
--- a/app/controllers/action_page_controller.rb
+++ b/app/controllers/action_page_controller.rb
@@ -5,15 +5,15 @@ class ActionPageController < ApplicationController
:protect_unpublished,
:redirect_to_specified_url,
:redirect_from_archived_to_active_action,
- only: [:show, :show_by_institution, :embed_iframe,
- :signature_count, :filter]
+ only: %i[show show_by_institution embed_iframe
+ signature_count filter]
before_action :redirect_to_cannonical_slug, only: [:show]
- before_action :set_institution, only: [:show_by_institution, :filter]
- before_action :set_action_display_variables, only: [:show,
- :show_by_institution,
- :embed_iframe,
- :signature_count,
- :filter]
+ before_action :set_institution, only: %i[show_by_institution filter]
+ before_action :set_action_display_variables, only: %i[show
+ show_by_institution
+ embed_iframe
+ signature_count
+ filter]
skip_before_action :verify_authenticity_token, only: :embed
@@ -26,9 +26,9 @@ def show
end
def index
- @actionPages = ActionPage.where(published: true, archived: false, victory: false).
- paginate(page: params[:page], per_page: 9).
- order(created_at: :desc)
+ @actionPages = ActionPage.where(published: true, archived: false, victory: false)
+ .paginate(page: params[:page], per_page: 9)
+ .order(created_at: :desc)
@actionPages = @actionPages.categorized(params[:category]) if params[:category].present?
@@ -51,10 +51,10 @@ def embed_iframe
def signature_count
@actionPage = ActionPage.friendly.find(params[:id])
- if petition = @actionPage.petition
- render text: petition.signatures.count
+ if @actionPage.petition
+ render body: @actionPage.petition.signatures.count
else
- render text: "0"
+ render body: "0"
end
end
@@ -83,18 +83,14 @@ def protect_unpublished
end
def redirect_to_specified_url
- if @actionPage.enable_redirect
- redirect_to @actionPage.redirect_url, status: 301
- end
+ redirect_to @actionPage.redirect_url, status: 301, allow_other_host: true if @actionPage.enable_redirect
end
def redirect_from_archived_to_active_action
- if @actionPage.redirect_from_archived_to_active_action?
- # Users can access actions they've taken in the past as a historical record
- unless current_user and (current_user.taken_action? @actionPage or current_user.admin?)
- redirect_to @actionPage.active_action_page_for_redirect
- end
- end
+ return unless @actionPage.redirect_from_archived_to_active_action?
+ return if current_user&.can_view_archived?(@actionPage)
+
+ redirect_to @actionPage.active_action_page_for_redirect
end
def redirect_to_cannonical_slug
diff --git a/app/controllers/admin/action_pages_controller.rb b/app/controllers/admin/action_pages_controller.rb
index 5045b8f7a..7f11f6eed 100644
--- a/app/controllers/admin/action_pages_controller.rb
+++ b/app/controllers/admin/action_pages_controller.rb
@@ -2,34 +2,32 @@ class Admin::ActionPagesController < Admin::ApplicationController
include DateRange
include ActionPageDisplay
- before_action :set_action_page, only: [
- :edit,
- :update,
- :destroy,
- :events,
- :events_table,
- :duplicate,
- :preview,
- :status,
- :edit_partners
+ before_action :set_action_page, only: %i[
+ edit
+ update
+ destroy
+ events
+ events_table
+ duplicate
+ preview
+ status
+ edit_partners
]
- before_action :set_petition_targets, only: %i(new edit duplicate)
- before_action :set_partners, only: %i(new edit duplicate)
- before_action :set_source_files, only: %i(new edit create update duplicate)
+ before_action :set_petition_targets, only: %i[new edit duplicate]
+ before_action :set_partners, only: %i[new edit duplicate]
+ before_action :set_source_files, only: %i[new edit create update duplicate]
- after_action :purge_cache, only: [:update, :publish]
+ after_action :purge_cache, only: %i[update publish]
allow_collaborators_to :index, :edit
def index
- @categories = Category.all.order(:title)
+ @categories = Category.order(:title)
@authors = User.authors.order(:last_name)
@actionPages = filter_action_pages
- if request.xhr?
- render partial: "admin/action_pages/index"
- end
+ render partial: "admin/action_pages/index" if request.xhr?
end
def new
@@ -64,26 +62,19 @@ def edit
@actionPage.email_campaign ||= EmailCampaign.new
@actionPage.congress_message_campaign ||= CongressMessageCampaign.new
10.times { @actionPage.affiliation_types.build }
- if @actionPage.enable_petition && @actionPage.petition.enable_affiliations
- @target_category = @actionPage.institutions.first.category
- end
+ @target_category = @actionPage.institutions.first.category if @actionPage.enable_petition && @actionPage.petition.enable_affiliations
end
- def status
- end
+ def status; end
def edit_partners
@partners = Partner.order(name: :desc)
end
def update
- @actionPage.background_image = nil if params[:destroy_background_image]
- @actionPage.featured_image = nil if params[:destroy_featured_image]
- @actionPage.og_image = nil if params[:destroy_og_image]
-
- @actionPage.update_attributes(action_page_params)
+ @actionPage.update(action_page_params)
if (institutions_params[:reset] && institutions_params[:reset] == "1") ||
- (institutions_params[:category] && @actionPage.institutions.empty?)
+ (institutions_params[:category] && @actionPage.institutions.empty?)
ActionInstitution.add(action_page: @actionPage,
**institutions_params.to_h.symbolize_keys)
end
@@ -96,12 +87,11 @@ def destroy
redirect_to admin_action_pages_path, notice: "Deleted action page: #{@actionPage.title}"
end
-
def preview
@actionPage.attributes = action_page_params
if @actionPage.enable_redirect
- redirect_to @actionPage.redirect_url, status: 301
+ redirect_to @actionPage.redirect_url, status: 301
return
end
@@ -132,9 +122,9 @@ def events
end
format.json do
render json: @events.chart_data(
- type: params[:type],
- range: @start_date..@end_date
- )
+ type: params[:type],
+ range: @start_date..@end_date
+ )
end
end
end
@@ -144,9 +134,7 @@ def events_table
@events = @actionPage.events.in_range(@start_date, @end_date)
@counts = @events.table_data
@summary = @events.summary
- if @actionPage.enable_congress_message?
- @fills = @actionPage.congress_message_campaign.date_fills(@start_date, @end_date)
- end
+ @fills = @actionPage.congress_message_campaign.date_fills(@start_date, @end_date) if @actionPage.enable_congress_message?
end
def homepage
@@ -183,25 +171,26 @@ def set_partners
def action_page_params
params.require(:action_page).permit(
- :title, :summary, :description, :category_id, :related_content_url, :featured_image,
+ :title, :summary, :description, :category_id, :related_content_url, :remote_featured_image_url,
:enable_call, :enable_petition, :enable_email, :enable_tweet,
- :enable_congress_message, :og_title, :og_image, :share_message, :published,
+ :enable_congress_message, :og_title, :remote_og_image_url, :share_message, :published,
:call_campaign_id, :what_to_say, :redirect_url, :email_text, :enable_redirect,
:victory, :victory_message, :archived_redirect_action_page_id, :archived, :status,
partner_ids: [],
- action_page_images_attributes: [:id, :action_page_image],
- call_campaign_attributes: [:id, :title, :message, :call_campaign_id],
- petition_attributes: [:id, :title, :description, :goal, :enable_affiliations],
- affiliation_types_attributes: [:id, :name],
+ action_page_images_attributes: %i[id action_page_image],
+ call_campaign_attributes: %i[id title message call_campaign_id],
+ petition_attributes: %i[id title description goal enable_affiliations],
+ affiliation_types_attributes: %i[id name],
tweet_attributes: [
:id, :target, :target_house, :target_senate, :message, :cta, :bioguide_id,
- tweet_targets_attributes: [:id, :_destroy, :twitter_id, :image]
+ { tweet_targets_attributes: %i[id _destroy twitter_id image] }
],
- email_campaign_attributes: [
- :id, :message, :subject, :target_house, :target_senate, :target_email,
- :email_addresses, :target_bioguide_id, :bioguide_id, :alt_text_email_your_rep,
- :alt_text_look_up_your_rep, :alt_text_extra_fields_explain, :topic_category_id,
- :alt_text_look_up_helper, :alt_text_customize_message_helper, :campaign_tag
+ email_campaign_attributes: %i[
+ id message subject state target_state_lower_chamber target_state_upper_chamber
+ target_governor target_email email_addresses target_bioguide_id
+ bioguide_id alt_text_email_your_rep alt_text_look_up_your_rep
+ alt_text_extra_fields_explain topic_category_id alt_text_look_up_helper
+ alt_text_customize_message_helper campaign_tag
],
congress_message_campaign_attributes: [
:id, :message, :subject, :target_house, :target_senate, { target_bioguide_list: [] },
@@ -210,18 +199,19 @@ def action_page_params
:alt_text_customize_message_helper, :campaign_tag,
:enable_customization_notice
],
- partnerships_attributes: [:id, :enable_mailings]
+ partnerships_attributes: %i[id enable_mailings]
)
end
def institutions_params
- return {} unless params.has_key? :institutions
- params.require(:institutions).permit(%i(category reset))
+ return {} unless params.key? :institutions
+
+ params.require(:institutions).permit(%i[category reset])
end
def filter_params
params.permit(:q, :date_range, :utf8,
- action_filters: %i(type status author category))
+ action_filters: %i[type status author category])
end
def purge_cache
diff --git a/app/controllers/admin/application_controller.rb b/app/controllers/admin/application_controller.rb
index 3eedde808..fee652024 100644
--- a/app/controllers/admin/application_controller.rb
+++ b/app/controllers/admin/application_controller.rb
@@ -6,25 +6,19 @@ def manifest
self.class.manifest || "admin"
end
- protected
-
+ # FLAG_AS_UNUSED
def self.allow_collaborators_to(*actions)
skip_before_action :must_be_admin, only: actions
before_action :must_be_admin_or_collaborator, only: actions
end
def must_be_admin
- unless user_signed_in? && current_user.admin?
- raise ActiveRecord::RecordNotFound
- end
+ raise ActiveRecord::RecordNotFound unless user_signed_in? && current_user.admin?
end
def must_be_admin_or_collaborator
- unless user_signed_in? && (current_user.admin? || current_user.collaborator?)
- raise ActiveRecord::RecordNotFound
- end
+ raise ActiveRecord::RecordNotFound unless user_signed_in? && (current_user.admin? || current_user.collaborator?)
end
- def images
- end
+ def images; end
end
diff --git a/app/controllers/admin/congress_message_campaigns_controller.rb b/app/controllers/admin/congress_message_campaigns_controller.rb
index 492ac7fd0..78360652d 100644
--- a/app/controllers/admin/congress_message_campaigns_controller.rb
+++ b/app/controllers/admin/congress_message_campaigns_controller.rb
@@ -3,8 +3,7 @@ class Admin::CongressMessageCampaignsController < Admin::ApplicationController
allow_collaborators_to :congress_tabulation, :staffer_report
- def congress_tabulation
- end
+ def congress_tabulation; end
def staffer_report
@bioguide_id = params[:bioguide_id]
diff --git a/app/controllers/admin/events_controller.rb b/app/controllers/admin/events_controller.rb
index 3bd605300..97b29d105 100644
--- a/app/controllers/admin/events_controller.rb
+++ b/app/controllers/admin/events_controller.rb
@@ -6,12 +6,12 @@ def index
@events = Ahoy::Event.all.in_range(@start_date, @end_date)
respond_to do |format|
format.html { @summary = @events.summary }
- format.json {
+ format.json do
render json: @events.chart_data(
- type: params[:type],
- range: @start_date..@end_date
- )
- }
+ type: params[:type],
+ range: @start_date..@end_date
+ )
+ end
end
end
end
diff --git a/app/controllers/admin/images_controller.rb b/app/controllers/admin/images_controller.rb
index d89edf4a7..774771fc9 100644
--- a/app/controllers/admin/images_controller.rb
+++ b/app/controllers/admin/images_controller.rb
@@ -1,4 +1,3 @@
class Admin::ImagesController < Admin::ApplicationController
- def index
- end
+ def index; end
end
diff --git a/app/controllers/admin/institutions_controller.rb b/app/controllers/admin/institutions_controller.rb
index 6b6c0a563..ca2783305 100644
--- a/app/controllers/admin/institutions_controller.rb
+++ b/app/controllers/admin/institutions_controller.rb
@@ -1,13 +1,11 @@
class Admin::InstitutionsController < Admin::ApplicationController
- before_action :set_institution, only: %i(destroy edit update)
- before_action :set_categories, only: %i(new edit upload index)
+ before_action :set_institution, only: %i[destroy edit update]
+ before_action :set_categories, only: %i[new edit upload index]
def index
- @institutions = Institution.includes(:action_pages).all.order(created_at: :desc)
+ @institutions = Institution.includes(:action_pages).order(created_at: :desc)
@institutions = @institutions.search(params[:q]) if params[:q].present?
- if params[:category].present? && params[:category] != "All"
- @institutions = @institutions.where(category: params[:category])
- end
+ @institutions = @institutions.where(category: params[:category]) if params[:category].present? && params[:category] != "All"
@institutions = @institutions.paginate(page: params[:page], per_page: 20)
end
@@ -42,11 +40,7 @@ def import
if names.empty?
redirect_to action: "upload", notice: "Import failed. Please check CSV formatting"
else
- category = if import_params[:new_category].blank?
- import_params[:category]
- else
- import_params[:new_category]
- end
+ category = import_params[:new_category].presence || import_params[:category]
Institution.delay.import(category, names)
redirect_to action: "index", notice: "Successfully imported #{names.length} targets"
end
diff --git a/app/controllers/admin/partners_controller.rb b/app/controllers/admin/partners_controller.rb
index d3bb7080b..3fce9ce28 100644
--- a/app/controllers/admin/partners_controller.rb
+++ b/app/controllers/admin/partners_controller.rb
@@ -1,7 +1,7 @@
class Admin::PartnersController < Admin::ApplicationController
layout "admin"
- before_action :set_partner, only: %i(edit update show destroy)
+ before_action :set_partner, only: %i[edit update show destroy]
# GET /partners
# GET /partners.json
@@ -22,16 +22,15 @@ def create
respond_to do |format|
if @partner.save
format.html { redirect_to @partner, notice: "Partner was successfully created." }
- format.json { render "show", status: :created, location: @partner }
+ format.json { render "show", status: 201, location: @partner }
else
format.html { render "new" }
- format.json { render json: @partner.errors, status: :unprocessable_entity }
+ format.json { render json: @partner.errors, status: 422 }
end
end
end
- def edit
- end
+ def edit; end
def update
if @partner.update(partner_params)
diff --git a/app/controllers/admin/petitions_controller.rb b/app/controllers/admin/petitions_controller.rb
index 331e767dd..1fde4420d 100644
--- a/app/controllers/admin/petitions_controller.rb
+++ b/app/controllers/admin/petitions_controller.rb
@@ -1,5 +1,5 @@
-include PetitionHelper
class Admin::PetitionsController < Admin::ApplicationController
+ include PetitionHelper
before_action :set_petition
allow_collaborators_to :show, :destroy_signatures
@@ -25,8 +25,8 @@ def affiliation_csv
signatures = @petition.signatures
if params[:institution_id].present?
- signatures = signatures.joins(affiliations: :institution).
- where(institutions: { id: params[:institution_id] })
+ signatures = signatures.joins(affiliations: :institution)
+ .where(institutions: { id: params[:institution_id] })
end
send_data signatures.to_affiliation_csv,
@@ -36,9 +36,7 @@ def affiliation_csv
def destroy_signatures
@petition.signatures.where(id: params[:signature_ids]).delete_all
- if params[:page].to_i > filtered_signatures.total_pages
- params[:page] = filtered_signatures.total_pages
- end
+ params[:page] = filtered_signatures.total_pages if params[:page].to_i > filtered_signatures.total_pages
redirect_to admin_action_page_petition_path(@petition.action_page,
@petition, search_params)
@@ -51,10 +49,10 @@ def set_petition
end
def filtered_signatures
- @petition.signatures.
- filter(params[:query]).
- order(created_at: :desc).
- paginate(page: params[:page], per_page: params[:per_page] || 10)
+ @petition.signatures
+ .search(params[:query])
+ .order(created_at: :desc)
+ .paginate(page: params[:page], per_page: params[:per_page] || 10)
end
def search_params
diff --git a/app/controllers/admin/s3_uploads_controller.rb b/app/controllers/admin/s3_uploads_controller.rb
index 78bca4f4b..5e80050c1 100644
--- a/app/controllers/admin/s3_uploads_controller.rb
+++ b/app/controllers/admin/s3_uploads_controller.rb
@@ -2,11 +2,11 @@ class Admin::S3UploadsController < Admin::ApplicationController
# GET /admin/source_files
# GET /admin/source_files.json
def index
- if params[:f].present?
- source_files = SourceFile.where("LOWER(file_name) LIKE ?", "%#{params[:f]}%".downcase)
- else
- source_files = SourceFile.limit(3)
- end
+ source_files = if params[:f].present?
+ SourceFile.where("LOWER(file_name) LIKE ?", "%#{params[:f]}%".downcase)
+ else
+ SourceFile.limit(3)
+ end
source_files = source_files.order(created_at: :desc)
@@ -22,15 +22,15 @@ def create
@source_file = SourceFile.new(parameters)
respond_to do |format|
if @source_file.save
- format.html {
+ format.html do
render json: @source_file.to_jq_upload,
- content_type: "text/html",
- layout: false
- }
- format.json { render json: @source_file.to_jq_upload, status: :created }
+ content_type: "text/html",
+ layout: false
+ end
+ format.json { render json: @source_file.to_jq_upload, status: 201 }
else
format.html { render "new" }
- format.json { render json: @source_file.errors, status: :unprocessable_entity }
+ format.json { render json: @source_file.errors, status: 422 }
end
end
end
@@ -52,7 +52,7 @@ def destroy
# for /admin/action_page/new
# GET /admin/source_files/generate_key
def generate_key
- uid = SecureRandom.uuid.gsub(/-/, "")
+ uid = SecureRandom.uuid.delete("-")
render json: {
key: "uploads/#{uid}/#{params[:filename]}",
diff --git a/app/controllers/admin/topic_categories_controller.rb b/app/controllers/admin/topic_categories_controller.rb
index 7242e9818..111bd1d8c 100644
--- a/app/controllers/admin/topic_categories_controller.rb
+++ b/app/controllers/admin/topic_categories_controller.rb
@@ -14,18 +14,16 @@ def create
end
def destroy
- begin
- TopicCategory.destroy(params[:id])
- render json: { id: params[:id] }
- rescue => e
- render text: e.message, status: 500
- end
+ TopicCategory.destroy(params[:id])
+ render json: { id: params[:id] }
+ rescue StandardError => e
+ render body: e.message, status: 500
end
def update
topic_category = TopicCategory.find(params[:id])
- if topic_category.update_attributes(topic_category_params)
+ if topic_category.update(topic_category_params)
render json: topic_category
else
render json: topic_category.errors, status: 500
diff --git a/app/controllers/admin/topic_sets_controller.rb b/app/controllers/admin/topic_sets_controller.rb
index 6ca7cb6db..7dab61a0b 100644
--- a/app/controllers/admin/topic_sets_controller.rb
+++ b/app/controllers/admin/topic_sets_controller.rb
@@ -1,16 +1,14 @@
class Admin::TopicSetsController < Admin::ApplicationController
def index
- topic_sets = TopicSet.all.order(:tier)
+ topic_sets = TopicSet.order(:tier)
render json: topic_sets
end
def destroy
- begin
- TopicSet.destroy(params[:id])
- render json: { id: params[:id] }
- rescue => e
- render text: e.message, status: 500
- end
+ TopicSet.destroy(params[:id])
+ render json: { id: params[:id] }
+ rescue StandardError => e
+ render body: e.message, status: 500
end
def create
@@ -28,7 +26,7 @@ def create
def update
topic_set = TopicSet.find(params[:id])
- if topic_set.update_attributes(topic_set_params)
+ if topic_set.update(topic_set_params)
render json: topic_set
else
render json: topic_set.errors, status: 500
diff --git a/app/controllers/admin/topics_controller.rb b/app/controllers/admin/topics_controller.rb
index a635cbb3f..ba41bb634 100644
--- a/app/controllers/admin/topics_controller.rb
+++ b/app/controllers/admin/topics_controller.rb
@@ -2,12 +2,10 @@ class Admin::TopicsController < Admin::ApplicationController
layout "admin"
def destroy
- begin
- Topic.destroy(params[:id])
- render json: { id: params[:id] }
- rescue => e
- render text: e.message, status: 500
- end
+ Topic.destroy(params[:id])
+ render json: { id: params[:id] }
+ rescue StandardError => e
+ render body: e.message, status: 500
end
def create
diff --git a/app/controllers/admin/users_controller.rb b/app/controllers/admin/users_controller.rb
index eb37ff0bb..38453b79f 100644
--- a/app/controllers/admin/users_controller.rb
+++ b/app/controllers/admin/users_controller.rb
@@ -6,7 +6,7 @@ def index
def update
user = User.find(params[:id])
- if user.update_attributes(user_params)
+ if user.update(user_params)
flash[:notice] = "#{user.email} was updated"
else
flash[:error] = "Could not update #{user.email}"
diff --git a/app/controllers/ahoy_controller.rb b/app/controllers/ahoy_controller.rb
index 83a56264c..8a6d70b83 100644
--- a/app/controllers/ahoy_controller.rb
+++ b/app/controllers/ahoy_controller.rb
@@ -1,15 +1,14 @@
class AhoyController < ApplicationController
before_action :set_ahoy_cookies
before_action :track_ahoy_visit
- before_action :set_ahoy_request_store
def visit
action_type = params.require(:action_type)
action_page_id = params.require(:action_page_id)
ahoy.track "View",
- { type: "action", actionType: action_type, actionPageId: action_page_id },
- action_page_id: action_page_id
+ { type: "action", actionType: action_type, actionPageId: action_page_id },
+ action_page_id: action_page_id
send_data image_asset, content_type: "image/gif"
end
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 0c4c4f5c2..71ebe9d3d 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -11,23 +11,17 @@ class ApplicationController < ActionController::Base
before_action :set_locale
before_action :user_conditional_logic
- skip_before_action :set_ahoy_cookies
skip_before_action :track_ahoy_visit
- skip_before_action :set_ahoy_request_store
def user_conditional_logic
- if user_signed_in?
- lock_users_with_expired_passwords! unless user_is_being_told_to_reset_pass_or_is_resetting_pass?
- end
+ lock_users_with_expired_passwords! if user_signed_in? && !user_is_being_told_to_reset_pass_or_is_resetting_pass?
end
# This method seems to check if the request is coming from a domain listed in
# `cors_allowed_domains` in application.yml, and if it is, the response gets
# a header allowing the requesting domain to use this app's CRUD
def cors
- if Actioncenter::Application.config.cors_allowed_domains.include? request.env["HTTP_ORIGIN"] or Actioncenter::Application.config.cors_allowed_domains.include? "*"
- response.headers["Access-Control-Allow-Origin"] = request.env["HTTP_ORIGIN"]
- end
+ response.headers["Access-Control-Allow-Origin"] = request.env["HTTP_ORIGIN"] if Actioncenter::Application.config.cors_allowed_domains.include?(request.env["HTTP_ORIGIN"]) || Actioncenter::Application.config.cors_allowed_domains.include?("*")
end
def self.manifest(value = nil)
@@ -60,7 +54,7 @@ def user_is_being_told_to_reset_pass_or_is_resetting_pass?
def configure_permitted_parameters
devise_parameter_sanitizer.permit(:sign_up,
- keys: [:record_activity, :subscribe])
+ keys: %i[record_activity subscribe])
end
def set_locale
diff --git a/app/controllers/concerns/action_page_display.rb b/app/controllers/concerns/action_page_display.rb
index f31507472..ca926275d 100644
--- a/app/controllers/concerns/action_page_display.rb
+++ b/app/controllers/concerns/action_page_display.rb
@@ -11,22 +11,25 @@ def set_action_display_variables
@congress_message_campaign = @actionPage.congress_message_campaign
# Shows a mailing list if no tools enabled
- @no_tools = [:tweet, :petition, :call, :email, :congress_message].none? do |tool|
+ @no_tools = %i[tweet petition call email congress_message].none? do |tool|
@actionPage.send "enable_#{tool}".to_sym
end
set_signatures
- if @actionPage.petition and @actionPage.petition.enable_affiliations
- @top_institutions = @actionPage.institutions.top(300, first: @institution.try(:id))
+ if @actionPage.petition&.enable_affiliations
+ @top_institutions = [
+ @institution,
+ TopInstitutionsQuery.run(action_page: @actionPage,
+ limit: 300,
+ exclude: [@institution])
+ ].flatten
@institutions = @actionPage.institutions.order(:name)
@institution_category = @institutions.first.category
end
@topic_category = nil
- if @email_campaign and !@email_campaign.topic_category.nil?
- @topic_category = @email_campaign.topic_category.as_2d_array
- end
+ @topic_category = @email_campaign.topic_category.as_2d_array if @email_campaign && !@email_campaign.topic_category.nil?
# Initialize a temporary signature object for form auto-population
current_zipcode = params[:zipcode] || current_user.try(:zipcode)
@@ -53,18 +56,17 @@ def set_signatures
@institution_signature_count = @signatures.pretty_count
elsif @petition.enable_affiliations
@signatures = @petition.signatures
- .includes(affiliations: [:institution, :affiliation_type])
+ .includes(affiliations: %i[institution affiliation_type])
else
@signatures = @petition.signatures
end
@signatures = @signatures
- .paginate(page: params[:page], per_page: 9)
- .order(created_at: :desc)
+ .paginate(page: params[:page], per_page: 9)
+ .order(created_at: :desc)
@signature_count = @petition.signatures.pretty_count
@require_location = !@petition.enable_affiliations
end
end
-
end
diff --git a/app/controllers/concerns/date_range.rb b/app/controllers/concerns/date_range.rb
index ccefc3f4f..eae82f3f3 100644
--- a/app/controllers/concerns/date_range.rb
+++ b/app/controllers/concerns/date_range.rb
@@ -7,10 +7,9 @@ def set_dates
def process_dates(date_range_text: nil, date_text: nil, **_)
return parse_date_range(date_range_text) if date_range_text.present?
- return [1.month.ago, Time.zone.now] unless date_text.present?
- if date_text == "Action lifetime" && @actionPage.present?
- return [@actionPage.created_at, Time.zone.now]
- end
+ return [1.month.ago, Time.zone.now] if date_text.blank?
+ return [@actionPage.created_at, Time.zone.now] if date_text == "Action lifetime" && @actionPage.present?
+
[parse_time_ago(date_text), Time.zone.now]
end
@@ -21,12 +20,14 @@ def parse_date_range(date_range_string)
# Convert Last X (days|weeks|months) to a time
def parse_time_ago(string)
_, count, unit = string.split(" ")
- return Time.zone.now - 1.month unless %w(days weeks months years).include? unit
+ return Time.zone.now - 1.month unless %w[days weeks months years].include? unit
+
Time.zone.now - count.to_i.send(unit)
end
def date_range_string
return "" unless @start_date && @end_date
+
format = "%Y-%m-%d"
"#{@start_date.strftime(format)} - #{@end_date.strftime(format)}"
end
diff --git a/app/controllers/concerns/logged_invisible_captcha.rb b/app/controllers/concerns/logged_invisible_captcha.rb
index 13885594d..a2b48f633 100644
--- a/app/controllers/concerns/logged_invisible_captcha.rb
+++ b/app/controllers/concerns/logged_invisible_captcha.rb
@@ -3,12 +3,12 @@ module LoggedInvisibleCaptcha
def on_spam(options = {})
log_failure
- super options
+ super(options)
end
def on_timestamp_spam(options = {})
log_failure
- super options
+ super(options)
end
def log_failure
diff --git a/app/controllers/concerns/tooling.rb b/app/controllers/concerns/tooling.rb
index e7b0cbef3..3a4605e16 100644
--- a/app/controllers/concerns/tooling.rb
+++ b/app/controllers/concerns/tooling.rb
@@ -5,17 +5,14 @@ module Tooling
def create_partner_subscription
return unless @action_page
+
@action_page.partners.each do |partner|
- if params["#{partner.code}_subscribe"] == "1"
- Subscription.create(partner_signup_params.merge(partner: partner))
- end
+ Subscription.create(partner_signup_params.merge(partner: partner)) if params["#{partner.code}_subscribe"] == "1"
end
end
def deliver_thanks_message
@email ||= current_user.try(:email) || params[:email] || params.dig(:subscription, :email)
- if @email.present?
- UserMailer.thanks_message(@email, @action_page, user: @user, name: @name).deliver_now
- end
+ UserMailer.thanks_message(@email, @action_page, user: @user, name: @name).deliver_now if @email.present?
end
end
diff --git a/app/controllers/congress_messages_controller.rb b/app/controllers/congress_messages_controller.rb
index 0bc6ab8aa..6b8976753 100644
--- a/app/controllers/congress_messages_controller.rb
+++ b/app/controllers/congress_messages_controller.rb
@@ -22,7 +22,7 @@ def new
end
forms, @links = CongressForms::Form.find(bioguide_ids)
@defunct_members, @members = @members.partition do |m|
- @links.keys.include? m.bioguide_id
+ @links.key?(m.bioguide_id)
end
@message = CongressMessage.new_from_lookup(location, @campaign, forms)
render partial: "form"
@@ -37,16 +37,16 @@ def create
else
params[:forms][:bioguide_ids]
end
- @message.forms, _ = CongressForms::Form.find(bioguide_ids)
+ @message.forms, = CongressForms::Form.find(bioguide_ids)
- if EmailValidator.valid?(user_params[:email]) && @message.background_submit(params[:test])
+ if EmailValidator.valid?(user_params[:email]) && @message.background_submit(test: params[:test])
@name = user_params[:first_name] # for deliver_thanks_message
@email = user_params[:email] # for deliver_thanks_message
track_action unless params[:test]
deliver_thanks_message unless subscribe_user
render partial: "tools/share"
else
- render plain: I18n.t(:invalid_submission, scope: :congress_forms), status: :bad_request
+ render plain: I18n.t(:invalid_submission, scope: :congress_forms), status: 400
end
end
@@ -84,35 +84,33 @@ def partner_signup_params
end
def update_user
- if params[:update_user_data] == "yes"
- current_user.update(user_params.except(:email))
- end
+ current_user.update(user_params.except(:email)) if params[:update_user_data] == "yes"
end
def subscribe_user
create_partner_subscription
if params[:subscribe] == "1"
- source = "action center congress message :: " + @action_page.title
+ source = "action center congress message :: #{@action_page.title}"
user = User.find_or_initialize_by(email: user_params[:email])
user.attributes = user_params
- user.subscribe!(opt_in = false, source = source)["requires_confirmation"]
+ user.subscribe!(opt_in: false, source: source)["requires_confirmation"]
end
end
def track_action
customized_message = params[:message] != @campaign.message
ahoy.track "Action",
- { type: "action", actionType: "congress_message", actionPageId: params[:action_id],
- customizedMessage: customized_message },
- action_page: @action_page
+ { type: "action", actionType: "congress_message", actionPageId: params[:action_id],
+ customizedMessage: customized_message },
+ action_page: @action_page
end
def address_not_found
- render plain: I18n.t(:address_lookup_failed, scope: :congress_forms), status: :bad_request
+ render plain: I18n.t(:address_lookup_failed, scope: :congress_forms), status: 400
end
def congress_forms_request_failed
- render plain: I18n.t(:request_failed, scope: :congress_forms), status: :internal_server_error
+ render plain: I18n.t(:request_failed, scope: :congress_forms), status: 500
end
end
diff --git a/app/controllers/partners_controller.rb b/app/controllers/partners_controller.rb
index 515f87f8b..ccb77b04d 100644
--- a/app/controllers/partners_controller.rb
+++ b/app/controllers/partners_controller.rb
@@ -6,9 +6,9 @@ class PartnersController < ApplicationController
# GET /partners/1
# GET /partners/1.json
def show
- @subscriptions = @partner.subscriptions.
- paginate(page: params[:page], per_page: 10).
- order("id desc")
+ @subscriptions = @partner.subscriptions
+ .paginate(page: params[:page], per_page: 10)
+ .order("id desc")
end
def csv
@@ -24,24 +24,22 @@ def update
format.json { head :no_content }
else
format.html { render "edit" }
- format.json { render json: @partner.errors, status: :unprocessable_entity }
+ format.json { render json: @partner.errors, status: 422 }
end
end
end
def add_user
- user = User.find_by_email(params[:email])
+ user = User.find_by(email: params[:email])
if user.nil?
flash[:notice] = "Couldn't find a user by email #{params[:email]}"
+ elsif user.partner == @partner
+ flash[:notice] = "That user is already linked to #{@partner.name}"
+ elsif user.partner.nil?
+ user.partner = @partner
+ user.save
else
- if user.partner.nil?
- user.partner = @partner
- user.save
- elsif user.partner == @partner
- flash[:notice] = "That user is already linked to #{@partner.name}"
- else
- flash[:notice] = "That user is linked to another partner: #{user.partner.name}"
- end
+ flash[:notice] = "That user is linked to another partner: #{user.partner.name}"
end
redirect_to @partner
end
@@ -66,9 +64,7 @@ def set_partner
def authenticate
authenticate_user!
- unless current_user.admin?
- raise ActiveRecord::RecordNotFound if current_user.partner != @partner
- end
+ raise ActiveRecord::RecordNotFound if !current_user.admin? && (current_user.partner != @partner)
end
# Never trust parameters from the scary internet, only allow the white list through.
diff --git a/app/controllers/registrations_controller.rb b/app/controllers/registrations_controller.rb
index 1254ffa85..1ea3f7de9 100644
--- a/app/controllers/registrations_controller.rb
+++ b/app/controllers/registrations_controller.rb
@@ -21,16 +21,14 @@ def update
private
def handle_nonunique_email
- resource.errors.delete(:email)
+ resource.errors.delete(:email) unless resource.errors[:email].size > 1
if resource.errors.empty?
- existing = User.find_by_email(resource.email)
+ existing = User.find_by(email: resource.email)
existing.send_email_taken_notice
# Allow unconfirmed users to set a new password by re-registering.
- if !existing.confirmed?
- existing.update_attributes(sign_up_params)
- end
+ existing.update(sign_up_params) unless existing.confirmed?
if resource.persisted?
resource.update_attribute(:unconfirmed_email, account_update_params[:email])
diff --git a/app/controllers/robots_controller.rb b/app/controllers/robots_controller.rb
index be90d584c..208100dda 100644
--- a/app/controllers/robots_controller.rb
+++ b/app/controllers/robots_controller.rb
@@ -1,9 +1,9 @@
class RobotsController < ApplicationController
def show
- if Rails.env.development? or Rails.application.secrets.enable_basic_auth == "true"
- render text: "User-agent: *\nDisallow: /"
+ if Rails.env.development? || (Rails.application.secrets.enable_basic_auth == "true")
+ render body: "User-agent: *\nDisallow: /"
else
- render text: ""
+ render body: ""
end
end
@@ -11,9 +11,9 @@ def show
# for load balancing/ database connection detecting
def heartbeat
if User.count >= 0
- render text: "Application Heart Beating OK"
+ render body: "Application Heart Beating OK"
else
- render text: "There's something odd about the database, probably disconnected...", status: 500
+ render body: "There's something odd about the database, probably disconnected...", status: 500
end
end
end
diff --git a/app/controllers/sessions_controller.rb b/app/controllers/sessions_controller.rb
index c86631eb7..e2f0fc452 100644
--- a/app/controllers/sessions_controller.rb
+++ b/app/controllers/sessions_controller.rb
@@ -3,7 +3,7 @@ class SessionsController < Devise::SessionsController
before_action :unset_logged_in, only: :destroy
def set_logged_in
- if (user_signed_in?)
+ if user_signed_in?
# Sets a "permanent" cookie (which expires in 20 years from now).
# This is exclusively used to never cache content for logged in users
cookies.permanent[:logged_in] = "I <3 EFF"
diff --git a/app/controllers/smarty_streets_controller.rb b/app/controllers/smarty_streets_controller.rb
index 3377aed18..6645415db 100644
--- a/app/controllers/smarty_streets_controller.rb
+++ b/app/controllers/smarty_streets_controller.rb
@@ -9,10 +9,13 @@ def street_address
render json: get_data_on_address_zip(params), status: 200
end
- # This endpoint appears unused
- def suggest
- render json: get_suggestions_for_address(params), status: 200
- end
+ # This endpoint appears unused (TheNotary 1/16)
+ # Lets remove it and see if anything breaks! (jparr 4/23)
+ # todo: remove if not used
+
+ # def suggest
+ # render json: get_suggestions_for_address(params), status: 200
+ # end
private
@@ -38,10 +41,8 @@ def authorize_query(params)
end
def proxy_request(url)
- begin
- return RestClient.get url, accept: :json, 'X-Include-Invalid': "true"
- rescue => e
- logger.error e
- end
+ RestClient.get url, accept: :json, 'X-Include-Invalid': "true"
+ rescue StandardError => e
+ logger.error e
end
end
diff --git a/app/controllers/sns_controller.rb b/app/controllers/sns_controller.rb
index 00eb8ffb5..191704e3c 100644
--- a/app/controllers/sns_controller.rb
+++ b/app/controllers/sns_controller.rb
@@ -40,7 +40,7 @@ def set_context
def set_message
body = JSON.parse(request.body.read)
- return JSON.parse(body["Message"])
+ JSON.parse(body["Message"])
end
def log_request
diff --git a/app/controllers/subscriptions_controller.rb b/app/controllers/subscriptions_controller.rb
index 95dcbe585..7554a5200 100644
--- a/app/controllers/subscriptions_controller.rb
+++ b/app/controllers/subscriptions_controller.rb
@@ -9,14 +9,14 @@ class SubscriptionsController < ApplicationController
def create
email = params[:subscription][:email]
- if !EmailValidator.valid?(email)
+ unless EmailValidator.valid?(email)
render json: { message: "Bad news, something went wrong with your email address. Please check it for typos and try again." }, status: 400
return
end
update_user_data(email: email)
params[:subscription][:opt_in] = params[:subscription][:opt_in] || false
- subscription = CiviCRM::subscribe params[:subscription]
+ subscription = Civicrm.subscribe params[:subscription]
if subscription["error"]
render json: { message: subscription["error_message"] }, status: 500
else
@@ -27,7 +27,7 @@ def create
def edit
civicrm_url = current_user.manage_subscription_url!
if civicrm_url
- redirect_to civicrm_url
+ redirect_to civicrm_url, allow_other_host: true
else
flash.now[:error] = I18n.t "subscriptions.edit_error"
redirect_to "/account"
diff --git a/app/controllers/tools_controller.rb b/app/controllers/tools_controller.rb
index d5fe9158d..eec3eca24 100644
--- a/app/controllers/tools_controller.rb
+++ b/app/controllers/tools_controller.rb
@@ -10,10 +10,10 @@ class ToolsController < ApplicationController
# Put an invisible captcha on forms are easy to submit programmatically and
# create email subscriptions.
- invisible_captcha only: [:email, :petition]
- before_action :create_newsletter_subscription, only: [:email, :call]
- before_action :create_partner_subscription, only: [:email, :call, :petition, :message_congress]
- after_action :deliver_thanks_message, only: [:email, :call, :petition, :message_congress]
+ invisible_captcha only: %i[email petition]
+ before_action :create_newsletter_subscription, only: %i[email call]
+ before_action :create_partner_subscription, only: %i[email call petition message_congress]
+ after_action :deliver_thanks_message, only: %i[email call petition message_congress]
skip_after_action :deliver_thanks_message, if: :signature_has_errors
# See https://github.com/EFForg/action-center-platform/wiki/Deployment-Notes#csrf-protection
@@ -22,14 +22,12 @@ class ToolsController < ApplicationController
def call
ahoy.track "Action",
- { type: "action", actionType: "call", actionPageId: params[:action_id] },
- action_page: @action_page
+ { type: "action", actionType: "call", actionPageId: params[:action_id] },
+ action_page: @action_page
@name = current_user.try :name
- if params[:update_user_data] == "yes"
- update_user_data(call_params)
- end
+ update_user_data(call_params) if params[:update_user_data] == "yes"
CallTool.campaign_call(params[:call_campaign_id],
phone: params[:phone],
@@ -56,12 +54,11 @@ def petition
@action_page = Petition.find(params[:signature][:petition_id]).action_page
@signature = Signature.new(signature_params.merge(user_id: @user.id))
- if @signature.zipcode.present? && @signature.country_code.blank?
- @signature.country_code = "US"
- end
+ @signature.country_code = "US" if @signature.zipcode.present? && @signature.country_code.blank?
if @signature.country_code == "US" && !Rails.application.secrets.smarty_streets_id.nil?
- if city_state = SmartyStreets.get_city_state(@signature.zipcode)
+ city_state = SmartyStreets.get_city_state(@signature.zipcode)
+ if city_state
@signature.city = city_state["city"]
@signature.state = city_state["state"]
end
@@ -76,28 +73,24 @@ def petition
:zipcode, :country_code, :phone
)
- @source = "action center petition :: " + @action_page.title
- @user.subscribe!(opt_in = true, source = @source)
+ @source = "action center petition :: #{@action_page.title}"
+ @user.subscribe!(opt_in: true, source: @source)
end
- if params[:update_user_data]
- update_user_data(signature_params)
- end
+ update_user_data(signature_params) if params[:update_user_data]
ahoy.track "Action",
- { type: "action", actionType: "signature", actionPageId: @action_page.id },
- action_page: @action_page
+ { type: "action", actionType: "signature", actionPageId: @action_page.id },
+ action_page: @action_page
respond_to do |format|
format.json { render json: { success: true }, status: 200 }
format.html do
- begin
- url = URI.parse(request.referrer)
- url.query = [url.query.presence, "thankyou=1"].join("&")
- redirect_to url.to_s
- rescue
- redirect_to welcome_index_path
- end
+ url = URI.parse(request.referrer)
+ url.query = [url.query.presence, "thankyou=1"].join("&")
+ redirect_to url.to_s
+ rescue StandardError
+ redirect_to welcome_index_path
end
end
else
@@ -107,23 +100,49 @@ def petition
def tweet
ahoy.track "Action",
- { type: "action", actionType: "tweet", actionPageId: params[:action_id] },
- action_page: @action_page
+ { type: "action", actionType: "tweet", actionPageId: params[:action_id] },
+ action_page: @action_page
render json: { success: true }, status: 200
end
def email
- unless (@user and @user.events.emails.find_by_action_page_id(params[:action_id])) or params[:dnt] == "true"
+ unless @user&.taken_action?(@action_page) || params[:dnt] == "true"
ahoy.track "Action",
- { type: "action", actionType: "email", actionPageId: params[:action_id] },
- action_page: @action_page
+ { type: "action", actionType: "email", actionPageId: params[:action_id] },
+ action_page: @action_page
end
if params[:service] == "copy"
@actionPage = @action_page
render "email_target"
+ elsif params[:state_rep_email]
+ redirect_to @action_page.email_campaign.service_uri(params[:service], { email: params[:state_rep_email] }), allow_other_host: true
else
- redirect_to @action_page.email_campaign.service_uri(params[:service])
+ redirect_to @action_page.email_campaign.service_uri(params[:service]), allow_other_host: true
+ end
+ end
+
+ # GET /tools/state_reps
+ #
+ # This endpoint is hit by the js for state legislator lookup-by-address actions.
+ # It renders json containing html markup for presentation on the view
+ def state_reps
+ @email_campaign = EmailCampaign.find(params[:email_campaign_id])
+ @actionPage = @email_campaign.action_page
+ # TODO: strong params this
+ address = "#{params[:street_address]} #{params[:zipcode]}"
+ civic_api_response = CivicApi.state_rep_search(address, @email_campaign.leg_level)
+ @state_reps = JSON.parse(civic_api_response.body)["officials"]
+ state_rep_emails = []
+ @state_reps.each do |sr|
+ state_rep_emails << sr["emails"] unless sr["emails"].nil?
+ end
+ # single-rep lookup only
+ @state_rep_email = state_rep_emails.flatten.first
+ if @state_reps.present?
+ render json: { content: render_to_string(partial: "action_page/state_reps") }, status: 200
+ else
+ render json: { error: "No representatives found" }, status: 200
end
end
@@ -162,7 +181,7 @@ def set_user
end
def set_action_page
- @action_page ||= ActionPage.find_by_id(params[:action_id])
+ @action_page ||= ActionPage.find_by(id: params[:action_id])
end
def create_newsletter_subscription
@@ -170,7 +189,7 @@ def create_newsletter_subscription
source = "action center #{@action_page.class.name.downcase} :: " + @action_page.title
params[:subscription][:opt_in] = true
params[:subscription][:source] = source
- CiviCRM::subscribe params[:subscription]
+ Civicrm.subscribe params[:subscription]
end
end
@@ -179,9 +198,9 @@ def signature_has_errors
end
def partner_signup_params
- attributes = %i(first_name last_name email)
+ attributes = %i[first_name last_name email]
# Partner signup params might come through the main form or a nested subscription form.
- %i(signature subscription).each do |model|
+ %i[signature subscription].each do |model|
return params.require(model).permit(*attributes) if params[model].present?
end
params.permit(*attributes)
@@ -191,8 +210,8 @@ def signature_params
params.require(:signature).permit(
:first_name, :last_name, :email, :petition_id, :user_id,
:street_address, :city, :state, :country_code, :zipcode, :anonymous,
- affiliations_attributes: [
- :id, :institution_id, :affiliation_type_id
+ affiliations_attributes: %i[
+ id institution_id affiliation_type_id
]
)
end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 38f7c87f2..99a9bd6a7 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -7,11 +7,11 @@ def show
end
def update
- if current_user.update_attributes(user_params)
- flash[:notice] = "You updated your account successfully."
- else
- flash[:notice] = "Could not update your account."
- end
+ flash[:notice] = if current_user.update(user_params)
+ "You updated your account successfully."
+ else
+ "Could not update your account."
+ end
if request.xhr?
render json: {}, status: 200
diff --git a/app/controllers/welcome_controller.rb b/app/controllers/welcome_controller.rb
index 8e018e532..269572d32 100644
--- a/app/controllers/welcome_controller.rb
+++ b/app/controllers/welcome_controller.rb
@@ -1,10 +1,10 @@
class WelcomeController < ApplicationController
manifest :welcome
def index
- @actionPages = FeaturedActionPage.includes(:action_page).
- order("weight desc").
- map(&:action_page).
- compact
+ @actionPages = FeaturedActionPage.includes(:action_page)
+ .order("weight desc")
+ .map(&:action_page)
+ .compact
@featuredActionPage = @actionPages.pop
@actionPages = @actionPages.reverse
end
diff --git a/app/helpers/action_page_helper.rb b/app/helpers/action_page_helper.rb
index 1e78245f3..2f322a71d 100644
--- a/app/helpers/action_page_helper.rb
+++ b/app/helpers/action_page_helper.rb
@@ -4,9 +4,7 @@ def twitter_share_url(action_page)
action_page.share_message, action_page_url(action_page)
].map(&:presence).compact.join(" ")
- suffix = if Rails.application.config.twitter_handle
- " via @#{Rails.application.config.twitter_handle}"
- end
+ suffix = (" via @#{Rails.application.config.twitter_handle}" if Rails.application.config.twitter_handle)
message += suffix if action_page.share_message.to_s.length + suffix.length <= 117
related = Rails.application.config.twitter_related.to_a.join(",")
@@ -14,7 +12,6 @@ def twitter_share_url(action_page)
"https://twitter.com/intent/tweet?text=#{u message}&related=#{related}"
end
-
def tweet_url(target, message)
message = [target, message].compact.join(" ")
related = Rails.application.config.twitter_related.to_a.join(",")
@@ -22,10 +19,8 @@ def tweet_url(target, message)
end
def facebook_share_url(action_page)
- "https://www.facebook.com/sharer/sharer.php?" + {
- u: action_page_url(action_page),
- display: "popup"
- }.to_param
+ fb_params = { u: action_page_url(action_page), display: "popup" }.to_param
+ "https://www.facebook.com/sharer/sharer.php?#{fb_params}"
end
def email_friends_url(action_page)
@@ -70,16 +65,17 @@ def parse_email_text(options = {})
title = @actionPage.title
name = html_escape(options[:name])
- email_text.
- gsub(/\$TITLE/, title).
- gsub(/\$URL/, url).
- gsub(/\$NAME/, name)
+ email_text
+ .gsub("$TITLE", title)
+ .gsub("$URL", url)
+ .gsub("$NAME", name)
end
def visible_partners
mailings_enabled = @actionPage.partners.includes(:partnerships)
.where(partnerships: { enable_mailings: true })
return mailings_enabled if params[:partner].blank?
+
mailings_enabled.where(code: params[:partner])
end
end
diff --git a/app/helpers/admin/action_pages_helper.rb b/app/helpers/admin/action_pages_helper.rb
index dfc8b35dc..d10cd02a5 100644
--- a/app/helpers/admin/action_pages_helper.rb
+++ b/app/helpers/admin/action_pages_helper.rb
@@ -1,47 +1,43 @@
-module Admin
- module ActionPagesHelper
- def call_campaign_options_for_select
- if CallTool.enabled?
- CallTool.campaigns.map do |campaign|
- ["#{campaign['name']} (#{campaign['status']})", campaign["id"]]
- end.sort_by(&:last).reverse
- else
- []
- end
- rescue SystemCallError, RestClient::Exception
+module Admin::ActionPagesHelper
+ def call_campaign_options_for_select
+ if CallTool.enabled?
+ CallTool.campaigns.map do |campaign|
+ ["#{campaign['name']} (#{campaign['status']})", campaign["id"]]
+ end.sort_by(&:last).reverse
+ else
[]
end
+ rescue SystemCallError, RestClient::Exception
+ []
+ end
- def congress_member_options_for_select(campaign)
- selected = (campaign.target_bioguide_ids || "").split(/\s*,\s*/)
+ def congress_member_options_for_select(campaign)
+ selected = (campaign.target_bioguide_ids || "").split(/\s*,\s*/)
- state_names = Places.us_state_codes.invert
+ state_names = Places.us_state_codes.invert
- congressional_bioguides = []
- grouped_reps = CongressMember.all.group_by do |rep|
- congressional_bioguides << rep.bioguide_id
- state_names[rep.state]
- end
+ congressional_bioguides = []
+ grouped_reps = CongressMember.all.group_by do |rep|
+ congressional_bioguides << rep.bioguide_id
+ state_names[rep.state]
+ end
- grouped_reps.each do |state, state_reps|
- grouped_reps[state] = state_reps.sort_by(&:last_name).map do |rep|
- label = "#{rep.full_name} (#{rep.bioguide_id})"
- [label, rep.bioguide_id]
- end
+ grouped_reps.each do |state, state_reps|
+ grouped_reps[state] = state_reps.sort_by(&:last_name).map do |rep|
+ label = "#{rep.full_name} (#{rep.bioguide_id})"
+ [label, rep.bioguide_id]
end
+ end
- grouped_reps = grouped_reps.keys.sort.map { |k| [k, grouped_reps[k]] }
+ grouped_reps = grouped_reps.keys.sort.map { |k| [k, grouped_reps[k]] }
- non_congressional_bioguides = []
- CongressMessageCampaign.targets_bioguide_ids.pluck(:target_bioguide_ids).each do |targets|
- non_congressional_bioguides.concat(targets.split(/\s*,\s*/) - congressional_bioguides)
- end
+ non_congressional_bioguides = []
+ CongressMessageCampaign.targets_bioguide_ids.pluck(:target_bioguide_ids).each do |targets|
+ non_congressional_bioguides.concat(targets.split(/\s*,\s*/) - congressional_bioguides)
+ end
- if non_congressional_bioguides.present?
- grouped_reps.unshift(["Non-congressional", non_congressional_bioguides.sort])
- end
+ grouped_reps.unshift(["Non-congressional", non_congressional_bioguides.sort]) if non_congressional_bioguides.present?
- grouped_options_for_select(grouped_reps, selected)
- end
+ grouped_options_for_select(grouped_reps, selected)
end
end
diff --git a/app/helpers/admin/topics_helper.rb b/app/helpers/admin/topics_helper.rb
index cb93a029c..9308f1c89 100644
--- a/app/helpers/admin/topics_helper.rb
+++ b/app/helpers/admin/topics_helper.rb
@@ -1,19 +1,17 @@
-module Admin
- module TopicsHelper
- def topic_category_props(topic_category)
- topic_sets = topic_category.topic_sets.map do |topic_set|
- {
- id: topic_set.id,
- tier: topic_set.tier,
- topics: topic_set.topics.map { |topic| topic.attributes.slice("id", "name") }
- }
- end
-
+module Admin::TopicsHelper
+ def topic_category_props(topic_category)
+ topic_sets = topic_category.topic_sets.map do |topic_set|
{
- topicCategoryId: topic_category.id,
- topicCategoryName: topic_category.name,
- topicSets: topic_sets
+ id: topic_set.id,
+ tier: topic_set.tier,
+ topics: topic_set.topics.map { |topic| topic.attributes.slice("id", "name") }
}
end
+
+ {
+ topicCategoryId: topic_category.id,
+ topicCategoryName: topic_category.name,
+ topicSets: topic_sets
+ }
end
end
diff --git a/app/helpers/ahoy_helper.rb b/app/helpers/ahoy_helper.rb
index 2bc4f3676..b1ef23a17 100644
--- a/app/helpers/ahoy_helper.rb
+++ b/app/helpers/ahoy_helper.rb
@@ -1,8 +1,8 @@
module AhoyHelper
def ahoy_track_tag(action_type, action_page_id)
- content_tag(:div, style: "height: 0; overflow: hidden") {
+ content_tag(:div, style: "height: 0; overflow: hidden") do
params = { action_type: action_type, action_page_id: action_page_id, format: :gif }
image_tag(ahoy_visit_url(params), style: "border: 0", alt: "")
- }
+ end
end
end
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 12ff78db6..ae639d71b 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -1,15 +1,15 @@
module ApplicationHelper
def page_title
- t("page_title", scope: [controller_path.gsub("/", "_"), action_name],
- default: [@title, I18n.t("site_title")].compact.join(" | "))
+ t("page_title", scope: [controller_path.tr("/", "_"), action_name],
+ default: [@title, I18n.t("site_title")].compact.join(" | "))
end
def escape_page_title
- URI.escape(page_title , Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
+ ERB::Util.url_encode page_title
end
def twitter_handle
- "@" + Rails.application.config.twitter_handle.to_s
+ "@#{Rails.application.config.twitter_handle}"
end
def markdown(blogtext)
@@ -21,7 +21,7 @@ def markdown(blogtext)
end
def substitute_keywords(blogtext)
- if @actionPage and @actionPage.description and @petition
+ if @actionPage&.description && @petition
blogtext.gsub("$SIGNATURECOUNT", @petition.signatures.pretty_count)
else
blogtext
@@ -71,24 +71,26 @@ def update_user_data(params = {})
if user_signed_in?
p = params.clone
p.delete(:email)
- current_user.update_attributes p
+ current_user.update p
end
end
+ # REFACTOR_FLAG
+ # use ActiveStorage::Filename#sanitized after upgrading to 5.2
def sanitize_filename(filename)
# Split the name when finding a period which is preceded by some
# character, and is followed by some character other than a period,
# if there is no following period that is followed by something
# other than a period (yeah, confusing, I know)
- fn = filename.split /(?<=.)\.(?=[^.])(?!.*\.[^.])/m
+ fn = filename.split(/(?<=.)\.(?=[^.])(?!.*\.[^.])/m)
# We now have one or two parts (depending on whether we could find
# a suitable period). For each of these parts, replace any unwanted
# sequence of characters with an underscore
- fn.map! { |s| s.gsub /[^a-z0-9\-]+/i, "_" }
+ fn.map! { |s| s.gsub(/[^a-z0-9\-]+/i, "_") }
# Finally, join the parts with a period and return the result
- return fn.join "."
+ fn.join "."
end
def can?(ability)
@@ -110,18 +112,20 @@ def messages
def percentage(x, y, precision: 0)
return "-" unless y > 0
+
number_to_percentage((x / y.to_f) * 100, precision: precision)
end
private
def user_session_data_whitelist
- [:email, :last_name, :first_name, :street_address, :city, :state, :zipcode,
- :country_code, :phone]
+ %i[email last_name first_name street_address city state zipcode
+ country_code phone]
end
def current_user_data(field)
return nil unless user_session_data_whitelist.include? field
+
current_user.try(field)
end
end
diff --git a/app/helpers/congress_message_helper.rb b/app/helpers/congress_message_helper.rb
index 12659b644..7fb8e7497 100644
--- a/app/helpers/congress_message_helper.rb
+++ b/app/helpers/congress_message_helper.rb
@@ -1,8 +1,7 @@
module CongressMessageHelper
def congress_forms_prefills(campaign, field)
- if field.value == "$TOPIC" && campaign.topic_category.present?
- return campaign.topic_category.best_match(field.options_hash)
- end
+ return campaign.topic_category.best_match(field.options_hash) if field.value == "$TOPIC" && campaign.topic_category.present?
+
{
"$NAME_FIRST" => current_first_name,
"$NAME_LAST" => current_last_name,
@@ -10,16 +9,16 @@ def congress_forms_prefills(campaign, field)
"$PHONE" => number_to_phone(current_user.try(:phone)),
"$ADDRESS_STREET" => current_street_address,
"$ADDRESS_CITY" => current_city,
- "$SUBJECT" => campaign.subject,
+ "$SUBJECT" => campaign.subject
}[field.value]
end
def congress_forms_field(field, campaign, message_attributes, bioguide_id = nil)
- if bioguide_id
- name = "member_attributes[#{bioguide_id}][#{field.value}]"
- else
- name = "common_attributes[#{field.value}]"
- end
+ name = if bioguide_id
+ "member_attributes[#{bioguide_id}][#{field.value}]"
+ else
+ "common_attributes[#{field.value}]"
+ end
# Try to guess the input based on saved info about the campaign + user.
prefill = congress_forms_prefills(campaign, field)
@@ -30,11 +29,11 @@ def congress_forms_field(field, campaign, message_attributes, bioguide_id = nil)
elsif field.value == "$PHONE"
telephone_field_tag name, prefill, congress_forms_field_defaults(field)
.merge({
- class: "form-control bfh-phone",
- "data-format": "ddd-ddd-dddd",
- pattern: "^((5\\d[123467890])|(5[123467890]\\d)|([2346789]\\d\\d))-\\d\\d\\d-\\d\\d\\d\\d$",
- title: "Must be a valid US phone number entered in 555-555-5555 format"
- })
+ class: "form-control bfh-phone",
+ "data-format": "ddd-ddd-dddd",
+ pattern: "^((5\\d[123467890])|(5[123467890]\\d)|([2346789]\\d\\d))-\\d\\d\\d-\\d\\d\\d\\d$",
+ title: "Must be a valid US phone number entered in 555-555-5555 format"
+ })
elsif field.value == "$EMAIL"
email_field_tag name, prefill, congress_forms_field_defaults(field)
elsif field.value.include?("ADDRESS") && !field.is_select?
@@ -44,7 +43,7 @@ def congress_forms_field(field, campaign, message_attributes, bioguide_id = nil)
text_field_tag name, prefill, congress_forms_field_defaults(field, placeholder: address_label, "aria-label": address_label)
elsif field.is_select?
select_tag name, options_for_select(field.options_hash, prefill),
- class: "form-control", "aria-label": field.label, include_blank: field.label, required: true
+ class: "form-control", "aria-label": field.label, include_blank: field.label, required: true
else
text_field_tag name, prefill, congress_forms_field_defaults(field)
end
diff --git a/app/helpers/devise_helper.rb b/app/helpers/devise_helper.rb
index ff4a7e3ce..c4bfed8b0 100644
--- a/app/helpers/devise_helper.rb
+++ b/app/helpers/devise_helper.rb
@@ -2,28 +2,22 @@ module DeviseHelper
# Customized to add model error instead of flashing the error.
def devise_error_messages!
flash_alerts = []
- error_key = "errors.messages.not_saved"
flash_alerts.push("This account was locked due to too many failed login attempts. Check your email for a link to unlock.") if locked_account?
- if !flash.empty?
+ unless flash.empty?
flash_alerts.push(flash[:error]) if flash[:error]
flash_alerts.push(flash[:alert]) if flash[:alert]
flash_alerts.push(flash[:notice]) if flash[:notice]
- error_key = "devise.failure.invalid"
end
return "" if resource.errors.empty? && flash_alerts.empty?
+
@hasErrorMessages = true
errors = resource.errors.empty? ? flash_alerts : resource.errors.full_messages
messages = errors.map { |msg| content_tag(:p, msg) }.join
- sentence = I18n.t(error_key, count: errors.count,
- resource: resource.class.model_name.human.downcase)
-
- if !flash[:notice] | flash[:alert]
- panel_title = "
@@ -42,7 +36,7 @@ def devise_error_messages?
end
def locked_account?
- u = User.find_by_email(@user.email)
- u && u.access_locked?
+ u = User.find_by(email: @user.email)
+ u&.access_locked?
end
end
diff --git a/app/helpers/email_campaign_helper.rb b/app/helpers/email_campaign_helper.rb
new file mode 100644
index 000000000..4f41b9d5c
--- /dev/null
+++ b/app/helpers/email_campaign_helper.rb
@@ -0,0 +1,14 @@
+module EmailCampaignHelper
+ def legislative_level_from_state_representative_info(legislator_info)
+ case legislator_info
+ when "legislatorLowerBody"
+ "state representative of the lower chamber"
+ when "legislatorUpperBody"
+ "state representative of the upper chamber"
+ when "headOfGovernment"
+ "Governor of the State"
+ else
+ "Invalid info"
+ end
+ end
+end
diff --git a/lib/action_cloner.rb b/app/lib/action_cloner.rb
similarity index 52%
rename from lib/action_cloner.rb
rename to app/lib/action_cloner.rb
index 45a63f02b..253d73fb4 100644
--- a/lib/action_cloner.rb
+++ b/app/lib/action_cloner.rb
@@ -7,13 +7,9 @@ def self.run(original)
clone_tools(original, clone)
end
- private
-
def self.clone_tools(original, clone)
- %i(tweet email_campaign petition congress_message_campaign call_campaign).each do |tool_sym|
- if original.send("#{tool_sym}_id").present?
- clone.send("#{tool_sym}=", original.send(tool_sym).dup)
- end
+ %i[tweet email_campaign petition congress_message_campaign call_campaign].each do |tool_sym|
+ clone.send("#{tool_sym}=", original.send(tool_sym).dup) if original.send("#{tool_sym}_id").present?
end
clone
end
diff --git a/lib/call_tool.rb b/app/lib/call_tool.rb
similarity index 69%
rename from lib/call_tool.rb
rename to app/lib/call_tool.rb
index 9bb969e40..0714715ec 100644
--- a/lib/call_tool.rb
+++ b/app/lib/call_tool.rb
@@ -2,23 +2,19 @@
module CallTool
def self.campaign_call(campaign, phone:, location:, user_id:, action_id:, callback_url:)
- unless [campaign, phone, location, action_id, callback_url].all?
- raise ArgumentError.new("required argument is nil")
- end
+ raise ArgumentError, "required argument is nil" unless [campaign, phone, location, action_id, callback_url].all?
get "/call/create", {
campaignId: campaign.to_param,
- userPhone: phone,
+ userPhone: phone,
userCountry: "US",
userLocation: location,
callback_url: callback_url,
-
- # TODO - Settle on the schema of the private meta data
meta: {
- user_id: user_id,
- action_id: action_id,
+ user_id: user_id,
+ action_id: action_id,
action_type: "call"
- }.to_json,
+ }.to_json
}
end
@@ -32,7 +28,7 @@ def self.campaigns
api_response = { "total_pages" => 1, "page" => 0 }
until api_response["page"] >= api_response["total_pages"]
- api_response = JSON.parse(get "/api/campaign", { api_key: api_key, page: api_response["page"] + 1 })
+ api_response = JSON.parse(get("/api/campaign", { api_key: api_key, page: api_response["page"] + 1 }))
campaigns.concat(api_response["objects"].map { |campaign| campaign.slice("id", "name", "allow_call_in", "phone_numbers", "status") })
end
@@ -44,19 +40,13 @@ def self.enabled?
Rails.application.secrets.fetch_values(:call_tool_url, :call_tool_api_key).all?
end
- private
-
def self.get(action, params = {})
RestClient.get endpoint(action), params: params
rescue RestClient::BadRequest => e
- begin
- error = JSON.parse(e.http_body)["error"]
- rescue
- raise
- end
+ error = JSON.parse(e.http_body)["error"]
# Don't raise for twilio error 13224: number invalid
- unless error.match(/^13224:/)
+ unless error.match?(/^13224:/)
if Rails.application.secrets.sentry_dsn.nil?
raise error
else
@@ -66,8 +56,8 @@ def self.get(action, params = {})
end
def self.endpoint(action)
- base = Rails.application.config.call_tool_url.sub(/\/$/, "")
- action = action.sub(/^\//, "")
+ base = Rails.application.config.call_tool_url.sub(%r{/$}, "")
+ action = action.sub(%r{^/}, "")
"#{base}/#{action}"
end
diff --git a/app/lib/civic_api.rb b/app/lib/civic_api.rb
new file mode 100644
index 000000000..3f28306de
--- /dev/null
+++ b/app/lib/civic_api.rb
@@ -0,0 +1,57 @@
+require "rest_client"
+
+# From Google, the API provider (September 2022):
+# Reference link: https://developers.google.com/civic-information/docs/data_guidelines?hl=en
+# "Developer’s using the API should make every effort to ensure all users are met with the same experience. We
+# do not allow holdbacks, A/B testing, or similar experiments."
+
+module CivicApi
+ VALID_ROLES = %w[legislatorLowerBody legislatorUpperBody headOfGovernment].freeze
+
+ def self.state_rep_search(address, roles)
+ raise ArgumentError, "required argument is nil" unless [address, roles].all?
+
+ raise ArgumentError, "Invalid role for Civic API #{roles}" unless VALID_ROLES.include?(roles)
+
+ # `includeOffices` param is needed in order to get officials list
+ # `administrativeArea1` param restricts the search to state-level legislators (and governors)
+ params = { address: address, includeOffices: true, levels: "administrativeArea1", roles: roles, key: civic_api_key }
+
+ get params
+ end
+
+ def self.all_state_reps_for_role(state, roles)
+ raise ArgumentError, "required argument is nil" unless [state, roles].all?
+
+ # need to append division information to API route
+ path_params = { ocdId: "ocd-division%2Fcountry%3Aus%2Fstate%3A#{state.downcase}" }
+ # `administrativeArea1` param restricts the search to state-level legislators (and governors)
+ query_params = { levels: "administrativeArea1", recursive: true, roles: roles, key: civic_api_key }
+
+ params = { path_params: path_params, query_params: query_params }
+
+ get params
+ end
+
+ def self.civic_api_key
+ Rails.application.secrets.google_civic_api_key
+ end
+
+ def self.endpoint
+ Rails.application.config.google_civic_api_url
+ end
+
+ def self.get(params = {})
+ if params[:path_params].nil?
+ url = endpoint
+ else
+ ocd_encpoint = endpoint.clone
+ url = ocd_encpoint.concat(params[:path_params][:ocdId])
+ params = params[:query_params]
+ end
+ RestClient.get url, params: params
+ rescue RestClient::BadRequest => e
+ error = JSON.parse(e.http_body)["error"]
+ raise error
+ end
+end
diff --git a/lib/civicrm.rb b/app/lib/civicrm.rb
similarity index 60%
rename from lib/civicrm.rb
rename to app/lib/civicrm.rb
index 7773669b7..2a8a081d3 100644
--- a/lib/civicrm.rb
+++ b/app/lib/civicrm.rb
@@ -1,5 +1,5 @@
require "rest_client"
-module CiviCRM
+module Civicrm
module UserMethods
def contact_attributes
attributes.symbolize_keys.slice(
@@ -8,34 +8,39 @@ def contact_attributes
)
end
- def subscribe!(opt_in = false, source = "action center")
- return nil if CiviCRM.skip_crm?
- res = CiviCRM::subscribe contact_attributes.merge(opt_in: opt_in, source: source)
- update_attributes(contact_id: res["contact_id"]) if (res && res["contact_id"])
+ def subscribe!(opt_in: false, source: "action center")
+ return nil if Civicrm.skip_crm?
+
+ res = Civicrm.subscribe contact_attributes.merge(opt_in: opt_in, source: source)
+ update(contact_id: res["contact_id"]) if res && res["contact_id"]
res || {}
end
def contact_id!
- return nil if CiviCRM.skip_crm?
- res = CiviCRM::import_contact contact_attributes
- update_attributes(contact_id: res["contact_id"]) if (res && res["contact_id"])
+ return nil if Civicrm.skip_crm?
+
+ res = Civicrm.import_contact contact_attributes
+ update(contact_id: res["contact_id"]) if res && res["contact_id"]
contact_id
end
def add_civicrm_activity!(action_page_id)
- return nil if CiviCRM.skip_crm?
- if contact_id && action_page = ActionPage.find_by_id(action_page_id)
- CiviCRM::add_activity(
- contact_id: contact_id,
- subject: "Took Action #{action_page.id}: #{action_page.title}"
- )
- end
+ return nil if Civicrm.skip_crm?
+
+ action_page = ActionPage.find_by(id: action_page_id)
+ return unless contact_id && action_page
+
+ Civicrm.add_activity(
+ contact_id: contact_id,
+ subject: "Took Action #{action_page.id}: #{action_page.title}"
+ )
end
def manage_subscription_url!
- checksum = CiviCRM::get_checksum(contact_id)
+ checksum = Civicrm.get_checksum(contact_id)
return nil unless checksum
- "#{Rails.application.secrets.supporters['host']}/update-your-preferences?" + {
+
+ "#{Rails.application.secrets.supporters[:host]}/update-your-preferences?" + {
cid1: contact_id,
cs: checksum
}.to_param
@@ -43,16 +48,18 @@ def manage_subscription_url!
end
def self.skip_crm?
- Rails.application.secrets.supporters["api_key"].nil?
+ Rails.application.secrets.supporters[:api_key].nil?
end
def self.subscribe(params)
return {} if skip_crm?
- self.import_contact params.merge(subscribe: true)
+
+ import_contact params.merge(subscribe: true)
end
def self.import_contact(params)
return {} if skip_crm?
+
post base_params.merge(
method: "import_contact",
data: {
@@ -73,6 +80,7 @@ def self.import_contact(params)
def self.add_activity(params)
return nil if skip_crm?
+
post base_params.merge(
method: "add_activity",
data: params.slice(:contact_id, :subject, :activity_type_id).to_json
@@ -80,21 +88,18 @@ def self.add_activity(params)
end
def self.supporters_api_url
- "#{Rails.application.secrets.supporters['host']}/#{Rails.application.secrets.supporters['path']}"
+ "#{Rails.application.secrets.supporters[:host]}/#{Rails.application.secrets.supporters[:path]}"
end
- private
-
def self.post(params)
- begin
- res = JSON.parse RestClient.post(supporters_api_url, params)
- raise res["error_message"] if res["error"]
- return res
- rescue => e
- Raven.capture_exception(e)
- Rails.logger.error "#{ e } (#{ e.class })!"
- return false
- end
+ res = JSON.parse RestClient.post(supporters_api_url, params)
+ raise res["error_message"] if res["error"]
+
+ res
+ rescue StandardError => e
+ Raven.capture_exception(e)
+ Rails.logger.error "#{e} (#{e.class})!"
+ false
end
def self.send_email_template_data(params)
@@ -116,6 +121,7 @@ def self.find_contact_by_email_data(params)
def self.get_checksum(contact_id)
return nil if skip_crm?
+
# Valid for 24 hours
res = post base_params.merge(
method: "generate_checksum",
@@ -125,6 +131,6 @@ def self.get_checksum(contact_id)
end
def self.base_params
- { site_key: Rails.application.secrets.supporters["api_key"] }
+ { site_key: Rails.application.secrets.supporters[:api_key] }
end
end
diff --git a/lib/congress_forms.rb b/app/lib/congress_forms.rb
similarity index 78%
rename from lib/congress_forms.rb
rename to app/lib/congress_forms.rb
index a31c483cf..9a6b549cd 100644
--- a/lib/congress_forms.rb
+++ b/app/lib/congress_forms.rb
@@ -7,7 +7,8 @@ class Form
def self.find(bioguide_ids)
raw_data = CongressForms.post("/retrieve-form-elements/", { bio_ids: bioguide_ids })
raise CongressForms::RequestFailed if raw_data.empty?
- links, forms = raw_data.partition { |id, raw| raw["defunct"] }
+
+ links, forms = raw_data.partition { |_id, raw| raw["defunct"] }
[
forms.map { |id, raw| Form.new(id, raw["required_actions"]) },
links.map { |id, raw| [id, raw["contact_url"]] }.to_h
@@ -21,7 +22,7 @@ def initialize(bioguide_id, fields)
end
def order_fields
- order = %w($NAME_PREFIX $NAME_FIRST $NAME_LAST $PHONE $EMAIL $SUBJECT $TOPIC)
+ order = %w[$NAME_PREFIX $NAME_FIRST $NAME_LAST $PHONE $EMAIL $SUBJECT $TOPIC]
@fields = @fields.sort_by { |f| order.index(f.value) || Float::INFINITY }
end
@@ -46,6 +47,7 @@ def validate(input)
return false if input.nil?
return false if max_length && input.length > max_length
return false unless options.nil? || options.include?(input)
+
true
end
@@ -72,9 +74,10 @@ def hash
end
def options_hash
- if @value == "$ADDRESS_STATE_POSTAL_ABBREV"
+ case @value
+ when "$ADDRESS_STATE_POSTAL_ABBREV"
Places.us_state_codes
- elsif @value == "$ADDRESS_STATE_FULL"
+ when "$ADDRESS_STATE_FULL"
Places.us_states
else
@options_hash
@@ -83,6 +86,7 @@ def options_hash
def options
return options_hash.values if options_hash.is_a?(Hash)
+
options_hash
end
end
@@ -95,7 +99,7 @@ def self.date_fills_path(campaign_tag = nil, start_date = nil, end_date = nil, b
params = {
date_start: start_date,
date_end: end_date,
- campaign_tag: campaign_tag,
+ campaign_tag: campaign_tag
}.compact
data_path("/successful-fills-by-date/", params, bioguide_id)
end
@@ -110,30 +114,26 @@ def self.date_fills(*args)
def self.data_path(base_path, params = {}, bioguide_id = nil)
base_path += bioguide_id unless bioguide_id.nil?
- base_path += "?" + {
- debug_key: Rails.application.secrets.congress_forms_debug_key,
+ "#{base_path}?" + {
+ debug_key: Rails.application.secrets.congress_forms_debug_key
}.merge(params).to_query
end
def self.get(path)
- begin
- JSON.parse RestClient.get(base_url + path)
- rescue RestClient::ExceptionWithResponse => e
- Raven.capture_exception(e)
- Rails.logger.error e
- return {}
- end
+ JSON.parse RestClient.get(base_url + path)
+ rescue RestClient::ExceptionWithResponse => e
+ Raven.capture_exception(e)
+ Rails.logger.error e
+ {}
end
def self.post(path, body = {})
- begin
- JSON.parse RestClient.post(base_url + path, body.to_json,
- { content_type: :json, accept: :json })
- rescue RestClient::ExceptionWithResponse => e
- Raven.capture_exception(e)
- Rails.logger.error e
- raise RequestFailed
- end
+ JSON.parse RestClient.post(base_url + path, body.to_json,
+ { content_type: :json, accept: :json })
+ rescue RestClient::ExceptionWithResponse => e
+ Raven.capture_exception(e)
+ Rails.logger.error e
+ raise RequestFailed
end
def self.base_url
diff --git a/lib/places.rb b/app/lib/places.rb
similarity index 53%
rename from lib/places.rb
rename to app/lib/places.rb
index 4809d8342..d29c96107 100644
--- a/lib/places.rb
+++ b/app/lib/places.rb
@@ -1,5 +1,6 @@
# frozen_string_literal: true
+# rubocop:disable Metrics/CollectionLiteralLength
module Places
def self.us_state_codes
{ "Alabama" => "AL",
@@ -69,193 +70,193 @@ def self.us_states
def self.country_codes
[
- ["Afghanistan", "AF"],
+ %w[Afghanistan AF],
["Aland Islands", "AX"],
- ["Albania", "AL"],
- ["Algeria", "DZ"],
+ %w[Albania AL],
+ %w[Algeria DZ],
["American Samoa", "AS"],
- ["Andorra", "AD"],
- ["Angola", "AO"],
- ["Anguilla", "AI"],
- ["Antarctica", "AQ"],
+ %w[Andorra AD],
+ %w[Angola AO],
+ %w[Anguilla AI],
+ %w[Antarctica AQ],
["Antigua and Barbuda", "AG"],
- ["Argentina", "AR"],
- ["Armenia", "AM"],
- ["Aruba", "AW"],
+ %w[Argentina AR],
+ %w[Armenia AM],
+ %w[Aruba AW],
["Ascension Island", "AC"],
- ["Australia", "AU"],
- ["Austria", "AT"],
- ["Azerbaijan", "AZ"],
- ["Bahamas", "BS"],
- ["Bahrain", "BH"],
- ["Bangladesh", "BD"],
- ["Barbados", "BB"],
- ["Belarus", "BY"],
- ["Belgium", "BE"],
- ["Belize", "BZ"],
- ["Benin", "BJ"],
- ["Bermuda", "BM"],
- ["Bhutan", "BT"],
+ %w[Australia AU],
+ %w[Austria AT],
+ %w[Azerbaijan AZ],
+ %w[Bahamas BS],
+ %w[Bahrain BH],
+ %w[Bangladesh BD],
+ %w[Barbados BB],
+ %w[Belarus BY],
+ %w[Belgium BE],
+ %w[Belize BZ],
+ %w[Benin BJ],
+ %w[Bermuda BM],
+ %w[Bhutan BT],
["Bolivia, Plurinational State of", "BO"],
["Bonaire, Sint Eustatius and Saba", "BQ"],
["Bosnia and Herzegovina", "BA"],
- ["Botswana", "BW"],
+ %w[Botswana BW],
["Bouvet Island", "BV"],
- ["Brazil", "BR"],
+ %w[Brazil BR],
["British Indian Ocean Territory", "IO"],
["Brunei Darussalam", "BN"],
- ["Bulgaria", "BG"],
+ %w[Bulgaria BG],
["Burkina Faso", "BF"],
- ["Burundi", "BI"],
- ["Cambodia", "KH"],
- ["Cameroon", "CM"],
- ["Canada", "CA"],
+ %w[Burundi BI],
+ %w[Cambodia KH],
+ %w[Cameroon CM],
+ %w[Canada CA],
["Cape Verde", "CV"],
["Cayman Islands", "KY"],
["Central African Republic", "CF"],
- ["Chad", "TD"],
- ["Chile", "CL"],
- ["China", "CN"],
+ %w[Chad TD],
+ %w[Chile CL],
+ %w[China CN],
["Christmas Island", "CX"],
["Cocos (Keeling) Islands", "CC"],
- ["Colombia", "CO"],
- ["Comoros", "KM"],
- ["Congo", "CG"],
+ %w[Colombia CO],
+ %w[Comoros KM],
+ %w[Congo CG],
["Congo, the Democratic Republic of the", "CD"],
["Cook Islands", "CK"],
["Costa Rica", "CR"],
["Cote d'Ivoire", "CI"],
- ["Croatia", "HR"],
- ["Cuba", "CU"],
- ["Curacao", "CW"],
- ["Cyprus", "CY"],
+ %w[Croatia HR],
+ %w[Cuba CU],
+ %w[Curacao CW],
+ %w[Cyprus CY],
["Czech Republic", "CZ"],
- ["Denmark", "DK"],
- ["Djibouti", "DJ"],
- ["Dominica", "DM"],
+ %w[Denmark DK],
+ %w[Djibouti DJ],
+ %w[Dominica DM],
["Dominican Republic", "DO"],
- ["Ecuador", "EC"],
- ["Egypt", "EG"],
+ %w[Ecuador EC],
+ %w[Egypt EG],
["El Salvador", "SV"],
["Equatorial Guinea", "GQ"],
- ["Eritrea", "ER"],
- ["Estonia", "EE"],
- ["Ethiopia", "ET"],
+ %w[Eritrea ER],
+ %w[Estonia EE],
+ %w[Ethiopia ET],
["Falkland Islands (Malvinas)", "FK"],
["Faroe Islands", "FO"],
- ["Fiji", "FJ"],
- ["Finland", "FI"],
- ["France", "FR"],
+ %w[Fiji FJ],
+ %w[Finland FI],
+ %w[France FR],
["French Guiana", "GF"],
["French Polynesia", "PF"],
["French Southern Territories", "TF"],
- ["Gabon", "GA"],
- ["Gambia", "GM"],
- ["Georgia", "GE"],
- ["Germany", "DE"],
- ["Ghana", "GH"],
- ["Gibraltar", "GI"],
- ["Greece", "GR"],
- ["Greenland", "GL"],
- ["Grenada", "GD"],
- ["Guadeloupe", "GP"],
- ["Guam", "GU"],
- ["Guatemala", "GT"],
- ["Guernsey", "GG"],
- ["Guinea", "GN"],
- ["Guinea-Bissau", "GW"],
- ["Guyana", "GY"],
- ["Haiti", "HT"],
+ %w[Gabon GA],
+ %w[Gambia GM],
+ %w[Georgia GE],
+ %w[Germany DE],
+ %w[Ghana GH],
+ %w[Gibraltar GI],
+ %w[Greece GR],
+ %w[Greenland GL],
+ %w[Grenada GD],
+ %w[Guadeloupe GP],
+ %w[Guam GU],
+ %w[Guatemala GT],
+ %w[Guernsey GG],
+ %w[Guinea GN],
+ %w[Guinea-Bissau GW],
+ %w[Guyana GY],
+ %w[Haiti HT],
["Heard Island and McDonald Islands", "HM"],
["Holy See (Vatican City State)", "VA"],
- ["Honduras", "HN"],
+ %w[Honduras HN],
["Hong Kong", "HK"],
- ["Hungary", "HU"],
- ["Iceland", "IS"],
- ["India", "IN"],
- ["Indonesia", "ID"],
+ %w[Hungary HU],
+ %w[Iceland IS],
+ %w[India IN],
+ %w[Indonesia ID],
["Iran, Islamic Republic of", "IR"],
- ["Iraq", "IQ"],
- ["Ireland", "IE"],
+ %w[Iraq IQ],
+ %w[Ireland IE],
["Isle of Man", "IM"],
- ["Israel", "IL"],
- ["Italy", "IT"],
- ["Jamaica", "JM"],
- ["Japan", "JP"],
- ["Jersey", "JE"],
- ["Jordan", "JO"],
- ["Kazakhstan", "KZ"],
- ["Kenya", "KE"],
- ["Kiribati", "KI"],
+ %w[Israel IL],
+ %w[Italy IT],
+ %w[Jamaica JM],
+ %w[Japan JP],
+ %w[Jersey JE],
+ %w[Jordan JO],
+ %w[Kazakhstan KZ],
+ %w[Kenya KE],
+ %w[Kiribati KI],
["Korea, Democratic People's Republic of", "KP"],
["Korea, Republic of", "KR"],
- ["Kosovo", "KV"],
- ["Kuwait", "KW"],
- ["Kyrgyzstan", "KG"],
+ %w[Kosovo KV],
+ %w[Kuwait KW],
+ %w[Kyrgyzstan KG],
["Lao People's Democratic Republic", "LA"],
- ["Latvia", "LV"],
- ["Lebanon", "LB"],
- ["Lesotho", "LS"],
- ["Liberia", "LR"],
- ["Libya", "LY"],
- ["Liechtenstein", "LI"],
- ["Lithuania", "LT"],
- ["Luxembourg", "LU"],
- ["Macao", "MO"],
+ %w[Latvia LV],
+ %w[Lebanon LB],
+ %w[Lesotho LS],
+ %w[Liberia LR],
+ %w[Libya LY],
+ %w[Liechtenstein LI],
+ %w[Lithuania LT],
+ %w[Luxembourg LU],
+ %w[Macao MO],
["Macedonia, The Former Yugoslav Republic Of", "MK"],
- ["Madagascar", "MG"],
- ["Malawi", "MW"],
- ["Malaysia", "MY"],
- ["Maldives", "MV"],
- ["Mali", "ML"],
- ["Malta", "MT"],
+ %w[Madagascar MG],
+ %w[Malawi MW],
+ %w[Malaysia MY],
+ %w[Maldives MV],
+ %w[Mali ML],
+ %w[Malta MT],
["Marshall Islands", "MH"],
- ["Martinique", "MQ"],
- ["Mauritania", "MR"],
- ["Mauritius", "MU"],
- ["Mayotte", "YT"],
- ["Mexico", "MX"],
+ %w[Martinique MQ],
+ %w[Mauritania MR],
+ %w[Mauritius MU],
+ %w[Mayotte YT],
+ %w[Mexico MX],
["Micronesia, Federated States of", "FM"],
["Moldova, Republic of", "MD"],
- ["Monaco", "MC"],
- ["Mongolia", "MN"],
- ["Montenegro", "ME"],
- ["Montserrat", "MS"],
- ["Morocco", "MA"],
- ["Mozambique", "MZ"],
- ["Myanmar", "MM"],
- ["Namibia", "NA"],
- ["Nauru", "NR"],
- ["Nepal", "NP"],
- ["Netherlands", "NL"],
+ %w[Monaco MC],
+ %w[Mongolia MN],
+ %w[Montenegro ME],
+ %w[Montserrat MS],
+ %w[Morocco MA],
+ %w[Mozambique MZ],
+ %w[Myanmar MM],
+ %w[Namibia NA],
+ %w[Nauru NR],
+ %w[Nepal NP],
+ %w[Netherlands NL],
["Netherlands Antilles", "AN"],
["New Caledonia", "NC"],
["New Zealand", "NZ"],
- ["Nicaragua", "NI"],
- ["Niger", "NE"],
- ["Nigeria", "NG"],
- ["Niue", "NU"],
+ %w[Nicaragua NI],
+ %w[Niger NE],
+ %w[Nigeria NG],
+ %w[Niue NU],
["Norfolk Island", "NF"],
["Northern Mariana Islands", "MP"],
- ["Norway", "NO"],
- ["Oman", "OM"],
- ["Pakistan", "PK"],
- ["Palau", "PW"],
+ %w[Norway NO],
+ %w[Oman OM],
+ %w[Pakistan PK],
+ %w[Palau PW],
["Palestinian Territory, Occupied", "PS"],
- ["Panama", "PA"],
+ %w[Panama PA],
["Papua New Guinea", "PG"],
- ["Paraguay", "PY"],
- ["Peru", "PE"],
- ["Philippines", "PH"],
- ["Pitcairn", "PN"],
- ["Poland", "PL"],
- ["Portugal", "PT"],
+ %w[Paraguay PY],
+ %w[Peru PE],
+ %w[Philippines PH],
+ %w[Pitcairn PN],
+ %w[Poland PL],
+ %w[Portugal PT],
["Puerto Rico", "PR"],
- ["Qatar", "QA"],
- ["Reunion", "RE"],
- ["Romania", "RO"],
+ %w[Qatar QA],
+ %w[Reunion RE],
+ %w[Romania RO],
["Russian Federation", "RU"],
- ["Rwanda", "RW"],
+ %w[Rwanda RW],
["Saint Barthelemy", "BL"],
["Saint Helena, Ascension and Tristan da Cunha", "SH"],
["Saint Kitts and Nevis", "KN"],
@@ -263,66 +264,66 @@ def self.country_codes
["Saint Martin (French part)", "MF"],
["Saint Pierre and Miquelon", "PM"],
["Saint Vincent and the Grenadines", "VC"],
- ["Samoa", "WS"],
+ %w[Samoa WS],
["San Marino", "SM"],
["Sao Tome and Principe", "ST"],
["Saudi Arabia", "SA"],
- ["Senegal", "SN"],
- ["Serbia", "RS"],
- ["Seychelles", "SC"],
+ %w[Senegal SN],
+ %w[Serbia RS],
+ %w[Seychelles SC],
["Sierra Leone", "SL"],
- ["Singapore", "SG"],
+ %w[Singapore SG],
["Sint Maarten (Dutch part)", "SX"],
- ["Slovakia", "SK"],
- ["Slovenia", "SI"],
+ %w[Slovakia SK],
+ %w[Slovenia SI],
["Solomon Islands", "SB"],
- ["Somalia", "SO"],
+ %w[Somalia SO],
["South Africa", "ZA"],
["South Georgia and the South Sandwich Islands", "GS"],
["South Sudan, Republic of", "SS"],
- ["Spain", "ES"],
+ %w[Spain ES],
["Sri Lanka", "LK"],
- ["Sudan", "SD"],
- ["Suriname", "SR"],
+ %w[Sudan SD],
+ %w[Suriname SR],
["Svalbard and Jan Mayen", "SJ"],
- ["Swaziland", "SZ"],
- ["Sweden", "SE"],
- ["Switzerland", "CH"],
+ %w[Swaziland SZ],
+ %w[Sweden SE],
+ %w[Switzerland CH],
["Syrian Arab Republic", "SY"],
- ["Taiwan", "TW"],
- ["Tajikistan", "TJ"],
+ %w[Taiwan TW],
+ %w[Tajikistan TJ],
["Tanzania, United Republic of", "TZ"],
- ["Thailand", "TH"],
- ["Timor-Leste", "TL"],
- ["Togo", "TG"],
- ["Tokelau", "TK"],
- ["Tonga", "TO"],
+ %w[Thailand TH],
+ %w[Timor-Leste TL],
+ %w[Togo TG],
+ %w[Tokelau TK],
+ %w[Tonga TO],
["Trinidad and Tobago", "TT"],
["Tristan da Cunha", "TA"],
- ["Tunisia", "TN"],
- ["Turkey", "TR"],
- ["Turkmenistan", "TM"],
+ %w[Tunisia TN],
+ %w[Turkey TR],
+ %w[Turkmenistan TM],
["Turks and Caicos Islands", "TC"],
- ["Tuvalu", "TV"],
- ["Uganda", "UG"],
- ["Ukraine", "UA"],
+ %w[Tuvalu TV],
+ %w[Uganda UG],
+ %w[Ukraine UA],
["United Arab Emirates", "AE"],
["United Kingdom", "GB"],
["United States", "US"],
["United States Minor Outlying Islands", "UM"],
- ["Uruguay", "UY"],
- ["Uzbekistan", "UZ"],
- ["Vanuatu", "VU"],
+ %w[Uruguay UY],
+ %w[Uzbekistan UZ],
+ %w[Vanuatu VU],
["Venezuela, Bolivarian Republic of", "VE"],
["Viet Nam", "VN"],
["Virgin Islands, British", "VG"],
["Virgin Islands, U.S.", "VI"],
["Wallis and Futuna", "WF"],
["Western Sahara", "EH"],
- ["Yemen", "YE"],
- ["Zambia", "ZM"],
- ["Zimbabwe", "ZW"]
+ %w[Yemen YE],
+ %w[Zambia ZM],
+ %w[Zimbabwe ZW]
].freeze
end
-
end
+# rubocop:enable Metrics/CollectionLiteralLength
diff --git a/app/lib/quotes.rb b/app/lib/quotes.rb
new file mode 100644
index 000000000..fff4641d2
--- /dev/null
+++ b/app/lib/quotes.rb
@@ -0,0 +1,11 @@
+module Quotes
+ def self.get
+ quotes.sample
+ end
+
+ def self.quotes
+ @quotes ||= YAML.load_file("config/custom_quotes.yml")
+ rescue Errno::ENOENT
+ @quotes ||= YAML.load_file("config/quotes.yml")
+ end
+end
diff --git a/lib/related_content.rb b/app/lib/related_content.rb
similarity index 98%
rename from lib/related_content.rb
rename to app/lib/related_content.rb
index ab5cd05a6..6e3fc3066 100644
--- a/lib/related_content.rb
+++ b/app/lib/related_content.rb
@@ -5,11 +5,12 @@ def initialize(url)
def load
return if url.blank?
+
begin
open_page
@loaded_successfully = true
rescue OpenURI::HTTPError
- return
+ nil
end
end
@@ -23,6 +24,7 @@ def title
def image
return @image if @image
+
og_url = page.css("meta[property='og:image']")
@image = if og_url.blank?
""
diff --git a/lib/smarty_streets.rb b/app/lib/smarty_streets.rb
similarity index 75%
rename from lib/smarty_streets.rb
rename to app/lib/smarty_streets.rb
index b7d004434..a9a65d283 100644
--- a/lib/smarty_streets.rb
+++ b/app/lib/smarty_streets.rb
@@ -3,15 +3,13 @@ module SmartyStreets
def self.get_city_state(zipcode)
url = "https://us-zipcode.api.smartystreets.com/lookup"
res = post(url, base_params.merge(zipcode: zipcode))
- if res && !res.empty?
- res.first["city_states"].try :first
- end
+ res.first["city_states"].try :first if res.present?
end
def self.get_location(street, zipcode)
url = "https://api.smartystreets.com/street-address"
res = post(url, base_params.merge(street: street, zipcode: zipcode))
- raise AddressNotFound if !res || res.empty?
+ raise AddressNotFound if res.blank?
location = OpenStruct.new
location.street = street
@@ -21,7 +19,7 @@ def self.get_location(street, zipcode)
location.state = res[0]["components"]["state_abbreviation"]
location.district = res[0]["metadata"]["congressional_district"]
location.district = "0" if location.district == "AL"
- return location
+ location
end
def self.get_congressional_district(street, zipcode)
@@ -31,17 +29,12 @@ def self.get_congressional_district(street, zipcode)
class AddressNotFound < StandardError; end
- private
-
def self.post(url, params)
- begin
- res = JSON.parse RestClient.get("#{url}?#{params.to_query}")
- return res
- rescue => e
- Raven.capture_exception(e)
- Rails.logger.error "#{ e } (#{ e.class })!"
- return false
- end
+ JSON.parse RestClient.get("#{url}?#{params.to_query}")
+ rescue StandardError => e
+ Raven.capture_exception(e)
+ Rails.logger.error "#{e} (#{e.class})!"
+ false
end
def self.base_params
diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb
index 185fde7cd..7609415fe 100644
--- a/app/mailers/user_mailer.rb
+++ b/app/mailers/user_mailer.rb
@@ -12,7 +12,7 @@ def thanks_message(email, actionPage, options = {})
mail(to: email, subject: "Thanks for taking action")
end
- def signup_attempt_with_existing_email(user, options = {})
+ def signup_attempt_with_existing_email(user, _options = {})
@user = user
@email = user.email
@token = user.reset_password_token
@@ -22,8 +22,6 @@ def signup_attempt_with_existing_email(user, options = {})
private
def check_bounces
- unless Bounce.find_by_email(@email.downcase).nil?
- mail.perform_deliveries = false
- end
+ mail.perform_deliveries = false unless Bounce.find_by(email: @email.downcase).nil?
end
end
diff --git a/app/models/action_institution.rb b/app/models/action_institution.rb
index d1491f79d..cd57fab1f 100644
--- a/app/models/action_institution.rb
+++ b/app/models/action_institution.rb
@@ -1,10 +1,11 @@
-class ActionInstitution < ActiveRecord::Base
+class ActionInstitution < ApplicationRecord
belongs_to :institution
belongs_to :action_page
def self.add(action_page:, category:, reset: false)
return unless action_page.enable_petition &&
- action_page.petition.enable_affiliations
+ action_page.petition.enable_affiliations
+
action_page.action_institutions.delete_all if reset == "1"
institution_ids = Institution.where(category: category).pluck(:id)
fast_create(action_page_id: action_page.id, institution_ids: institution_ids)
@@ -33,5 +34,5 @@ def self.fast_create(action_page_id:, institution_ids:)
# * Check if there are any duplicates in production
# * If so, remove them in a way that doesn't break anything else
# * Uncomment the following line
- #validates_uniqueness_of :institution_id, scope: :action_page_id
+ # validates_uniqueness_of :institution_id, scope: :action_page_id
end
diff --git a/app/models/action_page.rb b/app/models/action_page.rb
index 104a5149a..3c1de0d97 100644
--- a/app/models/action_page.rb
+++ b/app/models/action_page.rb
@@ -1,28 +1,28 @@
-class ActionPage < ActiveRecord::Base
- extend FriendlyId, AmazonCredentials
+class ActionPage < ApplicationRecord
+ extend FriendlyId
- include PgSearch
+ include PgSearch::Model
pg_search_scope :search,
- against: [
- :title,
- :slug,
- :summary,
- :description,
- :email_text,
+ against: %i[
+ title
+ slug
+ summary
+ description
+ email_text
],
associated_against: {
- call_campaign: [:title, :message],
- congress_message_campaign: [:subject, :message, :campaign_tag],
- email_campaign: [:subject, :message],
- petition: [:title, :description],
- tweet: [:target, :message, :cta]
+ call_campaign: %i[title message],
+ congress_message_campaign: %i[subject message campaign_tag],
+ email_campaign: %i[subject message],
+ petition: %i[title description],
+ tweet: %i[target message cta]
},
using: { tsearch: { prefix: true } }
- friendly_id :title, use: [:slugged, :history]
+ friendly_id :title, use: %i[slugged history]
scope :published, -> { where(published: true) }
- has_many :events, class_name: Ahoy::Event
+ has_many :events, class_name: "Ahoy::Event"
has_many :partnerships
has_many :partners, through: :partnerships
has_many :action_institutions
@@ -36,25 +36,19 @@ class ActionPage < ActiveRecord::Base
belongs_to :call_campaign
belongs_to :category, optional: true
belongs_to :active_action_page_for_redirect, class_name: "ActionPage",
- foreign_key: "archived_redirect_action_page_id"
+ foreign_key: "archived_redirect_action_page_id"
+
belongs_to :author, class_name: "User", foreign_key: :user_id, optional: true
+
accepts_nested_attributes_for :tweet, :petition, :email_campaign,
- :call_campaign, :congress_message_campaign, :affiliation_types, :partnerships,
- reject_if: :all_blank
-
- has_attached_file :featured_image, amazon_credentials.merge(default_url: "missing.png")
- has_attached_file :background_image, amazon_credentials
- has_attached_file :og_image, amazon_credentials
- validates_media_type_spoof_detection :featured_image,
- if: -> { featured_image.present? && featured_image_file_name_came_from_user? }
- validates_media_type_spoof_detection :background_image,
- if: -> { background_image.present? && background_image_file_name_came_from_user? }
- validates_media_type_spoof_detection :og_image,
- if: -> { og_image.present? && og_image_file_name_came_from_user? }
- do_not_validate_attachment_file_type [:featured_image, :background_image, :og_image]
-
- #validates_length_of :og_title, maximum: 65
+ :call_campaign, :congress_message_campaign, :affiliation_types, :partnerships,
+ reject_if: :all_blank
+
+ mount_uploader :featured_image, ActionPageImageUploader, mount_on: :featured_image_file_name
+ mount_uploader :background_image, ActionPageImageUploader, mount_on: :background_image_file_name
+ mount_uploader :og_image, ActionPageImageUploader, mount_on: :og_image_file_name
+
after_save :no_drafts_on_homepage
after_save :set_congress_tag, if: -> { enable_congress_message }
@@ -62,18 +56,16 @@ class ActionPage < ActiveRecord::Base
def self.type(*types)
scopes = Array(types).flatten.map do |t|
- unless %w(call congress_message email petition tweet redirect).include?(t)
- raise ArgumentError, "unrecognized type #{t}"
- end
+ raise ArgumentError, "unrecognized type #{t}" unless %w[call congress_message email petition tweet redirect].include?(t)
- where(:"enable_#{t}" => true)
+ where("enable_#{t}": true)
end
scopes.inject(:or) || all
end
def action_type
- %w(call congress_message email petition tweet redirect).each do |type|
+ %w[call congress_message email petition tweet redirect].each do |type|
return type.titleize if self[:"enable_#{type}"]
end
@@ -81,9 +73,8 @@ def action_type
end
def self.status(status)
- unless %w(archived victory live draft).include?(status)
- raise ArgumentError, "unrecognized status #{status}"
- end
+ raise ArgumentError, "unrecognized status #{status}" unless %w[archived victory live draft].include?(status)
+
case status
when "live"
where(published: true, archived: false, victory: false)
@@ -106,14 +97,14 @@ def should_generate_new_friendly_id?
def call_tool_title
call_campaign &&
- call_campaign.title.length > 0 &&
+ !call_campaign.title.empty? &&
call_campaign.title ||
"Call Your Legislators"
end
def message_rendered
# TODO: just write a test for this and rename this to .to_md
- call_campaign && call_campaign.message || ""
+ call_campaign&.message || ""
end
def verb
@@ -151,6 +142,7 @@ def image
def actions_taken_percent
return 0 if view_count == 0
+
@percent ||= (action_count / view_count.to_f) * 100
end
@@ -195,7 +187,8 @@ def no_drafts_on_homepage
end
def set_congress_tag
- return unless congress_message_campaign.campaign_tag.blank?
+ return if congress_message_campaign.campaign_tag.present?
+
congress_message_campaign.update(campaign_tag: slug)
end
end
diff --git a/app/models/affiliation.rb b/app/models/affiliation.rb
index 39a8b3c7f..3034772e2 100644
--- a/app/models/affiliation.rb
+++ b/app/models/affiliation.rb
@@ -1,4 +1,4 @@
-class Affiliation < ActiveRecord::Base
+class Affiliation < ApplicationRecord
belongs_to :action_page
belongs_to :signature
belongs_to :affiliation_type
diff --git a/app/models/affiliation_type.rb b/app/models/affiliation_type.rb
index 3a83e66b7..9a084ab4a 100644
--- a/app/models/affiliation_type.rb
+++ b/app/models/affiliation_type.rb
@@ -1,4 +1,4 @@
-class AffiliationType < ActiveRecord::Base
+class AffiliationType < ApplicationRecord
belongs_to :action_page
has_many :affiliations
end
diff --git a/app/models/ahoy/event.rb b/app/models/ahoy/event.rb
index 942bfae6e..fe7322748 100644
--- a/app/models/ahoy/event.rb
+++ b/app/models/ahoy/event.rb
@@ -1,17 +1,16 @@
module Ahoy
- class Event < ActiveRecord::Base
+ class Event < ApplicationRecord
self.table_name = "ahoy_events"
belongs_to :visit
belongs_to :user
belongs_to :action_page
counter_culture :action_page, column_name: proc { |record|
- if record.name == "Action"
+ case record.name
+ when "Action"
"action_count"
- elsif record.name == "View"
+ when "View"
"view_count"
- else
- nil
end
}
@@ -22,25 +21,23 @@ class Event < ActiveRecord::Base
scope :calls, -> { where("properties ->> 'actionType' = 'call'") }
scope :signatures, -> { where("properties ->> 'actionType' = 'signature'") }
scope :tweets, -> { where("properties ->> 'actionType' = 'tweet'") }
- scope :on_page, -> (id) { where(action_page_id: id) }
- scope :in_range, ->(start_date, end_date) {
+ scope :on_page, ->(id) { where(action_page_id: id) }
+ scope :in_range, lambda { |start_date, end_date|
where(time: start_date..end_date.tomorrow)
}
- before_save :user_opt_out
- before_save :anonymize_views
after_create :record_civicrm
- TYPES = %i(views emails tweets calls signatures congress_messages).freeze
+ TYPES = %i[views emails tweets calls signatures congress_messages].freeze
def self.action_types(action_page = nil)
TYPES.dup.tap do |t|
if action_page.present?
- t.delete(:calls) if !action_page.enable_call
- t.delete(:congress_messages) if !action_page.enable_congress_message
- t.delete(:emails) if !action_page.enable_email
- t.delete(:signatures) if !action_page.enable_petition
- t.delete(:tweets) if !action_page.enable_tweet
+ t.delete(:calls) unless action_page.enable_call
+ t.delete(:congress_messages) unless action_page.enable_congress_message
+ t.delete(:emails) unless action_page.enable_email
+ t.delete(:signatures) unless action_page.enable_petition
+ t.delete(:tweets) unless action_page.enable_tweet
end
end
end
@@ -86,20 +83,9 @@ def self.summary
{ view: views.count, action: actions.count }
end
- def user_opt_out
- if user
- user_id = nil unless user.record_activity?
- end
- end
-
def record_civicrm
- if name == "Action" && user && action_page_id
- user.add_civicrm_activity! action_page_id
- end
- end
-
- def anonymize_views
- self.user_id = nil if name == "View"
+ return unless name == "Action" && user && action_page_id
+ user.add_civicrm_activity! action_page_id
end
end
end
diff --git a/app/models/application_record.rb b/app/models/application_record.rb
new file mode 100644
index 000000000..10a4cba84
--- /dev/null
+++ b/app/models/application_record.rb
@@ -0,0 +1,3 @@
+class ApplicationRecord < ActiveRecord::Base
+ self.abstract_class = true
+end
diff --git a/app/models/bounce.rb b/app/models/bounce.rb
index a3deb6c0a..c1780fdaa 100644
--- a/app/models/bounce.rb
+++ b/app/models/bounce.rb
@@ -1,2 +1,2 @@
-class Bounce < ActiveRecord::Base
+class Bounce < ApplicationRecord
end
diff --git a/app/models/call_campaign.rb b/app/models/call_campaign.rb
index 37c8f7d9d..dd8c55198 100644
--- a/app/models/call_campaign.rb
+++ b/app/models/call_campaign.rb
@@ -1,3 +1,3 @@
-class CallCampaign < ActiveRecord::Base
+class CallCampaign < ApplicationRecord
has_one :action_page
end
diff --git a/app/models/category.rb b/app/models/category.rb
index e3960204f..aa92bc0c4 100644
--- a/app/models/category.rb
+++ b/app/models/category.rb
@@ -1,4 +1,4 @@
-class Category < ActiveRecord::Base
- validates_presence_of :title
- validates_format_of :title, with: /\A[\w\s&]+\Z/
+class Category < ApplicationRecord
+ validates :title, presence: true
+ validates :title, format: { with: /\A[\w\s&]+\Z/ }
end
diff --git a/app/models/complaint.rb b/app/models/complaint.rb
index b0904e938..3b14e25b0 100644
--- a/app/models/complaint.rb
+++ b/app/models/complaint.rb
@@ -1,2 +1,2 @@
-class Complaint < ActiveRecord::Base
+class Complaint < ApplicationRecord
end
diff --git a/app/models/congress_member.rb b/app/models/congress_member.rb
index 43317fa2f..83fc6d3dc 100644
--- a/app/models/congress_member.rb
+++ b/app/models/congress_member.rb
@@ -1,19 +1,19 @@
-class CongressMember < ActiveRecord::Base
- validates_uniqueness_of :bioguide_id
+class CongressMember < ApplicationRecord
+ validates :bioguide_id, uniqueness: true
- scope :current, -> { where("? <= term_end", Time.now) }
+ scope :current, -> { where("? <= term_end", Time.zone.now) }
- scope :filter, ->(f) do
+ scope :search, lambda { |f|
if f.present?
fields = "first_name || ' ' || last_name || ' ' || full_name || ' ' || bioguide_id"
where("LOWER(#{fields}) LIKE ?", "%#{f.downcase}%")
else
all
end
- end
+ }
def current?
- Time.now <= term_end
+ Time.zone.now <= term_end
end
def senate?
diff --git a/app/models/congress_message.rb b/app/models/congress_message.rb
index b67398c5e..29d382fef 100644
--- a/app/models/congress_message.rb
+++ b/app/models/congress_message.rb
@@ -7,11 +7,16 @@ class CongressMessage
attr_accessor :forms, :campaign
attr_writer :common_attributes, :member_attributes
- ALWAYS_COMMON = %w($NAME_FIRST $NAME_LAST $ADDRESS_CITY $ADDRESS_STATE
- $ADDRESS_STREET $ADDRESS_ZIP5 $EMAIL).freeze
+ ALWAYS_COMMON = %w[$NAME_FIRST $NAME_LAST $ADDRESS_CITY $ADDRESS_STATE
+ $ADDRESS_STREET $ADDRESS_ZIP5 $EMAIL].freeze
- def common_attributes() @common_attributes || {}; end
- def member_attributes() @member_attributes || {}; end
+ def common_attributes
+ @common_attributes || {}
+ end
+
+ def member_attributes
+ @member_attributes || {}
+ end
def self.new_from_lookup(location, campaign, forms)
common_attributes = {
@@ -20,13 +25,13 @@ def self.new_from_lookup(location, campaign, forms)
}
if location
common_attributes.merge!({
- "$ADDRESS_STREET" => location.street,
- "$ADDRESS_CITY" => location.city,
- "$ADDRESS_ZIP4" => location.zip4,
- "$ADDRESS_ZIP5" => location.zipcode,
- "$ADDRESS_STATE" => location.state,
- "$ADDRESS_STATE_POSTAL_ABBREV" => location.state
- })
+ "$ADDRESS_STREET" => location.street,
+ "$ADDRESS_CITY" => location.city,
+ "$ADDRESS_ZIP4" => location.zip4,
+ "$ADDRESS_ZIP5" => location.zipcode,
+ "$ADDRESS_STATE" => location.state,
+ "$ADDRESS_STATE_POSTAL_ABBREV" => location.state
+ })
end
new({ common_attributes: common_attributes, forms: forms, campaign: campaign })
end
@@ -45,7 +50,7 @@ def forms_minus_common_fields
@forms.map do |form|
form_minus = form.dup
form_minus.fields = form.fields
- .reject { |x| common_fields.include?(x) }
+ .reject { |x| common_fields.include?(x) }
form_minus
end
end
@@ -56,12 +61,15 @@ def targets
def attributes_for(bioguide_id)
return common_attributes unless member_attributes[bioguide_id]
+
common_attributes.merge(member_attributes[bioguide_id])
end
- def background_submit(test = false)
- if valid?
- @forms.each { |f| f.delay.fill(attributes_for(f.bioguide_id), campaign.campaign_tag, test) }
+ def background_submit(test: false)
+ return unless valid?
+
+ @forms.each do |f|
+ f.delay.fill(attributes_for(f.bioguide_id), campaign.campaign_tag, test)
end
end
@@ -77,9 +85,7 @@ def attributes_satisfy_forms
@forms.each do |form|
attributes = attributes_for(form.bioguide_id)
form.fields.each do |field|
- if !field.validate(attributes[field.value])
- errors.add(:base, "Invalid input for #{field.value}")
- end
+ errors.add(:base, "Invalid input for #{field.value}") unless field.validate(attributes[field.value])
end
end
end
diff --git a/app/models/congress_message_campaign.rb b/app/models/congress_message_campaign.rb
index 3ec85b171..3e2ee674e 100644
--- a/app/models/congress_message_campaign.rb
+++ b/app/models/congress_message_campaign.rb
@@ -1,4 +1,4 @@
-class CongressMessageCampaign < ActiveRecord::Base
+class CongressMessageCampaign < ApplicationRecord
belongs_to :topic_category
has_one :action_page
@@ -65,7 +65,7 @@ def target_specific_legislators
private
def target_bioguide_text_or_default(custom_text, default)
- if !target_bioguide_ids or custom_text.blank?
+ if !target_bioguide_ids || custom_text.blank?
default
else
custom_text
diff --git a/app/models/congress_scorecard.rb b/app/models/congress_scorecard.rb
index 092f922c8..ecca65aeb 100644
--- a/app/models/congress_scorecard.rb
+++ b/app/models/congress_scorecard.rb
@@ -2,7 +2,7 @@
# petition action that drew in a signature from one of their constituents
# So calling #counter on a model will display the number of signatures from
# that member's constituents
-class CongressScorecard < ActiveRecord::Base
+class CongressScorecard < ApplicationRecord
belongs_to :action_page
def increment!
diff --git a/app/models/email_campaign.rb b/app/models/email_campaign.rb
index 604935b9b..fceb74b87 100644
--- a/app/models/email_campaign.rb
+++ b/app/models/email_campaign.rb
@@ -1,7 +1,10 @@
-class EmailCampaign < ActiveRecord::Base
+class EmailCampaign < ApplicationRecord
belongs_to :topic_category
has_one :action_page
+ # No DC
+ STATES = %w[AK AL AR AZ CA CO CT DE FL GA HI IA ID IL IN KS KY LA MA MD ME MI MN MO MS MT NC ND NE NH NJ NM NV NY OH OK OR PA RI SC SD TN TX UT VA VT WA WI WV WY].freeze
+
def email_your_rep_text(default)
target_bioguide_text_or_default alt_text_email_your_rep, default
end
@@ -22,19 +25,40 @@ def extra_fields_explain_text(default)
target_bioguide_text_or_default alt_text_extra_fields_explain, default
end
+ def leg_level
+ return "legislatorLowerBody" if target_state_lower_chamber
+ return "legislatorUpperBody" if target_state_upper_chamber
+ return "headOfGovernment" if target_governor
+
+ ""
+ end
+
include ERB::Util
- def service_uri(service)
- mailto_addresses = email_addresses.split(/\s*,\s*/).map do |email|
- u(email.gsub(" ", "")).gsub("%40", "@")
+ def service_uri(service, opts = {})
+ mailto_addresses = opts[:email]
+ mailto_addresses ||= email_addresses
+ # look for custom email addresses set on the back end if there is no email param from the front-end,
+ # as is the case when we send state-level emails -- we cannot store these email address in our db,
+ # reason below:
+
+ # https://developers.google.com/terms#e_prohibitions_on_content
+ # Section 5.e.1., as of December 2022
+ # e. Prohibitions on Content
+ # Unless expressly permitted by the content owner or by applicable law, you will not, and will not permit your end users or others acting on your behalf to, do the following with content returned from the APIs:
+ # Scrape, build databases, or otherwise create permanent copies of such content, or keep cached copies longer than permitted by the cache header;
+
+ # results in comma-separated string of email addresses
+ default_mailto_addresses ||= mailto_addresses.split(/\s*,\s*/).map do |email|
+ u(email.delete(" ")).gsub("%40", "@").gsub("%2B", "+")
end.join(",")
{
- default: "mailto:#{mailto_addresses}?#{query(body: message, subject: subject)}",
+ default: "mailto:#{default_mailto_addresses}?#{query(body: message, subject: subject)}",
- gmail: "https://mail.google.com/mail/?view=cm&fs=1{{ to: email_addresses, body: message, su: subject }.to_query}",
+ gmail: "https://mail.google.com/mail/?view=cm&fs=1{{ to: mailto_addresses, body: message, su: subject }.to_query}",
- hotmail: "https://outlook.live.com/default.aspx?rru=compose{{ to: email_addresses, body: message, subject: subject }.to_query}#page=Compose"
+ hotmail: "https://outlook.live.com/default.aspx?rru=compose{{ to: mailto_addresses, body: message, subject: subject }.to_query}#page=Compose"
}.fetch(service.to_sym)
end
@@ -48,7 +72,7 @@ def query(hash)
end
def target_bioguide_text_or_default(custom_text, default)
- if !target_bioguide_id or custom_text.blank?
+ if !target_bioguide_id || custom_text.blank?
default
else
custom_text
diff --git a/app/models/featured_action_page.rb b/app/models/featured_action_page.rb
index 78a0c3bae..60deafad2 100644
--- a/app/models/featured_action_page.rb
+++ b/app/models/featured_action_page.rb
@@ -1,6 +1,6 @@
-class FeaturedActionPage < ActiveRecord::Base
+class FeaturedActionPage < ApplicationRecord
belongs_to :action_page
- validates_presence_of :action_page, :weight
+ validates :action_page, :weight, presence: true
def initialize(attributes = {})
super(attributes.reverse_merge(weight: 0))
@@ -9,7 +9,8 @@ def initialize(attributes = {})
def self.load_for_edit
existing = order(:weight).preload(:action_page)
return existing unless existing.length < 4
+
weights_to_create = (1..4).to_a - existing.map(&:weight)
- existing += weights_to_create.map { |w| new(weight: w) }
+ existing + weights_to_create.map { |w| new(weight: w) }
end
end
diff --git a/app/models/institution.rb b/app/models/institution.rb
index c81c09f8f..ef6a8d1ee 100644
--- a/app/models/institution.rb
+++ b/app/models/institution.rb
@@ -1,14 +1,14 @@
-class Institution < ActiveRecord::Base
+class Institution < ApplicationRecord
require "csv"
extend FriendlyId
- friendly_id :name, use: [:slugged, :history]
+ friendly_id :name, use: %i[slugged history]
- include PgSearch
+ include PgSearch::Model
pg_search_scope :search,
- against: [
- :name,
- :category
+ against: %i[
+ name
+ category
],
using: { tsearch: { prefix: true } }
@@ -16,15 +16,16 @@ class Institution < ActiveRecord::Base
has_many :action_pages, through: :action_institutions
has_many :affiliations
- validates_presence_of :name
- validates_uniqueness_of :name
- validates_presence_of :category
+ validates :name, presence: true
+ validates :name, uniqueness: true
+ validates :category, presence: true
def self.process_csv(csv_file)
[].tap do |names|
CSV.foreach(csv_file.path, headers: true) do |row|
row = row.to_hash
return [] unless row["name"]
+
names << row["name"]
end
end
@@ -39,22 +40,12 @@ def self.import(category, names)
end
def self.categories
- all.distinct.pluck(:category)
- end
-
- # Sort institutions by most popular.
- # Put `first` at the top of the list if it exists.
- def self.top(n, first: 0)
- select("institutions.*, COUNT(signatures.id) AS s_count")
- .joins("LEFT OUTER JOIN affiliations ON institutions.id = affiliations.institution_id")
- .joins("LEFT OUTER JOIN signatures ON affiliations.signature_id = signatures.id")
- .group("institutions.id")
- .order("institutions.id = #{first.to_i} desc", "s_count DESC", "institutions.name")
- .limit(n)
+ distinct.pluck(:category)
end
def included_in_active_actions?
return false if action_pages.empty?
+
action_pages.map(&:status).any? "live"
end
end
diff --git a/app/models/partner.rb b/app/models/partner.rb
index 4f665124f..703d73799 100644
--- a/app/models/partner.rb
+++ b/app/models/partner.rb
@@ -1,17 +1,11 @@
-class Partner < ActiveRecord::Base
- extend AmazonCredentials
+class Partner < ApplicationRecord
acts_as_paranoid
has_many :subscriptions
has_many :users
has_many :partnerships
has_many :action_pages, through: :partnerships
- has_attached_file :logo, amazon_credentials
-
- validates_media_type_spoof_detection :logo,
- if: -> { logo.present? && logo_file_name_came_from_user? }
- do_not_validate_attachment_file_type [:logo]
- validates_uniqueness_of :code
+ validates :code, uniqueness: true
def to_csv(options = {})
column_names = %w[first_name last_name email created_at]
diff --git a/app/models/partnership.rb b/app/models/partnership.rb
index 7f832d22b..0576af137 100644
--- a/app/models/partnership.rb
+++ b/app/models/partnership.rb
@@ -1,4 +1,4 @@
-class Partnership < ActiveRecord::Base
+class Partnership < ApplicationRecord
belongs_to :partner
belongs_to :action_page
end
diff --git a/app/models/petition.rb b/app/models/petition.rb
index 6c864dc1b..6869f85fe 100644
--- a/app/models/petition.rb
+++ b/app/models/petition.rb
@@ -1,20 +1,21 @@
-class Petition < ActiveRecord::Base
+class Petition < ApplicationRecord
has_one :action_page
has_many :signatures
after_initialize :set_goal
def percent_complete
return 0 if goal == 0
- [signatures.count.to_f / goal.to_f, 1].min * 100
+
+ [signatures.count / goal.to_f, 1].min * 100
end
def recent_signatures(num)
recent = []
- signatures.last(num).reverse.each do |s|
+ signatures.last(num).reverse_each do |s|
if s.anonymous
- recent.push(s.as_json(only: [], methods: [:time_ago, :location]))
+ recent.push(s.as_json(only: [], methods: %i[time_ago location]))
else
- recent.push(s.as_json(only: [:first_name, :last_name, :city], methods: [:time_ago, :location]))
+ recent.push(s.as_json(only: %i[first_name last_name city], methods: %i[time_ago location]))
end
end
recent
@@ -22,7 +23,7 @@ def recent_signatures(num)
def signatures_by_institution(institution)
signatures.includes(affiliations: :institution)
- .where(institutions: { id: institution })
+ .where(institutions: { id: institution })
end
def location_required?
@@ -30,14 +31,12 @@ def location_required?
end
def to_s
- "#{title}-exported_on-#{DateTime.now.strftime("%Y-%m-%d")}"
+ "#{title}-exported_on-#{DateTime.now.strftime('%Y-%m-%d')}"
end
private
def set_goal
- if new_record?
- goal = 100
- end
+ self.goal = 100 if new_record?
end
end
diff --git a/app/models/signature.rb b/app/models/signature.rb
index 7d797c471..ff7a34449 100644
--- a/app/models/signature.rb
+++ b/app/models/signature.rb
@@ -1,16 +1,16 @@
-include GoingPostal
+class Signature < ApplicationRecord
+ include GoingPostal
-class Signature < ActiveRecord::Base
- belongs_to :user
+ belongs_to :user, optional: true
belongs_to :petition
has_many :affiliations
before_validation :format_zipcode
- before_save :sanitize_input
- validates_presence_of :first_name, :last_name, :petition_id,
- message: "This can't be blank."
+ before_validation :sanitize_input
+ validates :first_name, :last_name, :petition_id,
+ presence: { message: "This can't be blank." }
- validates_presence_of :country_code, if: :location_required?
+ validates :country_code, presence: { if: :location_required? }
validates :email, email: true
validates :email, uniqueness: { scope: :petition_id,
@@ -20,15 +20,15 @@ class Signature < ActiveRecord::Base
accepts_nested_attributes_for :affiliations, reject_if: :all_blank
- scope :filter, ->(f) do
+ scope :search, lambda { |f|
if f.present?
- where("LOWER(email) LIKE ? " +
+ where("LOWER(email) LIKE ? " \
"OR LOWER(first_name || ' ' || last_name) LIKE ?",
"%#{f}%".downcase, "%#{f}%".downcase)
else
all
end
- end
+ }
include ActionView::Helpers::DateHelper
@@ -38,7 +38,7 @@ def self.to_csv(options = {})
CSV.generate(options) do |csv|
csv << column_names
- all.each do |sub|
+ find_each do |sub|
csv << sub.attributes.values_at(*column_names)
end
end
@@ -47,22 +47,22 @@ def self.to_csv(options = {})
def self.to_presentable_csv(options = {})
column_names = %w[full_name email city state country]
- CSV.generate(options) do |csv|
+ CSV.generate(**options) do |csv|
csv << column_names
- all.each do |signature|
+ find_each do |signature|
csv << signature.to_csv_line
end
end
end
def self.to_affiliation_csv(options = {})
- column_names = %w[full_name, institution, affiliation_type]
+ column_names = %w[full_name institution affiliation_type]
CSV.generate(options) do |csv|
csv << column_names
- all.each do |s|
+ find_each do |s|
affiliation = s.affiliations.first or next
csv << [
@@ -75,18 +75,18 @@ def self.to_affiliation_csv(options = {})
end
def self.institutions
- joins(affiliations: :institution).
- distinct.pluck("institutions.name, institutions.id").sort
+ joins(affiliations: :institution)
+ .distinct.pluck("institutions.name, institutions.id").sort
end
def self.pretty_count
- ActiveSupport::NumberHelper::number_to_delimited(self.count, delimiter: ",")
+ ActiveSupport::NumberHelper.number_to_delimited(count, delimiter: ",")
end
def arbitrary_opinion_of_country_string_validity
- if country_code.present? and full_country_name.nil?
- errors.add(:country_code, "Country Code might come from a spam bot.")
- end
+ return unless country_code.present? && full_country_name.nil?
+
+ errors.add(:country_code, "Country Code might come from a spam bot.")
end
def name
@@ -118,17 +118,15 @@ def location_required?
end
def full_country_name
- begin
- IsoCountryCodes.find(country_code).name
- rescue IsoCountryCodes::UnknownCodeError
- nil
- end
+ IsoCountryCodes.find(country_code).name
+ rescue IsoCountryCodes::UnknownCodeError
+ nil
end
private
def format_zipcode
- zipcode = GoingPostal.format_zipcode(zipcode, country_code) || zipcode
+ self.zipcode = GoingPostal.format_zipcode(zipcode, country_code) || zipcode
end
def sanitize_input
@@ -143,8 +141,8 @@ def sanitize_input
end
def validate_zipcode
- unless GoingPostal.valid_zipcode?(zipcode, country_code)
- errors.add(:zipcode, "Invalid zip/postal code for country")
- end
+ return if GoingPostal.valid_zipcode?(zipcode, country_code)
+
+ errors.add(:zipcode, "Invalid zip/postal code for country")
end
end
diff --git a/app/models/source_file.rb b/app/models/source_file.rb
index 63b1022ca..8574ae639 100644
--- a/app/models/source_file.rb
+++ b/app/models/source_file.rb
@@ -1,7 +1,7 @@
-class SourceFile < ActiveRecord::Base
+class SourceFile < ApplicationRecord
include Rails.application.routes.url_helpers
- validates_presence_of :file_name, :file_content_type, :file_size, :key, :bucket
+ validates :file_name, :file_content_type, :file_size, :key, :bucket, presence: true
delegate :secrets, to: "Rails.application".to_sym
@@ -23,8 +23,16 @@ class SourceFile < ActiveRecord::Base
def pull_down_s3_object_attributes
Rails.logger.debug "Trying to validate S3 object."
self.file_name = key.split("/").last if key
- self.file_size ||= s3_object.content_length rescue nil
- self.file_content_type ||= s3_object.content_type rescue nil
+ self.file_size ||= begin
+ s3_object.content_length
+ rescue StandardError
+ nil
+ end
+ self.file_content_type ||= begin
+ s3_object.content_type
+ rescue StandardError
+ nil
+ end
false
end
@@ -33,7 +41,7 @@ def full_url
if ENV["amazon_bucket_url"]
"https://#{ENV['amazon_bucket_url']}/#{key}"
else # we have to build the url up from amazon information
- "https://#{ENV['amazon_bucket']}.#{AmazonCredentials.build_s3_host_name}/#{key}"
+ "https://#{ENV['amazon_bucket']}.s3-#{Rails.application.secrets.amazon_region}.amazonaws.com/#{key}"
end
end
@@ -43,7 +51,7 @@ def to_jq_upload
"name" => file_name,
"size" => file_size,
"full_url" => full_url,
- "image" => self.is_image?,
+ "image" => is_image?,
"delete_url" => Rails.application.routes.url_helpers.admin_source_file_path(self, format: :json)
}
end
diff --git a/app/models/subscription.rb b/app/models/subscription.rb
index 81cf3cbf4..36322681b 100644
--- a/app/models/subscription.rb
+++ b/app/models/subscription.rb
@@ -1,4 +1,4 @@
-class Subscription < ActiveRecord::Base
+class Subscription < ApplicationRecord
belongs_to :partner, counter_cache: true
validates :email, presence: true, email: true
validates :email, uniqueness: { scope: :partner_id }
diff --git a/app/models/topic.rb b/app/models/topic.rb
index 3e69c04c2..667c86dd5 100644
--- a/app/models/topic.rb
+++ b/app/models/topic.rb
@@ -1,3 +1,3 @@
-class Topic < ActiveRecord::Base
+class Topic < ApplicationRecord
belongs_to :topic_set
end
diff --git a/app/models/topic_category.rb b/app/models/topic_category.rb
index fd08268bc..a6c8aff5b 100644
--- a/app/models/topic_category.rb
+++ b/app/models/topic_category.rb
@@ -1,19 +1,17 @@
-class TopicCategory < ActiveRecord::Base
+class TopicCategory < ApplicationRecord
has_many :topic_sets, dependent: :destroy
has_many :email_campaigns
has_many :congress_message_campaigns
def as_2d_array
- arr = []
- topic_sets.order(:tier).each do |ts|
- arr.push ts.topics.map { |t| t.name }
+ arr = topic_sets.order(:tier).map do |ts|
+ ts.topics.map(&:name)
end
- arr
end
def best_match(options)
topics = topic_sets.order(:tier).reduce([]) do |arr, ts|
- arr += ts.topics
+ arr + ts.topics
end
topics.each do |topic|
diff --git a/app/models/topic_set.rb b/app/models/topic_set.rb
index 916375ee2..ecda608f8 100644
--- a/app/models/topic_set.rb
+++ b/app/models/topic_set.rb
@@ -1,4 +1,4 @@
-class TopicSet < ActiveRecord::Base
+class TopicSet < ApplicationRecord
belongs_to :topic_category
has_many :topics, dependent: :destroy
end
diff --git a/app/models/tweet.rb b/app/models/tweet.rb
index ae5d52be7..f94782e25 100644
--- a/app/models/tweet.rb
+++ b/app/models/tweet.rb
@@ -1,9 +1,9 @@
-class Tweet < ActiveRecord::Base
+class Tweet < ApplicationRecord
has_one :action_page
has_many :tweet_targets
alias :targets :tweet_targets
accepts_nested_attributes_for :tweet_targets, reject_if: :all_blank,
- allow_destroy: true
+ allow_destroy: true
def target_congress?
target_house? || target_senate?
diff --git a/app/models/tweet_target.rb b/app/models/tweet_target.rb
index 57b154db4..bdb5d43bc 100644
--- a/app/models/tweet_target.rb
+++ b/app/models/tweet_target.rb
@@ -1,34 +1,7 @@
-class TweetTarget < ActiveRecord::Base
- extend AmazonCredentials
- require "open-uri"
-
+class TweetTarget < ApplicationRecord
belongs_to :tweet
- has_attached_file :image, amazon_credentials
- validates_media_type_spoof_detection :image, if: ->() { image_file_name.present? }
- do_not_validate_attachment_file_type :image
- after_save :attach_twitter_image
def url
- "https://twitter.com/" + twitter_id
- end
-
- def image_url
- image.url
- end
-
- def attach_twitter_image
- self.delay.attach_twitter_image_without_delay if image_file_name.nil? and Twitter.has_api_keys?
- end
-
- def attach_twitter_image_without_delay
- access_token = Twitter.prepare_access_token Rails.application.secrets.twitter_oauth_token, Rails.application.secrets.twitter_oauth_token_secret
-
- # ref: https://dev.twitter.com/overview/general/user-profile-images-and-banners
- response = access_token.request(:get, "https://api.twitter.com/1.1/users/show.json?screen_name=" + twitter_id)
- user_info = JSON.parse response.body
- user_image_url = user_info["profile_image_url_https"].gsub(/_normal\./, "_bigger.")
-
- self.image = URI.parse(user_image_url)
- self.save
+ "https://twitter.com/#{twitter_id}"
end
end
diff --git a/app/models/twitter.rb b/app/models/twitter.rb
index 117123ec9..0ea83eaac 100644
--- a/app/models/twitter.rb
+++ b/app/models/twitter.rb
@@ -1,21 +1,22 @@
class Twitter
def self.has_api_keys?
- !Rails.application.secrets.twitter_api_key.blank? &&
- !Rails.application.secrets.twitter_api_secret.blank? &&
- !Rails.application.secrets.twitter_oauth_token.blank? &&
- !Rails.application.secrets.twitter_oauth_token_secret.blank?
+ Rails.application.secrets.twitter_api_key.present? &&
+ Rails.application.secrets.twitter_api_secret.present? &&
+ Rails.application.secrets.twitter_oauth_token.present? &&
+ Rails.application.secrets.twitter_oauth_token_secret.present?
end
# ref: https://dev.twitter.com/oauth/overview/single-user
def self.prepare_access_token(oauth_token, oauth_token_secret)
consumer = OAuth::Consumer.new(
- Rails.application.secrets.twitter_api_key,
- Rails.application.secrets.twitter_api_secret,
- { site: "https://api.twitter.com", scheme: :header })
+ Rails.application.secrets.twitter_api_key,
+ Rails.application.secrets.twitter_api_secret,
+ { site: "https://api.twitter.com", scheme: :header }
+ )
# now create the access token object from passed values
token_hash = { oauth_token: oauth_token,
oauth_token_secret: oauth_token_secret }
- access_token = OAuth::AccessToken.from_hash(consumer, token_hash)
+ OAuth::AccessToken.from_hash(consumer, token_hash)
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 526b66a5c..0a11d5889 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -1,9 +1,9 @@
require "civicrm"
-class User < ActiveRecord::Base
- include CiviCRM::UserMethods
+class User < ApplicationRecord
+ include Civicrm::UserMethods
- include PgSearch
- pg_search_scope :search, against: [:email, :first_name, :last_name]
+ include PgSearch::Model
+ pg_search_scope :search, against: %i[email first_name last_name]
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
@@ -12,7 +12,7 @@ class User < ActiveRecord::Base
remember_for: 90.days
has_many :signatures
has_many :user_preferences
- has_many :events, class_name: Ahoy::Event
+ has_many :events, class_name: "Ahoy::Event"
belongs_to :partner
validates :email, email: true
validate :password_complexity
@@ -25,7 +25,7 @@ class User < ActiveRecord::Base
alias :preferences :user_preferences
- scope :authors, ->() { joins(:action_pages).distinct }
+ scope :authors, -> { joins(:action_pages).distinct }
def self.group_created_in_range(start_date, end_date)
if start_date == end_date
@@ -42,11 +42,13 @@ def invalidate_password_reset_tokens
end
def email_taken?
- errors.added? :email, :taken
+ return false unless errors.include? :email
+
+ errors.details[:email].any? { |x| x.value?(:taken) }
end
def send_email_taken_notice
- if self.confirmed?
+ if confirmed?
UserMailer.signup_attempt_with_existing_email(self).deliver_now
else
send_confirmation_instructions
@@ -54,9 +56,7 @@ def send_email_taken_notice
end
def password_complexity
- if admin? && password.present? and password.length < 30
- errors.add :password, "must be at least 30 (try choosing 6 memorable words)"
- end
+ errors.add :password, "must be at least 30 (try choosing 6 memorable words)" if admin? && password.present? && (password.length < 30)
end
def name
@@ -64,21 +64,9 @@ def name
end
def display_name
- return name unless name.blank?
- email
- end
-
- def percentile_rank
- user_action_counts = Rails.cache.fetch("user_action_counts", expires_in: 24.hours) {
- User.select("users.id, count(ahoy_events.id) AS events_count")
- .joins("LEFT OUTER JOIN ahoy_events ON ahoy_events.user_id = users.id")
- .where("ahoy_events.name IS null OR ahoy_events.name = ?", "Action")
- .group("users.id")
- .map { |u| u.events_count }
- }
+ return name if name.present?
- user_count = events.actions.count
- percentile = user_action_counts.percentile_rank(user_count - 1).round(0)
+ email
end
def signed?(petition)
@@ -124,19 +112,25 @@ def privileged_role?
# This is here for collission avoidance when generating new user names in tests
def self.next_id
- self.last.nil? ? 1 : self.last.id + 1
+ last.nil? ? 1 : last.id + 1
end
# We're allowing unconfirmed users to reset their passwords by
# re-registering. In that case, they shouldn't get a password reset
# notification.
def send_password_change_notification?
- self.confirmed? && super
+ confirmed? && super
+ end
+
+ def can_view_archived?(action_page)
+ return true if admin?
+
+ taken_action? action_page
end
protected
def after_confirmation
- subscribe!(opt_in = true) if self.subscribe?
+ subscribe!(opt_in: true) if subscribe?
end
end
diff --git a/app/models/user_preference.rb b/app/models/user_preference.rb
index 9e7860cb4..200d8ccf9 100644
--- a/app/models/user_preference.rb
+++ b/app/models/user_preference.rb
@@ -1,5 +1,5 @@
-class UserPreference < ActiveRecord::Base
+class UserPreference < ApplicationRecord
belongs_to :user
- validates_presence_of :name
- validates_presence_of :value
+ validates :name, presence: true
+ validates :value, presence: true
end
diff --git a/app/models/visit.rb b/app/models/visit.rb
index 6bb47fed0..9bcf891d7 100644
--- a/app/models/visit.rb
+++ b/app/models/visit.rb
@@ -1,4 +1,4 @@
-class Visit < ActiveRecord::Base
+class Visit < ApplicationRecord
has_many :ahoy_events, class_name: "Ahoy::Event"
belongs_to :user
end
diff --git a/app/queries/action_page_filters.rb b/app/queries/action_page_filters.rb
index 98d379cd9..d0ba042d3 100644
--- a/app/queries/action_page_filters.rb
+++ b/app/queries/action_page_filters.rb
@@ -14,6 +14,7 @@ def run
filters.each do |f, val|
next unless valid_query?(f, val)
+
@relation = if NAMED_SCOPES.include? f
relation.send(f, val)
else
@@ -25,8 +26,8 @@ def run
private
- NAMED_SCOPES = %i(type status).freeze
- VALID_FILTERS = %i(type status author category).freeze
+ NAMED_SCOPES = %i[type status].freeze
+ VALID_FILTERS = %i[type status author category].freeze
attr_accessor :relation, :filters
@@ -35,7 +36,8 @@ def empty_value?(val)
end
def process_date_range
- return unless filters[:date_range].present?
+ return if filters[:date_range].blank?
+
start_date, end_date = parse_date_range
@relation = relation.where(created_at: start_date..(end_date + 1.day))
end
@@ -50,8 +52,6 @@ def valid_query?(f, val)
end
def validate_filter_name(f)
- unless VALID_FILTERS.include? f
- raise ArgumentError, "unrecognized filter #{f}"
- end
+ raise ArgumentError, "unrecognized filter #{f}" unless VALID_FILTERS.include? f
end
end
diff --git a/app/queries/top_institutions_query.rb b/app/queries/top_institutions_query.rb
new file mode 100644
index 000000000..10215ec51
--- /dev/null
+++ b/app/queries/top_institutions_query.rb
@@ -0,0 +1,34 @@
+class TopInstitutionsQuery
+ def self.run(**args)
+ new(**args).run
+ end
+
+ def initialize(action_page:, limit: 300, exclude: [])
+ @action_page = action_page
+ @limit = limit
+ @exclusions = exclude.compact.map(&:id)
+ end
+
+ def run
+ action_page.institutions
+ .where.not(id: exclusions)
+ .left_outer_joins(affiliations: [:signature])
+ .distinct
+ # TODO: break up / document
+ .select("institutions.*, COUNT(signatures.id) AS sig_count")
+ .group("institutions.id")
+ .order("sig_count DESC", "institutions.name")
+ .limit(limit)
+ end
+
+ private
+
+ attr_reader :action_page, :limit, :exclusions
+
+ def source_collection
+ @source_collection ||= action_page.institutions
+ return @source_collection if exclusions.empty?
+
+ @source_collection = @source_collection.where.not(id: exclusions)
+ end
+end
diff --git a/app/uploaders/action_page_image_uploader.rb b/app/uploaders/action_page_image_uploader.rb
new file mode 100644
index 000000000..43a5ffa3d
--- /dev/null
+++ b/app/uploaders/action_page_image_uploader.rb
@@ -0,0 +1,27 @@
+class ActionPageImageUploader < CarrierWave::Uploader::Base
+ storage :fog
+ # cache_storage :file
+
+ def default_url(*args)
+ "missing.png"
+ end
+
+ def store_dir
+ "#{model.class.to_s.pluralize.underscore}/#{mounted_as.to_s.pluralize}/#{id_partition}/#{style}"
+ end
+
+ # we could set this here or config/initializers/carrier_wave.rb
+ def asset_host
+ Rails.application.secrets.amazon_bucket_url.present? ? "https://#{Rails.application.secrets.amazon_bucket_url}" : super
+ end
+
+ private
+
+ def style
+ version_name || "original"
+ end
+
+ def id_partition # mimics paperclips mapping function
+ ("%09d" % model.id).scan(/\d{3}/).join("/")
+ end
+end
diff --git a/app/validators/email_validator.rb b/app/validators/email_validator.rb
index 676a65476..874cce619 100644
--- a/app/validators/email_validator.rb
+++ b/app/validators/email_validator.rb
@@ -1,7 +1,5 @@
class EmailValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
- unless value =~ /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i
- record.errors[attribute] << (options[:message] || "is not an email")
- end
+ record.errors[attribute] << (options[:message] || "is not an email") unless /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\z/i.match?(value)
end
end
diff --git a/app/views/action_page/_meta_tags.html.erb b/app/views/action_page/_meta_tags.html.erb
index 382706cc6..5136ff61d 100644
--- a/app/views/action_page/_meta_tags.html.erb
+++ b/app/views/action_page/_meta_tags.html.erb
@@ -1,7 +1,7 @@
<% summary = strip_tags stripdown(@actionPage.summary) -%>
<%
- image_url = if @actionPage.image.try(:exists?)
- image_url(@actionPage.image.to_s)
+ image_url = if @actionPage.image.present?
+ image_url(@actionPage.image.url)
else
image_url("og-image-default.png")
end
diff --git a/app/views/action_page/_partner_logos.html.erb b/app/views/action_page/_partner_logos.html.erb
deleted file mode 100644
index 27b862cff..000000000
--- a/app/views/action_page/_partner_logos.html.erb
+++ /dev/null
@@ -1,9 +0,0 @@
-<% if @actionPage.partners.present? && @actionPage.partners.any? { |p| p.logo.present? } %>
-
Who We Are
-
- <%= image_tag "EFF_Monogram-red" %>
- <% @actionPage.partners.each do |partner| %>
- <%= image_tag partner.logo if partner.logo.present? %>
- <% end %>
-
-<% end %>
diff --git a/app/views/action_page/_state_reps.html.erb b/app/views/action_page/_state_reps.html.erb
new file mode 100644
index 000000000..58740e8d3
--- /dev/null
+++ b/app/views/action_page/_state_reps.html.erb
@@ -0,0 +1,17 @@
+
+ <%= "This action is for the #{legislative_level_from_state_representative_info(@email_campaign.leg_level)}." %>
+ <% @state_reps.each do |sr| %>
+
+ <%= "Your representative is #{sr['name']}" %>.
+ <% if sr["emails"].present? %>
+ <%= "They can be reached at: #{sr['emails'].join(', ')}" %>
+ <% else %>
+ <%= "We could not find their email address." %>
+ <% end %>
+
+ <% end %>
+
+
+
+ <%= render 'tools/send_email' %>
+
diff --git a/app/views/action_page/index.atom.builder b/app/views/action_page/index.atom.builder
index cf969cdc4..6b300b7ae 100644
--- a/app/views/action_page/index.atom.builder
+++ b/app/views/action_page/index.atom.builder
@@ -1,19 +1,22 @@
atom_feed do |feed|
- feed.title(t :site_title)
- feed.subtitle(t :summary)
- feed.updated(@actionPages[0].created_at) if @actionPages.length > 0
+ feed.title(t(:site_title))
+ feed.subtitle(t(:summary))
+ feed.updated(@actionPages[0].created_at) unless @actionPages.empty?
@actionPages.each do |actionPage|
feed.entry(actionPage) do |entry|
- entry.link(rel: "enclosure", type: actionPage.featured_image.content_type || "image/png",
- href: URI.join(root_url, image_path(actionPage.featured_image)))
+ entry.link(
+ rel: "enclosure",
+ type: (actionPage.featured_image.content_type.presence || "image/png"),
+ href: URI.join(root_url, image_path(actionPage.featured_image.url))
+ )
entry.title(actionPage.title)
entry.summary(markdown(actionPage.summary), type: "html")
entry.content(markdown(actionPage.description), type: "html")
entry.author do |author|
- author.name(t :organization_name)
+ author.name(t(:organization_name))
end
end
end
diff --git a/app/views/action_page/index.html.erb b/app/views/action_page/index.html.erb
index ecfd70701..321061b8d 100644
--- a/app/views/action_page/index.html.erb
+++ b/app/views/action_page/index.html.erb
@@ -7,7 +7,7 @@
<%= form_tag action_page_index_path, method: :get, id: "action-page-filter" do %>
<%= select_tag :category,
- options_from_collection_for_select(Category.all.order(:title).uniq,
+ options_from_collection_for_select(Category.all.order(:title).distinct,
:title, :title, params[:category]),
include_blank: "All campaigns" %>
<% end %>
@@ -18,7 +18,7 @@
<%= link_to action_page_path(actionPage) do%>
- <%= image_tag(actionPage.featured_image) %>
+ <%= image_tag(actionPage.featured_image.url) %>
<% end %>
diff --git a/app/views/action_page/index.json.jbuilder b/app/views/action_page/index.json.jbuilder
index 761f1f25b..db98d0fbc 100644
--- a/app/views/action_page/index.json.jbuilder
+++ b/app/views/action_page/index.json.jbuilder
@@ -4,7 +4,7 @@ json.array! @actionPages do |actionPage|
json.summary markdown actionPage.summary
if actionPage.featured_image_file_name
json.featured_image do
- json.alt image_alt actionPage.featured_image_file_name
+ json.alt actionPage.featured_image_file_name.titleize
json.url image_url actionPage.featured_image
end
end
diff --git a/app/views/action_page/show.html.erb b/app/views/action_page/show.html.erb
index c025665bd..52fdca997 100644
--- a/app/views/action_page/show.html.erb
+++ b/app/views/action_page/show.html.erb
@@ -10,11 +10,9 @@
<%= @actionPage.category.title -%>
<% end %>
<%= @actionPage.title -%>
- <%= image_tag(@actionPage.featured_image) %>
+ <%= image_tag(@actionPage.featured_image.url) %>
<%= markdown @actionPage.summary -%>
- <%= render "action_page/partner_logos" %>
-
<% if @actionPage.enable_petition? && @petition && @petition.description.present? && !@actionPage.description.include?('``` letter') -%>
<%= render(partial: "action_page/letter", layout: false) %>
<% end -%>
diff --git a/app/views/admin/action_pages/_email_fields.html.erb b/app/views/admin/action_pages/_email_fields.html.erb
index e8ee74353..0a0c98ab7 100644
--- a/app/views/admin/action_pages/_email_fields.html.erb
+++ b/app/views/admin/action_pages/_email_fields.html.erb
@@ -1,8 +1,4 @@
<%= f.fields_for(:email_campaign) do |sf| %>
-
- <%= sf.label :email_addresses, "To" %>
- <%= sf.text_field :email_addresses %>
-
<%= sf.label :subject %>
@@ -13,4 +9,36 @@
<%= sf.label :message %>
<%= sf.text_area :message %>
+
+
+
<% end %>
diff --git a/app/views/admin/action_pages/_gallery.html.erb b/app/views/admin/action_pages/_gallery.html.erb
index 1f315d914..5022f32d7 100644
--- a/app/views/admin/action_pages/_gallery.html.erb
+++ b/app/views/admin/action_pages/_gallery.html.erb
@@ -1,10 +1,12 @@
<% if defined?(f) %>
+
<%= f.send :hidden_field, field, value: nil %>
+ <%= f.send :hidden_field, "remote_#{field}_url", value: nil %>
<% if current_value = f.object.send(field).presence %>