From 1be01f8dd4dd8f877840d863a6feb242aa6d8fda Mon Sep 17 00:00:00 2001 From: Sam Saffron Date: Tue, 30 Apr 2019 16:58:18 +1000 Subject: [PATCH] DEV: Add support for Rails 6 Minor fixes to add Rails 6 support to Discourse, we now will boot with RAILS_MASTER=1, all specs pass Only one tiny deprecation left Largest change was the way ActiveModel:Errors changed interface a bit but there is a simple backwards compat way of working it --- app/controllers/extra_locales_controller.rb | 6 +++++- app/controllers/uploads_controller.rb | 2 +- app/mailers/user_notifications.rb | 5 +++-- app/models/group.rb | 2 +- app/models/user.rb | 2 +- app/views/layouts/_head.html.erb | 2 +- app/views/metadata/opensearch.xml.erb | 2 +- app/views/users/password_reset.html.erb | 2 +- lib/discourse_tagging.rb | 8 ++++---- lib/email/receiver.rb | 4 +++- .../active_record_attribute_methods.rb | 10 ++++++++++ lib/freedom_patches/rails6.rb | 9 +++++++++ lib/has_errors.rb | 2 +- lib/new_post_manager.rb | 8 ++++---- lib/new_post_result.rb | 2 +- lib/post_creator.rb | 13 +++++++------ lib/post_revisor.rb | 2 +- lib/topic_creator.rb | 2 +- lib/validators/post_validator.rb | 2 +- lib/validators/upload_url_validator.rb | 2 +- lib/validators/url_validator.rb | 2 +- spec/components/concern/has_custom_fields_spec.rb | 8 ++++---- spec/components/concern/has_search_data_spec.rb | 8 ++++---- spec/components/concern/positionable_spec.rb | 6 +++--- spec/components/concern/searchable_spec.rb | 8 ++++---- spec/components/validators/post_validator_spec.rb | 2 +- spec/models/category_spec.rb | 2 +- spec/models/tag_user_spec.rb | 2 +- spec/models/topic_timer_spec.rb | 2 +- spec/requests/uploads_controller_spec.rb | 8 +++++--- spec/serializers/current_user_serializer_spec.rb | 2 +- 31 files changed, 83 insertions(+), 54 deletions(-) create mode 100644 lib/freedom_patches/rails6.rb diff --git a/app/controllers/extra_locales_controller.rb b/app/controllers/extra_locales_controller.rb index 72e1cd38d5f..dfcc64719a2 100644 --- a/app/controllers/extra_locales_controller.rb +++ b/app/controllers/extra_locales_controller.rb @@ -3,7 +3,11 @@ class ExtraLocalesController < ApplicationController layout :false - skip_before_action :check_xhr, :preload_json, :redirect_to_login_if_required + + skip_before_action :check_xhr, + :preload_json, + :redirect_to_login_if_required, + :verify_authenticity_token def show bundle = params[:bundle] diff --git a/app/controllers/uploads_controller.rb b/app/controllers/uploads_controller.rb index a3af31cb8a9..1e8ca6be397 100644 --- a/app/controllers/uploads_controller.rb +++ b/app/controllers/uploads_controller.rb @@ -152,7 +152,7 @@ class UploadsController < ApplicationController upload.update_columns(retain_hours: retain_hours) if retain_hours > 0 end - upload.errors.empty? ? upload : { errors: upload.errors.values.flatten } + upload.errors.empty? ? upload : { errors: upload.errors.to_hash.values.flatten } ensure tempfile&.close! end diff --git a/app/mailers/user_notifications.rb b/app/mailers/user_notifications.rb index 523ab0c7fc0..53392ccd757 100644 --- a/app/mailers/user_notifications.rb +++ b/app/mailers/user_notifications.rb @@ -584,7 +584,7 @@ class UserNotifications < ActionMailer::Base ) unless translation_override_exists - html = UserNotificationRenderer.new(Rails.configuration.paths["app/views"]).render( + html = UserNotificationRenderer.with_view_paths(Rails.configuration.paths["app/views"]).render( template: 'email/invite', format: :html, locals: { message: PrettyText.cook(message, sanitize: false).html_safe, @@ -611,7 +611,8 @@ class UserNotifications < ActionMailer::Base end unless translation_override_exists - html = UserNotificationRenderer.new(Rails.configuration.paths["app/views"]).render( + + html = UserNotificationRenderer.with_view_paths(Rails.configuration.paths["app/views"]).render( template: 'email/notification', format: :html, locals: { context_posts: context_posts, diff --git a/app/models/group.rb b/app/models/group.rb index 82ceee125ed..bb0adf78e43 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -99,7 +99,7 @@ class Group < ActiveRecord::Base validates :messageable_level, inclusion: { in: ALIAS_LEVELS.values } scope :visible_groups, Proc.new { |user, order, opts| - groups = Group.order(order || "name ASC") + groups = self.order(order || "name ASC") if !opts || !opts[:include_everyone] groups = groups.where("groups.id > 0") diff --git a/app/models/user.rb b/app/models/user.rb index 1c6d9adeb6e..7245e809969 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -988,7 +988,7 @@ class User < ActiveRecord::Base end def secure_category_ids - cats = self.admin? ? Category.where(read_restricted: true) : secure_categories.references(:categories) + cats = self.admin? ? Category.unscoped.where(read_restricted: true) : secure_categories.references(:categories) cats.pluck('categories.id').sort end diff --git a/app/views/layouts/_head.html.erb b/app/views/layouts/_head.html.erb index 12334ba5eaf..02bbb01f3c8 100644 --- a/app/views/layouts/_head.html.erb +++ b/app/views/layouts/_head.html.erb @@ -5,7 +5,7 @@ <%- end %> <% site_apple_touch_icon_url = SiteSetting.site_apple_touch_icon_url %> <%- if site_apple_touch_icon_url.present? %> - + <%- end %> <% if mobile_view? %> diff --git a/app/views/metadata/opensearch.xml.erb b/app/views/metadata/opensearch.xml.erb index 5495c3ffc9d..1ce0ae45c7e 100644 --- a/app/views/metadata/opensearch.xml.erb +++ b/app/views/metadata/opensearch.xml.erb @@ -4,7 +4,7 @@ Search for posts on <%= SiteSetting.title %> discourse forum <% site_favicon_url = SiteSetting.site_favicon_url %> - <% absolute_site_favicon_url = UrlHelper.absolute(site_favicon_url) %> + <% absolute_site_favicon_url = ::UrlHelper.absolute(site_favicon_url) %> <% if site_favicon_url =~ /\.ico$/ -%> <%= absolute_site_favicon_url %> <%- else -%> diff --git a/app/views/users/password_reset.html.erb b/app/views/users/password_reset.html.erb index 3a3c4338bf2..8a982ae95e2 100644 --- a/app/views/users/password_reset.html.erb +++ b/app/views/users/password_reset.html.erb @@ -4,7 +4,7 @@ <%= @error %> <%end%> - <% if @user.present? and @user.errors.any? %> + <% if @user.present? and @user.errors.present? %>
<% @user.errors.full_messages.each do |msg| %>
  • <%= msg %>
  • diff --git a/lib/discourse_tagging.rb b/lib/discourse_tagging.rb index 4ddc8875c9b..0ef5fba265d 100644 --- a/lib/discourse_tagging.rb +++ b/lib/discourse_tagging.rb @@ -27,13 +27,13 @@ module DiscourseTagging staff_tags = new_tag_names & all_staff_tags staff_tags += new_tag_names & hidden_tags if staff_tags.present? - topic.errors[:base] << I18n.t("tags.staff_tag_disallowed", tag: staff_tags.join(" ")) + topic.errors.add(:base, I18n.t("tags.staff_tag_disallowed", tag: staff_tags.join(" "))) return false end staff_tags = removed_tag_names & all_staff_tags if staff_tags.present? - topic.errors[:base] << I18n.t("tags.staff_tag_remove_disallowed", tag: staff_tags.join(" ")) + topic.errors.add(:base, I18n.t("tags.staff_tag_remove_disallowed", tag: staff_tags.join(" "))) return false end @@ -77,7 +77,7 @@ module DiscourseTagging # validate minimum required tags for a category if !guardian.is_staff? && category && category.minimum_required_tags > 0 && tags.length < category.minimum_required_tags - topic.errors[:base] << I18n.t("tags.minimum_required_tags", count: category.minimum_required_tags) + topic.errors.add(:base, I18n.t("tags.minimum_required_tags", count: category.minimum_required_tags)) return false end @@ -85,7 +85,7 @@ module DiscourseTagging else # validate minimum required tags for a category if !guardian.is_staff? && category && category.minimum_required_tags > 0 - topic.errors[:base] << I18n.t("tags.minimum_required_tags", count: category.minimum_required_tags) + topic.errors.add(:base, I18n.t("tags.minimum_required_tags", count: category.minimum_required_tags)) return false end diff --git a/lib/email/receiver.rb b/lib/email/receiver.rb index 669f70dc834..68a5fa817c6 100644 --- a/lib/email/receiver.rb +++ b/lib/email/receiver.rb @@ -1112,7 +1112,9 @@ module Email raise TooShortPost end - raise InvalidPost, errors.join("\n") if result.errors.any? + if result.errors.present? + raise InvalidPost, errors.join("\n") + end if result.post @incoming_email.update_columns(topic_id: result.post.topic_id, post_id: result.post.id) diff --git a/lib/freedom_patches/active_record_attribute_methods.rb b/lib/freedom_patches/active_record_attribute_methods.rb index 71fd5d44c7b..22710613154 100644 --- a/lib/freedom_patches/active_record_attribute_methods.rb +++ b/lib/freedom_patches/active_record_attribute_methods.rb @@ -10,9 +10,19 @@ module ActiveRecord module AttributeMethods module ClassMethods + # this is for Rails 5 def enforce_raw_sql_whitelist(*args) return end + + BLANK_ARRAY = [].freeze + + # this patch just allows everyting in Rails 6 + def disallow_raw_sql!(args, permit: nil) + # we may consider moving to https://github.com/rails/rails/pull/33330 + # once all frozen string hints are in place + return BLANK_ARRAY + end end end end diff --git a/lib/freedom_patches/rails6.rb b/lib/freedom_patches/rails6.rb new file mode 100644 index 00000000000..b9aace631b4 --- /dev/null +++ b/lib/freedom_patches/rails6.rb @@ -0,0 +1,9 @@ +# this is a quick backport of a new method introduced in Rails 6 +# to be removed after we upgrade to Rails 6 +if ! defined? ActionView::Base.with_view_paths + class ActionView::Base + class << self + alias with_view_paths new + end + end +end diff --git a/lib/has_errors.rb b/lib/has_errors.rb index a68c752ce13..e7379c31628 100644 --- a/lib/has_errors.rb +++ b/lib/has_errors.rb @@ -25,7 +25,7 @@ module HasErrors end def add_error(msg) - errors[:base] << msg unless errors[:base].include?(msg) + errors.add(:base, msg) unless errors[:base].include?(msg) end def add_errors_from(obj) diff --git a/lib/new_post_manager.rb b/lib/new_post_manager.rb index 714a3fe6bad..2beacba7206 100644 --- a/lib/new_post_manager.rb +++ b/lib/new_post_manager.rb @@ -124,14 +124,14 @@ class NewPostManager if post.errors[:raw].present? result = NewPostResult.new(:created_post, false) - result.errors[:base] << post.errors[:raw] + result.errors.add(:base, post.errors[:raw]) return result elsif manager.args[:topic_id] topic = Topic.unscoped.where(id: manager.args[:topic_id]).first unless manager.user.guardian.can_create_post_on_topic?(topic) result = NewPostResult.new(:created_post, false) - result.errors[:base] << I18n.t(:topic_not_found) + result.errors.add(:base, I18n.t(:topic_not_found)) return result end elsif manager.args[:category] @@ -139,7 +139,7 @@ class NewPostManager unless manager.user.guardian.can_create_topic_on_category?(category) result = NewPostResult.new(:created_post, false) - result.errors[:base] << I18n.t("js.errors.reasons.forbidden") + result.errors.add(:base, I18n.t("js.errors.reasons.forbidden")) return result end end @@ -172,7 +172,7 @@ class NewPostManager def perform if !self.class.exempt_user?(@user) && matches = WordWatcher.new("#{@args[:title]} #{@args[:raw]}").should_block? result = NewPostResult.new(:created_post, false) - result.errors[:base] << I18n.t('contains_blocked_words', word: matches[0]) + result.errors.add(:base, I18n.t('contains_blocked_words', word: matches[0])) return result end diff --git a/lib/new_post_result.rb b/lib/new_post_result.rb index f4971545fa0..3b82b90b71e 100644 --- a/lib/new_post_result.rb +++ b/lib/new_post_result.rb @@ -27,7 +27,7 @@ class NewPostResult if arr.empty? @success = true else - arr.each { |e| errors[:base] << e unless errors[:base].include?(e) } + arr.each { |e| errors.add(:base, e) unless errors[:base].include?(e) } end end diff --git a/lib/post_creator.rb b/lib/post_creator.rb index 0749312e8ad..91e7c79f488 100644 --- a/lib/post_creator.rb +++ b/lib/post_creator.rb @@ -91,7 +91,7 @@ class PostCreator @post = nil if @user.suspended? && !skip_validations? - errors[:base] << I18n.t(:user_is_suspended) + errors.add(:base, I18n.t(:user_is_suspended)) return false end @@ -102,8 +102,9 @@ class PostCreator max_allowed_message_recipients = SiteSetting.max_allowed_message_recipients if names.length > max_allowed_message_recipients - errors[:base] << I18n.t(:max_pm_recepients, - recipients_limit: max_allowed_message_recipients + errors.add( + :base, + I18n.t(:max_pm_recepients, recipients_limit: max_allowed_message_recipients) ) return false @@ -124,7 +125,7 @@ class PostCreator ", user_ids: users.keys) .pluck(:id).each do |m| - errors[:base] << I18n.t(:not_accepting_pms, username: users[m]) + errors.add(:base, I18n.t(:not_accepting_pms, username: users[m])) end return false if errors[:base].present? @@ -136,7 +137,7 @@ class PostCreator else @topic = Topic.find_by(id: @opts[:topic_id]) unless @topic.present? && (@opts[:skip_guardian] || guardian.can_create?(Post, @topic)) - errors[:base] << I18n.t(:topic_not_found) + errors.add(:base, I18n.t(:topic_not_found)) return false end end @@ -147,7 +148,7 @@ class PostCreator if @post.has_host_spam? @spam = true - errors[:base] << I18n.t(:spamming_host) + errors.add(:base, I18n.t(:spamming_host)) return false end diff --git a/lib/post_revisor.rb b/lib/post_revisor.rb index a9041589771..acba0366f6a 100644 --- a/lib/post_revisor.rb +++ b/lib/post_revisor.rb @@ -562,7 +562,7 @@ class PostRevisor category.update_column(:description, new_description) @category_changed = category else - @post.errors[:base] << I18n.t("category.errors.description_incomplete") + @post.errors.add(:base, I18n.t("category.errors.description_incomplete")) end end diff --git a/lib/topic_creator.rb b/lib/topic_creator.rb index 65a439e4731..e5e731ffa0a 100644 --- a/lib/topic_creator.rb +++ b/lib/topic_creator.rb @@ -160,7 +160,7 @@ class TopicCreator # Validate minimum required tags for a category category = find_category if category.present? && category.minimum_required_tags > 0 - topic.errors[:base] << I18n.t("tags.minimum_required_tags", count: category.minimum_required_tags) + topic.errors.add(:base, I18n.t("tags.minimum_required_tags", count: category.minimum_required_tags)) rollback_from_errors!(topic) end end diff --git a/lib/validators/post_validator.rb b/lib/validators/post_validator.rb index b18abd9bd5b..df2e8b1ec90 100644 --- a/lib/validators/post_validator.rb +++ b/lib/validators/post_validator.rb @@ -59,7 +59,7 @@ class Validators::PostValidator < ActiveModel::Validator def watched_words(post) if !post.acting_user&.staff? && !post.acting_user&.staged && matches = WordWatcher.new(post.raw).should_block? - post.errors[:base] << I18n.t('contains_blocked_words', word: matches[0]) + post.errors.add(:base, I18n.t('contains_blocked_words', word: matches[0])) end end diff --git a/lib/validators/upload_url_validator.rb b/lib/validators/upload_url_validator.rb index 7823478aa77..e1f1b790b81 100644 --- a/lib/validators/upload_url_validator.rb +++ b/lib/validators/upload_url_validator.rb @@ -8,7 +8,7 @@ class UploadUrlValidator < ActiveModel::EachValidator end unless uri && Upload.exists?(url: value) - record.errors[attribute] << (options[:message] || I18n.t('errors.messages.invalid')) + record.errors.add(attribute, options[:message] || I18n.t('errors.messages.invalid')) end end end diff --git a/lib/validators/url_validator.rb b/lib/validators/url_validator.rb index fec4470cec8..eec84ea3b9f 100644 --- a/lib/validators/url_validator.rb +++ b/lib/validators/url_validator.rb @@ -15,7 +15,7 @@ class UrlValidator < ActiveModel::EachValidator end unless valid - record.errors[attribute] << (options[:message] || I18n.t('errors.messages.invalid')) + record.errors.add(attribute, options[:message] || I18n.t('errors.messages.invalid')) end end end diff --git a/spec/components/concern/has_custom_fields_spec.rb b/spec/components/concern/has_custom_fields_spec.rb index b08b75aef35..324ba16a62d 100644 --- a/spec/components/concern/has_custom_fields_spec.rb +++ b/spec/components/concern/has_custom_fields_spec.rb @@ -22,10 +22,10 @@ describe HasCustomFields do DB.exec("drop table custom_fields_test_items") DB.exec("drop table custom_fields_test_item_custom_fields") - # import is making my life hard, we need to nuke this out of orbit - des = ActiveSupport::DescendantsTracker.class_variable_get :@@direct_descendants - des[ActiveRecord::Base].delete(CustomFieldsTestItem) - des[ActiveRecord::Base].delete(CustomFieldsTestItemCustomField) + # this weakref in the descendant tracker should clean up the two tests + # if this becomes an issue we can revisit (watch out for erratic tests) + Object.send(:remove_const, :CustomFieldsTestItem) + Object.send(:remove_const, :CustomFieldsTestItemCustomField) end it "simple modification of custom fields" do diff --git a/spec/components/concern/has_search_data_spec.rb b/spec/components/concern/has_search_data_spec.rb index 4bf0e9624ee..e064ec33539 100644 --- a/spec/components/concern/has_search_data_spec.rb +++ b/spec/components/concern/has_search_data_spec.rb @@ -21,10 +21,10 @@ describe HasSearchData do DB.exec("drop table model_items") DB.exec("drop table model_item_search_data") - # import is making my life hard, we need to nuke this out of orbit - des = ActiveSupport::DescendantsTracker.class_variable_get :@@direct_descendants - des[ActiveRecord::Base].delete(ModelItem) - des[ActiveRecord::Base].delete(ModelItemSearchData) + # this weakref in the descendant tracker should clean up the two tests + # if this becomes an issue we can revisit (watch out for erratic tests) + Object.send(:remove_const, :ModelItem) + Object.send(:remove_const, :ModelItemSearchData) end let(:item) do diff --git a/spec/components/concern/positionable_spec.rb b/spec/components/concern/positionable_spec.rb index 395251d3988..dc7baa6c3bd 100644 --- a/spec/components/concern/positionable_spec.rb +++ b/spec/components/concern/positionable_spec.rb @@ -20,9 +20,9 @@ describe Positionable do after do DB.exec("drop table test_items") - # import is making my life hard, we need to nuke this out of orbit - des = ActiveSupport::DescendantsTracker.class_variable_get :@@direct_descendants - des[ActiveRecord::Base].delete(TestItem) + # this weakref in the descendant tracker should clean up the two tests + # if this becomes an issue we can revisit (watch out for erratic tests) + Object.send(:remove_const, :TestItem) end it "can position stuff correctly" do diff --git a/spec/components/concern/searchable_spec.rb b/spec/components/concern/searchable_spec.rb index 49726a68557..a4548621eae 100644 --- a/spec/components/concern/searchable_spec.rb +++ b/spec/components/concern/searchable_spec.rb @@ -22,10 +22,10 @@ describe Searchable do DB.exec("drop table searchable_records") DB.exec("drop table searchable_record_search_data") - # import is making my life hard, we need to nuke this out of orbit - des = ActiveSupport::DescendantsTracker.class_variable_get :@@direct_descendants - des[ActiveRecord::Base].delete(SearchableRecord) - des[ActiveRecord::Base].delete(SearchableRecordSearchData) + # this weakref in the descendant tracker should clean up the two tests + # if this becomes an issue we can revisit (watch out for erratic tests) + Object.send(:remove_const, :SearchableRecord) + Object.send(:remove_const, :SearchableRecordSearchData) end let(:item) { SearchableRecord.create! } diff --git a/spec/components/validators/post_validator_spec.rb b/spec/components/validators/post_validator_spec.rb index deb51c3ad6f..1426caaf27d 100644 --- a/spec/components/validators/post_validator_spec.rb +++ b/spec/components/validators/post_validator_spec.rb @@ -227,7 +227,7 @@ describe Validators::PostValidator do it "should add an error" do validator.unique_post_validator(new_post) - expect(new_post.errors.keys).to contain_exactly(:raw) + expect(new_post.errors.to_hash.keys).to contain_exactly(:raw) end it "should not add an error if post.skip_unique_check is true" do diff --git a/spec/models/category_spec.rb b/spec/models/category_spec.rb index 7aa2bd87af6..9ff217b4ded 100644 --- a/spec/models/category_spec.rb +++ b/spec/models/category_spec.rb @@ -23,7 +23,7 @@ describe Category do category.search_priority = Searchable::PRIORITIES.values.last + 1 expect(category.valid?).to eq(false) - expect(category.errors.keys).to contain_exactly(:search_priority) + expect(category.errors.to_hash.keys).to contain_exactly(:search_priority) end it 'validates uniqueness in case insensitive way' do diff --git a/spec/models/tag_user_spec.rb b/spec/models/tag_user_spec.rb index 773a0127d46..d9d26a94011 100644 --- a/spec/models/tag_user_spec.rb +++ b/spec/models/tag_user_spec.rb @@ -164,7 +164,7 @@ describe TagUser do result = DiscourseTagging.tag_topic_by_names(topic, Guardian.new(staff), ["foo"]) expect(result).to eq(true) - topic.errors[:base].clear + topic.errors.clear result = DiscourseTagging.tag_topic_by_names(topic, Guardian.new(user), []) expect(result).to eq(false) diff --git a/spec/models/topic_timer_spec.rb b/spec/models/topic_timer_spec.rb index 7145aaab069..c8433388ca7 100644 --- a/spec/models/topic_timer_spec.rb +++ b/spec/models/topic_timer_spec.rb @@ -84,7 +84,7 @@ RSpec.describe TopicTimer, type: :model do ) expect(topic_timer).to_not be_valid - expect(topic_timer.errors.keys).to include(:category_id) + expect(topic_timer.errors).to include(:category_id) end end diff --git a/spec/requests/uploads_controller_spec.rb b/spec/requests/uploads_controller_spec.rb index fb6109e62ed..d1dd951e5c0 100644 --- a/spec/requests/uploads_controller_spec.rb +++ b/spec/requests/uploads_controller_spec.rb @@ -240,7 +240,9 @@ describe UploadsController do upload = upload_file("logo.png") get "/uploads/#{site}/#{upload.sha1}.#{upload.extension}" expect(response.status).to eq(200) - expect(response.headers["Content-Disposition"]).to eq("attachment; filename=\"logo.png\"") + + # rails 6 adds UTF-8 filename to disposition + expect(response.headers["Content-Disposition"]).to include("attachment; filename=\"logo.png\"") end it "handles image without extension" do @@ -249,7 +251,7 @@ describe UploadsController do get "/uploads/#{site}/#{upload.sha1}.json" expect(response.status).to eq(200) - expect(response.headers["Content-Disposition"]).to eq("attachment; filename=\"image_no_extension.png\"") + expect(response.headers["Content-Disposition"]).to include("attachment; filename=\"image_no_extension.png\"") end it "handles file without extension" do @@ -258,7 +260,7 @@ describe UploadsController do get "/uploads/#{site}/#{upload.sha1}.json" expect(response.status).to eq(200) - expect(response.headers["Content-Disposition"]).to eq("attachment; filename=\"not_an_image\"") + expect(response.headers["Content-Disposition"]).to include("attachment; filename=\"not_an_image\"") end context "prevent anons from downloading files" do diff --git a/spec/serializers/current_user_serializer_spec.rb b/spec/serializers/current_user_serializer_spec.rb index 4a9afbc7555..32dc2412300 100644 --- a/spec/serializers/current_user_serializer_spec.rb +++ b/spec/serializers/current_user_serializer_spec.rb @@ -50,7 +50,7 @@ RSpec.describe CurrentUserSerializer do end it "should include correct id in top_category_ids array" do - category = Category.first + _category = Category.first CategoryUser.create!(user_id: user.id, category_id: category1.id, notification_level: CategoryUser.notification_levels[:tracking])