diff --git a/.rubocop.yml b/.rubocop.yml index 4a1663d5ae..0c855b37a2 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -1,7 +1,7 @@ inherit_from: .rubocop_todo.yml AllCops: - TargetRubyVersion: 2.3 + TargetRubyVersion: 2.4 Exclude: - 'bin/**/*' - 'db/schema.rb' @@ -28,12 +28,6 @@ Style/MultilineMethodCallIndentation: Style/BracesAroundHashParameters: EnforcedStyle: context_dependent -Lint/BlockAlignment: - AlignWith: start_of_block - -Lint/EndAlignment: - AlignWith: keyword - Lint/InheritException: Enabled: false diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 7a4111964a..0565dc305d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -167,6 +167,17 @@ Style/SingleLineBlockParams: Exclude: - 'spec/support/helper_functions.rb' +Style/EmptyMethod: + Enabled: false + +Metrics/BlockLength: + Exclude: + - Guardfile + - app/admin/** + - config/**/* + - lib/**/* + - spec/**/* + Metrics/LineLength: Max: 120 Exclude: diff --git a/Gemfile b/Gemfile index f31b32dfdf..917282644b 100644 --- a/Gemfile +++ b/Gemfile @@ -3,83 +3,83 @@ source 'https://rubygems.org' ruby '2.4.0' -gem 'rails', '4.2.8' -gem 'rake' -gem 'rails-observers' -gem 'readthis' -gem 'hiredis' -gem 'redis', '>= 3.2.0', require: ['redis', 'redis/connection/hiredis'] -gem 'pg' -gem 'jquery-rails' -gem 'selectize-rails' # why not npm? +gem 'aasm' +gem 'activeadmin', git: 'https://github.com/activeadmin/activeadmin' +gem 'bcrypt', '~> 3.1.7' +gem 'braintree', '~> 2.54.0' +gem 'browserify-rails', '~> 2.2.0' gem 'codemirror-rails' gem 'countries' -gem 'geocoder' -gem 'phony' -gem 'browserify-rails', '~> 2.2.0' +gem 'country_select' +gem 'devise' gem 'font-awesome-sass' -gem 'money' +gem 'geocoder' +gem 'gocardless_pro' gem 'google_currency' -gem 'rack-cors', require: 'rack/cors' +gem 'hiredis' gem 'httparty' -gem 'jbuilder', '~> 2.0' -gem 'braintree', '~> 2.54.0' -gem 'gocardless_pro' -gem 'aasm' gem 'i18n-js', '>= 3.0.0.rc12' -gem 'rails-i18n', '~> 4.0.0' -gem 'bcrypt', '~> 3.1.7' -gem 'slim-rails', '~> 3.1.1' +gem 'jbuilder', '~> 2.0' +gem 'jquery-rails' +gem 'kaminari' gem 'liquid' -gem 'remotipart', '~> 1.2' # [Q] Are we using this? -gem 'devise' +gem 'money' gem 'omniauth-google-oauth2' -gem 'activeadmin', git: 'https://github.com/activeadmin/activeadmin' -gem 'country_select' -gem 'kaminari' +gem 'pg' +gem 'phony' +gem 'rack-cors', require: 'rack/cors' +gem 'rails', '4.2.8' +gem 'rails-i18n', '~> 4.0.0' +gem 'rails-observers' +gem 'rake' +gem 'readthis' +gem 'redis', '>= 3.2.0', require: ['redis', 'redis/connection/hiredis'] +gem 'remotipart', '~> 1.2' # [Q] Are we using this? +gem 'selectize-rails' # why not npm? +gem 'slim-rails', '~> 3.1.1' # Use Paper Trail for containing a full history of our edits. +gem 'action_parameter' +gem 'aws-sdk', '~> 2' +gem 'paperclip', '~> 5.0.0' gem 'paper_trail' gem 'rmagick' # rmagick for image processing -gem 'paperclip', '~> 5.0.0' -gem 'aws-sdk', '~> 2' -gem 'action_parameter' # AWS SDK for Rails - makes SES integration easy +gem 'actionkit_connector', git: 'https://github.com/SumOfUs/actionkit_connector', branch: 'master' +gem 'airbrake', '~> 5.7.1' gem 'aws-sdk-rails' +gem 'bootstrap-sass', '~> 3.3.5' +gem 'browser', '~> 2.0', '>= 2.0.3' +gem 'coffee-rails', '~> 4.1.0' +gem 'compass-rails', '~> 3.0.2' # was using git master branch before +gem 'config' +gem 'envyable', require: 'envyable/rails-now' +gem 'friendly_id' +gem 'jwt' gem 'logger' gem 'lograge' -gem 'summernote-rails' -gem 'browser', '~> 2.0', '>= 2.0.3' -gem 'share_progress', git: 'https://github.com/SumOfUs/share_progress', branch: 'master', require: false +gem 'metamagic' gem 'newrelic_rpm' gem 'puma', '~> 2.15.3' -gem 'friendly_id' -gem 'config' -gem 'twilio-ruby' -gem 'metamagic' -gem 'jwt' -gem 'actionkit_connector', git: 'https://github.com/SumOfUs/actionkit_connector', branch: 'master' -gem 'airbrake', '~> 5.7.1' -gem 'envyable', require: 'envyable/rails-now' -gem 'webpack-rails' -gem 'bootstrap-sass', '~> 3.3.5' -gem 'sprockets-rails' -gem 'compass-rails', '~> 3.0.2' # was using git master branch before gem 'sass-rails', '~> 5.0.6' +gem 'share_progress', git: 'https://github.com/SumOfUs/share_progress', branch: 'master', require: false +gem 'sprockets-rails' +gem 'summernote-rails' +gem 'twilio-ruby' gem 'uglifier', '>= 1.3.0' -gem 'coffee-rails', '~> 4.1.0' +gem 'webpack-rails' group :development, :test do - gem 'rubocop', require: false - gem 'spring' - gem 'rspec-rails' gem 'capybara' # Capybara for integration testing gem 'database_cleaner' gem 'factory_girl_rails' gem 'faker' - gem 'vcr' gem 'magic_lamp' + gem 'rspec-rails' + gem 'rubocop', require: false + gem 'spring' gem 'spring-commands-rspec' + gem 'vcr' end group :doc do @@ -87,19 +87,19 @@ group :doc do end group :development do - gem 'guard-rspec', require: false - gem 'byebug' - gem 'web-console', '~> 2.0' gem 'annotate' + gem 'byebug' gem 'foreman', require: false + gem 'guard-rspec', require: false gem 'terminal-notifier-guard' # [OSX] brew install terminal-notifier + gem 'web-console', '~> 2.0' end group :test do - gem 'webmock' - gem 'timecop' gem 'coveralls', require: false gem 'poltergeist' + gem 'timecop' + gem 'webmock' end # Rails Assets - reference any Bower components that you need as gems. diff --git a/app/controllers/plugins/forms_controller.rb b/app/controllers/plugins/forms_controller.rb index d72c406b25..1c333d83c9 100644 --- a/app/controllers/plugins/forms_controller.rb +++ b/app/controllers/plugins/forms_controller.rb @@ -15,7 +15,7 @@ def create def show plugin = Plugins.find_for permitted_params[:plugin_type], permitted_params[:plugin_id] - partial_dir = (plugin.name == 'Survey') ? 'surveys' : 'shared' + partial_dir = plugin.name == 'Survey' ? 'surveys' : 'shared' render partial: "plugins/#{partial_dir}/preview", locals: { plugin: plugin } end diff --git a/app/helpers/layout_select_helper.rb b/app/helpers/layout_select_helper.rb index fef7428ff3..b96d270008 100644 --- a/app/helpers/layout_select_helper.rb +++ b/app/helpers/layout_select_helper.rb @@ -9,7 +9,7 @@ def construct_layout_select_class(liquid_layout, page, field) end def specify_layout_types(field) - (field == :liquid_layout_id) ? 'primary' : 'follow-up' + field == :liquid_layout_id ? 'primary' : 'follow-up' end private diff --git a/app/liquid/champaign_liquid_filters.rb b/app/liquid/champaign_liquid_filters.rb index 90b5da1aaf..482161b6c1 100644 --- a/app/liquid/champaign_liquid_filters.rb +++ b/app/liquid/champaign_liquid_filters.rb @@ -2,7 +2,7 @@ module ChampaignLiquidFilters def select_option(tags_string, to_select) # if one is already selected then leave it - return tags_string if tags_string =~ /selected/ + return tags_string if tags_string.match?(/selected/) tags_string.gsub(/(/, '\1 selected \2>') end diff --git a/app/liquid/liquid_helper.rb b/app/liquid/liquid_helper.rb index 34f40958cf..e03374843b 100644 --- a/app/liquid/liquid_helper.rb +++ b/app/liquid/liquid_helper.rb @@ -15,7 +15,7 @@ def country_option_tags(user_country_code = nil) options = [] names_with_codes = ISO3166::Country.all_names_with_codes(I18n.locale.to_s) names_with_codes.each do |name, code| - selected = (user_country_code == code) ? "selected='selected'" : '' + selected = user_country_code == code ? "selected='selected'" : '' options << "" end options.join("\n") diff --git a/app/models/form.rb b/app/models/form.rb index 0f11317a73..df971244b2 100644 --- a/app/models/form.rb +++ b/app/models/form.rb @@ -34,7 +34,7 @@ class Form < ActiveRecord::Base after_touch do formable.try(:page) do |page| - page.touch if page + page&.touch end end diff --git a/app/models/link.rb b/app/models/link.rb index 6599c55a2b..69b7386797 100644 --- a/app/models/link.rb +++ b/app/models/link.rb @@ -26,7 +26,7 @@ class Link < ActiveRecord::Base private def url_has_protocol - unless %r{^(https?:)?\/\/}i =~ url + unless %r{^(https?:)?\/\/}i.match?(url) errors.add(:url, 'must have a protocol (like http://)') end end diff --git a/app/models/page.rb b/app/models/page.rb index 875ba92f63..108457daca 100644 --- a/app/models/page.rb +++ b/app/models/page.rb @@ -53,7 +53,7 @@ class Page < ActiveRecord::Base has_many :images, dependent: :destroy has_many :links, dependent: :destroy - scope :language, -> (code) { code ? joins(:language).where(languages: { code: code }) : all } + scope :language, ->(code) { code ? joins(:language).where(languages: { code: code }) : all } scope :featured, -> { where(featured: true) } validates :title, presence: true @@ -139,7 +139,7 @@ def language_code def switch_plugins fields = %w(liquid_layout_id follow_up_liquid_layout_id follow_up_plan) if fields.any? { |f| changed.include?(f) } - secondary = (follow_up_plan == 'with_liquid') ? follow_up_liquid_layout : nil + secondary = follow_up_plan == 'with_liquid' ? follow_up_liquid_layout : nil PagePluginSwitcher.new(self).switch(liquid_layout, secondary) end end diff --git a/app/models/payment/braintree.rb b/app/models/payment/braintree.rb index b6e04d6f84..b7f3346aec 100644 --- a/app/models/payment/braintree.rb +++ b/app/models/payment/braintree.rb @@ -55,7 +55,7 @@ def build @customer = Payment::Braintree::Customer.create(customer_attrs) end - payment_method = Payment::Braintree::PaymentMethod.find_or_create_by!(token: @bt_payment_method.token) do |pm| + payment_method = Payment::Braintree::PaymentMethod.find_or_create_by!(token: @bt_payment_method.token) do |pm| pm.customer = @customer pm.store_in_vault = @store_in_vault end @@ -159,15 +159,15 @@ def create_customer end def create_payment_method - if payment_method_token.nil? || @bt_result.transaction.nil? - @local_payment_method_id = nil - else - @local_payment_method_id = BraintreeServices::PaymentMethodBuilder.new( - transaction: @bt_result.transaction, - customer: @customer, - store_in_vault: @store_in_vault - ).create.id - end + @local_payment_method_id = if payment_method_token.nil? || @bt_result.transaction.nil? + nil + else + BraintreeServices::PaymentMethodBuilder.new( + transaction: @bt_result.transaction, + customer: @customer, + store_in_vault: @store_in_vault + ).create.id + end end def create_transaction diff --git a/app/models/plugins/has_form.rb b/app/models/plugins/has_form.rb index df678a3e6e..c3c93acd7a 100644 --- a/app/models/plugins/has_form.rb +++ b/app/models/plugins/has_form.rb @@ -33,7 +33,7 @@ def dup clone = super clone.save! - clone.form.form_elements = form.form_elements.map(&:dup) if clone.form + clone.form&.form_elements = form.form_elements.map(&:dup) clone end diff --git a/app/models/share/email.rb b/app/models/share/email.rb index 594e109a5b..17345c2a17 100644 --- a/app/models/share/email.rb +++ b/app/models/share/email.rb @@ -20,6 +20,6 @@ class Share::Email < ActiveRecord::Base validate :has_link def has_link - errors.add(:body, 'does not contain {LINK}') unless body =~ /\{LINK\}/ + errors.add(:body, 'does not contain {LINK}') unless body.match?(/\{LINK\}/) end end diff --git a/app/models/share/twitter.rb b/app/models/share/twitter.rb index 99e9bbaab7..0ad8d34622 100644 --- a/app/models/share/twitter.rb +++ b/app/models/share/twitter.rb @@ -20,6 +20,6 @@ class Share::Twitter < ActiveRecord::Base validate :has_link def has_link - errors.add(:description, 'does not contain {LINK}') unless description =~ /\{LINK\}/ + errors.add(:description, 'does not contain {LINK}') unless description.match?(/\{LINK\}/) end end diff --git a/app/services/page_updater.rb b/app/services/page_updater.rb index d797a75b28..c7dc9f3696 100644 --- a/app/services/page_updater.rb +++ b/app/services/page_updater.rb @@ -116,21 +116,21 @@ def update_plugin(plugin_params) end def update_share(share_params, _name) - if share_params[:id].present? - variant = ShareProgressVariantBuilder.update( - params: without_name(share_params), - variant_type: share_params[:name], - page: @page, - id: share_params[:id] - ) - else - variant = ShareProgressVariantBuilder.create( - params: without_name(share_params), - variant_type: share_params[:name], - page: @page, - url: @page_url - ) - end + variant = if share_params[:id].present? + ShareProgressVariantBuilder.update( + params: without_name(share_params), + variant_type: share_params[:name], + page: @page, + id: share_params[:id] + ) + else + ShareProgressVariantBuilder.create( + params: without_name(share_params), + variant_type: share_params[:name], + page: @page, + url: @page_url + ) + end variant.errors end diff --git a/app/services/search/page_searcher.rb b/app/services/search/page_searcher.rb index 4e5549a2d9..d52ded07cd 100644 --- a/app/services/search/page_searcher.rb +++ b/app/services/search/page_searcher.rb @@ -37,7 +37,7 @@ def search def validate_query(query) # if query is an empty array, nil or an empty string, skip filtering for that query - ([[], nil, ''].include? query) ? false : true + [[], nil, ''].include? query ? false : true end def combine_collections(collection1, collection2) diff --git a/app/services/share_progress_variant_builder.rb b/app/services/share_progress_variant_builder.rb index 8a539614a4..0fb1f75a17 100644 --- a/app/services/share_progress_variant_builder.rb +++ b/app/services/share_progress_variant_builder.rb @@ -49,7 +49,7 @@ def create if sp_button.save button.update(sp_id: sp_button.id, sp_button_html: sp_button.share_button_html, url: sp_button.page_url) - variant.update(sp_id: sp_button.variants[@variant_type].last[:id]) + variant.update(sp_id: sp_button.variants[@variant_type].last[:id]) else add_sp_errors_to_variant(sp_button, variant) end diff --git a/config/initializers/airbrake.rb b/config/initializers/airbrake.rb index 489c033a40..a9ffffff61 100644 --- a/config/initializers/airbrake.rb +++ b/config/initializers/airbrake.rb @@ -8,53 +8,55 @@ # # Configuration details: # https://github.com/airbrake/airbrake-ruby#configuration -Airbrake.configure do |c| - # You must set both project_id & project_key. To find your project_id and - # project_key navigate to your project's General Settings and copy the values - # from the right sidebar. - # https://github.com/airbrake/airbrake-ruby#project_id--project_key - - c.project_id = Settings.airbrake_project_id - c.project_key = Settings.airbrake_api_key - - # Configures the root directory of your project. Expects a String or a - # Pathname, which represents the path to your project. Providing this option - # helps us to filter out repetitive data from backtrace frames and link to - # GitHub files from our dashboard. - # https://github.com/airbrake/airbrake-ruby#root_directory - c.root_directory = Rails.root - - # By default, Airbrake Ruby outputs to STDOUT. In Rails apps it makes sense to - # use the Rails' logger. - # https://github.com/airbrake/airbrake-ruby#logger - c.logger = Rails.logger - - # Configures the environment the application is running in. Helps the Airbrake - # dashboard to distinguish between exceptions occurring in different - # environments. By default, it's not set. - # NOTE: This option must be set in order to make the 'ignore_environments' - # option work. - # https://github.com/airbrake/airbrake-ruby#environment - c.environment = Rails.env - - # Setting this option allows Airbrake to filter exceptions occurring in - # unwanted environments such as :test. By default, it is equal to an empty - # Array, which means Airbrake Ruby sends exceptions occurring in all - # environments. - # NOTE: This option *does not* work if you don't set the 'environment' option. - # https://github.com/airbrake/airbrake-ruby#ignore_environments - c.ignore_environments = %w(test) - - # A list of parameters that should be filtered out of what is sent to - # Airbrake. By default, all "password" attributes will have their contents - # replaced. - # https://github.com/airbrake/airbrake-ruby#blacklist_keys - c.blacklist_keys = [/password/i] - - # Alternatively, you can integrate with Rails' filter_parameters. - # Read more: https://goo.gl/gqQ1xS - # c.blacklist_keys = Rails.application.config.filter_parameters -end if Settings.airbrake_project_id.present? +if Settings.airbrake_project_id.present? + Airbrake.configure do |c| + # You must set both project_id & project_key. To find your project_id and + # project_key navigate to your project's General Settings and copy the values + # from the right sidebar. + # https://github.com/airbrake/airbrake-ruby#project_id--project_key + + c.project_id = Settings.airbrake_project_id + c.project_key = Settings.airbrake_api_key + + # Configures the root directory of your project. Expects a String or a + # Pathname, which represents the path to your project. Providing this option + # helps us to filter out repetitive data from backtrace frames and link to + # GitHub files from our dashboard. + # https://github.com/airbrake/airbrake-ruby#root_directory + c.root_directory = Rails.root + + # By default, Airbrake Ruby outputs to STDOUT. In Rails apps it makes sense to + # use the Rails' logger. + # https://github.com/airbrake/airbrake-ruby#logger + c.logger = Rails.logger + + # Configures the environment the application is running in. Helps the Airbrake + # dashboard to distinguish between exceptions occurring in different + # environments. By default, it's not set. + # NOTE: This option must be set in order to make the 'ignore_environments' + # option work. + # https://github.com/airbrake/airbrake-ruby#environment + c.environment = Rails.env + + # Setting this option allows Airbrake to filter exceptions occurring in + # unwanted environments such as :test. By default, it is equal to an empty + # Array, which means Airbrake Ruby sends exceptions occurring in all + # environments. + # NOTE: This option *does not* work if you don't set the 'environment' option. + # https://github.com/airbrake/airbrake-ruby#ignore_environments + c.ignore_environments = %w(test) + + # A list of parameters that should be filtered out of what is sent to + # Airbrake. By default, all "password" attributes will have their contents + # replaced. + # https://github.com/airbrake/airbrake-ruby#blacklist_keys + c.blacklist_keys = [/password/i] + + # Alternatively, you can integrate with Rails' filter_parameters. + # Read more: https://goo.gl/gqQ1xS + # c.blacklist_keys = Rails.application.config.filter_parameters + end +end # If Airbrake doesn't send any expected exceptions, we suggest to uncomment the # line below. It might simplify debugging of background Airbrake workers, which diff --git a/db/migrate/20150827085930_add_master_and_position_to_form_elements.rb b/db/migrate/20150827085930_add_master_and_position_to_form_elements.rb index 3e3fc798a7..450cd715b4 100644 --- a/db/migrate/20150827085930_add_master_and_position_to_form_elements.rb +++ b/db/migrate/20150827085930_add_master_and_position_to_form_elements.rb @@ -2,6 +2,6 @@ class AddMasterAndPositionToFormElements < ActiveRecord::Migration def change add_column :forms, :master, :boolean, default: false - add_column :form_elements, :position, :integer, null: false, default: 0 + add_column :form_elements, :position, :integer, null: false, default: 0 end end diff --git a/lib/liquid_markup_seeder.rb b/lib/liquid_markup_seeder.rb index c4c2ca8987..2bc14fbfc9 100644 --- a/lib/liquid_markup_seeder.rb +++ b/lib/liquid_markup_seeder.rb @@ -61,7 +61,7 @@ def parse_name(file) end def klass(file) - file =~ /\_\w+\.liquid$/ ? 'LiquidPartial' : 'LiquidLayout' + file.match?(/\_\w+\.liquid$/) ? 'LiquidPartial' : 'LiquidLayout' end def set_metadata_fields(view) diff --git a/lib/payment_processor/braintree/error_processing.rb b/lib/payment_processor/braintree/error_processing.rb index a452b2ee7a..62baa74778 100644 --- a/lib/payment_processor/braintree/error_processing.rb +++ b/lib/payment_processor/braintree/error_processing.rb @@ -32,7 +32,7 @@ class ErrorProcessing .flatten .freeze - FILTER = -> (error) { USER_ERROR_CODES.include?(error.code.to_i) } + FILTER = ->(error) { USER_ERROR_CODES.include?(error.code.to_i) } # locale is unused, added to match API for GoCardless def initialize(response, locale: nil) diff --git a/lib/payment_processor/braintree/subscription.rb b/lib/payment_processor/braintree/subscription.rb index d0e6b91615..b2ef5eb9eb 100644 --- a/lib/payment_processor/braintree/subscription.rb +++ b/lib/payment_processor/braintree/subscription.rb @@ -63,9 +63,9 @@ def create_or_retrieve_payment_method_on_braintree(customer_result) if existing_customer.present? payment_method_result = ::Braintree::PaymentMethod.create(payment_method_options) break_if_rejected(payment_method_result) - return payment_method_result.payment_method + payment_method_result.payment_method else - return customer_result.customer.payment_methods.first + customer_result.customer.payment_methods.first end end diff --git a/lib/payment_processor/go_cardless/populator.rb b/lib/payment_processor/go_cardless/populator.rb index 441e3f5d6d..51faff6198 100644 --- a/lib/payment_processor/go_cardless/populator.rb +++ b/lib/payment_processor/go_cardless/populator.rb @@ -70,7 +70,7 @@ def bacs? def complete_redirect_flow @complete_redirect_flow ||= client.redirect_flows.complete(@redirect_flow_id, params: { session_token: @session_token }) rescue GoCardlessPro::InvalidStateError => e - raise e unless e.message =~ /already completed/ + raise e unless e.message.match?(/already completed/) @complete_redirect_flow = client.redirect_flows.get(@redirect_flow_id) end diff --git a/spec/models/link_spec.rb b/spec/models/link_spec.rb index f1d0ebf4e6..90c12f556b 100644 --- a/spec/models/link_spec.rb +++ b/spec/models/link_spec.rb @@ -112,7 +112,7 @@ old_time = Time.now.utc Timecop.travel(1.hour) do - expect { link.update(source: 'BBC') }.to change{ + expect { link.update(source: 'BBC') }.to change { page.reload.updated_at.to_s }.from(old_time.to_s).to((old_time + 1.hour).to_s) end diff --git a/spec/requests/api/go_cardless/go_cardless_spec.rb b/spec/requests/api/go_cardless/go_cardless_spec.rb index dd4de7986d..6cf5e405e0 100644 --- a/spec/requests/api/go_cardless/go_cardless_spec.rb +++ b/spec/requests/api/go_cardless/go_cardless_spec.rb @@ -59,7 +59,7 @@ URI.parse(assigns(:flow).redirect_flow_instance.success_redirect_url).query ) request.params.each_pair do |key, val| - next if key =~ /controller|action/ + next if key.match?(/controller|action/) expect(success_redirect_params[key]).to eq val end end diff --git a/spec/services/share_progress_variant_builder_spec.rb b/spec/services/share_progress_variant_builder_spec.rb index aaf4d66945..4d8d584a7a 100644 --- a/spec/services/share_progress_variant_builder_spec.rb +++ b/spec/services/share_progress_variant_builder_spec.rb @@ -15,7 +15,7 @@ id: '1', share_button_html: '
', page_url: 'http://example.com/foo', - variants: { facebook: sp_variants }) + variants: { facebook: sp_variants }) end let(:failure_sp_button) do