Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

AO3-5033 Rails 5.0 upgrade #2958

Merged
merged 120 commits into from Aug 7, 2017

Conversation

Projects
None yet
6 participants
Contributor

WendyBeth commented Jul 13, 2017

Pull Request Checklist

  • Have you read How to write the perfect pull request?
  • Have you read through the contributor guidelines?
  • Have you added tests for any changed functionality?
  • Have you added the JIRA issue number as the first thing in your pull request title (eg: AO3-1234 Fix thing)
  • Have you updated the JIRA issue with the information below?

Issue

https://otwarchive.atlassian.net/browse/AO3-5033

Purpose

What does this PR do?

Upgrades application from 4.2 to 5.0.

There are a handful of deprecations not addressed in this PR:

  1. alias_method_chain - there is a file, lib/plugins/livevalidation/form_helpers.rb which will need to be restructured in order to remove alias_method_chain and replace it with Module#prepend. I've held off on this as I believe the test failures it causes in 5.1 will be useful in restructuring (instead of attempting to do so blind).

  2. The dynamic :controller/:action segments in routes will not be outdated until 5.2.

Some others, left alone simply because I believe the test failures in 5.1 will make it easier to fix them.

Testing

How can the Archive's QA team verify that this is working as you intended? (If you have access, please copy this into the JIRA ticket for them!)

Due to the extensive nature of these changes, a full walkthrough in the staging environment is likely necessary to ensure everything is working as expected.

References

Are there any other relevant issues / PRs / mailing lists discussions related to this?

Credit

What name do you want us to use to credit your work in the Archive of Our Own's Release Notes?

Wendy Randquist - Littlelines

What pronouns do you prefer (she/her, he/him, zie/hir etc)?

she/her

(if you do not fill this in, we will use your GitHub account name and will use "they" to avoid making assumptions about your gender)

WendyBeth and others added some commits Jun 8, 2017

Removes test_after_commit gem - now available in Rails by default
Comments out rpm_contrib - gem triggers `cannot call config on nil` in Rails,
but cannot be upgraded because the version specified in the Gemfile was the last
version because the Gem was deprecated
Fixes :store_location has not been defined error
skip_* actions in Rails 5 will now raise if the provided method is not defined.

plataformatec/devise#4207
Fixes UserSession's inability to recognize params
Due to changes in controller params, UserSession was not recognizing the raw
params as valid login credentials. Separating the params out into a hash solved
this issue.
Fixes test bug that didn't set the default locale as a user's preferr…
…ed locale

Hard-coding '1' as the preferred_locale for a new preference makes tests nearly
impossible to maintain when the database cleaner is removing and adding Locales
on a per-test basis.
Allows params passed by view to be sent to controller
This prevents an error indicating that the use of `params.merge` in the
AlphabetHelper is unsave. However, because the parameters will be whitelisted
once handed to the controller, this should not be a problem in the helper.
Makes admins/admin_works features pass
TODO: Figure out a way to ensure AdminSetting exists wherever it's needed
without changing all of the tests like this
Extracts out text testing step that checks for html tags
Capybara intentionally does not see html with the `have_content` method, but
there are features in admin_post_news that are testing specifically for the
presence of user-entered html tags. In order to ensure those continue testing
what they're supposed to, I wrote a separate step specifically for features
where matching against certain html tags is part of what's under test.
Merge pull request #10 from JesseHerrick/jh-fix-work_model_callback_bug
Fix bug in the Work model related to Rails 5 callback functionality changes

WendyBeth added some commits Jul 6, 2017

Prevents error in work callback
Weird problem.

@work.destroy is triggering the *_save callbacks when running:

`RAILS_ENV=test bundle exec rspec spec/lib/works_owner_spec.rb[1:4:2:1:2]`

(when the work's owner is a collection)

This is happening on master. I'd consider it unexpected behavior, but it doesn't
seem to have any side-effects. The only reason it's causing an error now is
because Rails 5 no longer swallows errors raised in callbacks (in this case,
undefined method published_at for nil, because the work's chapters have already
been deleted by the time the *_save callbacks are re-triggered).
Fixes expectation that expected double error
Upgrade fixed email has already been taken error to only appear once. Yay!
Fixes bug
work.comments is not an AR Association Collection, it's a Relation object, and
therefore no longer responds to << as a method on work.comments. But
work.first_chapter.comments << comment does the same thing for the purposes
of the tests in requests/comments_spec.
Re-implements reverse_merge! in tag model method
It looks like reverse_merge! will be available for ActionController::Parameters in 5.1:

It looks like it was merged in here: rails/rails#28355

And that pull is referenced by an issue that references the current deprecationg
warning, here: rails/rails#28353

Adding reverse_merge back makes the other_a tests pass. So it seems like the
deprecation warning can be ignored.
it_redirects_to(new_orphan_path(series_id: series))
end
end
describe 'create' do
it 'renders new if the series is invalid' do
fake_login_known_user(user)
- post :create, series: {summary: ""}
+ post :create, params: { series: {summary: ""} }
@houndci-bot

houndci-bot Jul 13, 2017

Space inside { missing.
Space inside } missing.

it_redirects_to_with_error(edit_series_path(series), \
"Sorry, you cannot remove yourself entirely as an author of a series right now.")
end
xit 'allows you to change the pseuds associated with the series' do
fake_login_known_user(user)
new_pseud = create(:pseud)
- put :update, series: { author_attributes: { ids: [user.id] } }, id: series, pseud: { byline: new_pseud.byline }
+ put :update, params: { series: { author_attributes: { ids: [user.id] } }, id: series, pseud: { byline: new_pseud.byline } }
@houndci-bot

houndci-bot Jul 13, 2017

Inconsistent indentation detected.

@@ -804,6 +804,7 @@ def add_freeform_nominations(num)
}
}
}
+ }
@houndci-bot

houndci-bot Jul 13, 2017

Indent the right brace the same as the start of the line where the left brace is.

- post :create, tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
- owned_tag_set_id: owned_tag_set.id }
+ post :create, params: { tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
+ owned_tag_set_id: owned_tag_set.id } }
@houndci-bot

houndci-bot Jul 13, 2017

Align the elements of a hash literal if they span more than one line.

expect(response).to render_template('new')
end
it 'builds a new tag set nomination' do
- expect { post :create, tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
- owned_tag_set_id: owned_tag_set.id } }.
+ expect { post :create, params: { tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
@houndci-bot

houndci-bot Jul 13, 2017

Parenthesize the param change { owned_tag_set.tag_set_nominations.count } to make sure that the block will be associated with the change method call.
Avoid using {...} for multi-line blocks.
Block body expression is on the same line as the block start.

- expect { post :create, tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
- owned_tag_set_id: owned_tag_set.id } }.
+ expect { post :create, params: { tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
+ owned_tag_set_id: owned_tag_set.id } } }.
@houndci-bot

houndci-bot Jul 13, 2017

Align the elements of a hash literal if they span more than one line.
Expression at 898, 127 should be on its own line.

- post :create, tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
- owned_tag_set_id: owned_tag_set.id }
+ post :create, params: { tag_set_id: owned_tag_set.id, tag_set_nomination: { pseud_id: random_user.default_pseud.id,
+ owned_tag_set_id: owned_tag_set.id } }
@houndci-bot

houndci-bot Jul 13, 2017

Align the elements of a hash literal if they span more than one line.

- put :update, id: tag_set_nomination.id, tag_set_id: owned_tag_set.id,
- tag_set_nomination: { pseud_id: random_user.default_pseud.id }
+ put :update, params: { id: tag_set_nomination.id, tag_set_id: owned_tag_set.id,
+ tag_set_nomination: { pseud_id: random_user.default_pseud.id } }
@houndci-bot

houndci-bot Jul 13, 2017

Align the elements of a hash literal if they span more than one line.

@@ -1025,6 +1027,7 @@ def add_freeform_nominations(num)
}
}
}
+ }
@houndci-bot

houndci-bot Jul 13, 2017

Indent the right brace the same as the start of the line where the left brace is.

@@ -1079,6 +1082,7 @@ def add_freeform_nominations(num)
from_fandom_nomination: true }
} }
} }
+ }
@houndci-bot

houndci-bot Jul 13, 2017

Indent the right brace the same as the start of the line where the left brace is.

tag_set_id: owned_tag_set.id,
id: tag_set_nomination.id,
tag_set_nomination: { pseud_id: tag_nominator_pseud.id,
owned_tag_set_id: owned_tag_set.id }
+ }
@houndci-bot

houndci-bot Jul 13, 2017

Indent the right brace the same as the start of the line where the left brace is.

@@ -43,7 +43,7 @@
end
it "should redirect to the wrangle action for that tag" do
- expect(put :mass_update, id: @fandom1.name, show: 'freeforms', status: 'unwrangled').
+ expect(put :mass_update, params: { id: @fandom1.name, show: 'freeforms', status: 'unwrangled' }).
@houndci-bot

houndci-bot Jul 13, 2017

Add parentheses to nested method call put :mass_update, params: { id: @fandom1.name, show: 'freeforms', status: 'unwrangled' }.

@@ -86,7 +86,7 @@
context "with a canonical fandom in the fandom string, a selected unwrangled character, and the same character to be made canonical" do
it "should be successful" do
- put :mass_update, id: @fandom1.name, show: 'characters', status: 'unwrangled', fandom_string: "#{@fandom1.name}", selected_tags: [@character1.id], canonicals: [@character1.id]
+ put :mass_update, params: { id: @fandom1.name, show: 'characters', status: 'unwrangled', fandom_string: "#{@fandom1.name}", selected_tags: [@character1.id], canonicals: [@character1.id] }
@houndci-bot

houndci-bot Jul 13, 2017

Prefer to_s over string interpolation.

@@ -96,7 +96,7 @@
context "with a canonical fandom in the fandom string, a selected synonym character, and the same character to be made canonical" do
it "should be successful" do
- put :mass_update, id: @fandom1.name, show: 'characters', status: 'unfilterable', fandom_string: "#{@fandom2.name}", selected_tags: [@character2.id], canonicals: [@character2.id]
+ put :mass_update, params: { id: @fandom1.name, show: 'characters', status: 'unfilterable', fandom_string: "#{@fandom2.name}", selected_tags: [@character2.id], canonicals: [@character2.id] }
@houndci-bot

houndci-bot Jul 13, 2017

Prefer to_s over string interpolation.

@@ -5,7 +5,7 @@
include LoginMacros
include RedirectExpectationHelper
- describe "before_filter #clean_work_search_params" do
+ describe "before_action #clean_work_search_params" do
@houndci-bot

houndci-bot Jul 13, 2017

Block has too many lines. [149/25]

expect(assigns(:works)).to include(@unrestricted_work_in_collection)
expect(assigns(:works)).to include(@unrestricted_work_2_in_collection)
expect(assigns(:works)).not_to include(@unrestricted_work)
expect(assigns(:works)).not_to include(@restricted_work_in_collection)
end
it "should return filtered works when search parameters are provided" do
- get :collected, { user_id: collected_user.login, work_search: { query: "fandom_ids:#{collected_fandom2.id}" }}
+ get :collected, params: { user_id: collected_user.login, work_search: { query: "fandom_ids:#{collected_fandom2.id}" }}
@houndci-bot

houndci-bot Jul 13, 2017

Space inside } missing.

@ariana-paris ariana-paris changed the title from Ao3 5033 rails 5 dot 0 upgrade to AO3-5033 Rails 5.0 upgrade Jul 13, 2017

I have a few questions and some tiny nitpicks, plus there are some spots I'm asking for additional review on (some of the spots I've marked here, but others I'm asking about in the staff Slack channel), but this looks good 🎉 The most significant problem is that there are some merge conflicts, but -- unless it's easier for you -- we don't need to worry about those until the 5.1 upgrade is done and we're thinking about merging this.

app/controllers/comments_controller.rb
@@ -511,8 +511,7 @@ def redirect_to_comment(comment, options = {})
end
end
- def redirect_to_all_comments(commentable, options = {})
- default_options = {anchor: "comments"}
+ def redirect_to_all_comments(commentable, options = {}) default_options = {anchor: "comments"}
@sarken

sarken Jul 26, 2017

Owner

Does this need to be all on one line now?

@WendyBeth

WendyBeth Aug 1, 2017

Contributor

No. Sometimes my editor has its own opinion about things. >_> Will fix.

@@ -524,14 +524,16 @@ def import
render(:new_import) && return
end
+ importing_for_others = params[:importing_for_others] != "false" && params[:importing_for_others]
@sarken

sarken Jul 26, 2017

Owner

@ariana-paris Since you're our importing code expert, can you double check the logic changes here? The commit is here if that's easier to follow: littlelines/otwarchive@34c7583

@WendyBeth

WendyBeth Aug 1, 2017

Contributor

I replied in the commit to @ariana-paris. Hopefully the logic is sound.

@@ -391,7 +391,8 @@ def delete_signup_notification(user, challenge_signup)
I18n.with_locale(Locale.find(@user.preference.preferred_locale).iso) do
mail(
to: user.email,
- subject: "[#{ArchiveConfig.APP_SHORT_NAME}] Your sign-up for #{@signup.collection.title} has been deleted"
+ subject: "[#{ArchiveConfig.APP_SHORT_NAME}] Your sign-up for #{@signup.collection.title} has been deleted",
+ body: ""
@sarken

sarken Jul 26, 2017

Owner

Why is it only necessary to define body for this particular mailer? Is it because there's no existing template for delete_signup_notification? (Despite the presence of this code, we don't actually seem to send an email when a user's challenge sign-up is deleted.)

@WendyBeth

WendyBeth Aug 1, 2017

Contributor

Yes - it needs a body. It looks like it's sent in the before_destroy callback in ChallengeSignup so I'm not sure what you mean about it not being used. ?

@sarken

sarken Aug 1, 2017

Owner

I just mean I haven't gotten one of these emails when deleting challenge sign-ups in recent memory -- the last time I did it on production was April, and because this email didn't sound familiar, I tested it manually on staging shortly after this PR was submitted. It's possible Google's spam filter is eating my emails or it's been broken for a long time and we failed to notice.

@@ -1,3 +1,3 @@
<% content_for :message do %>
-<%= t 'user_mailer.invite_increase_notification.html', login: style_bold(@user.login), total: @total, invitation_page: style_link("your invitations page", user_invitations_url(@user)) , archive_name: style_link(ArchiveConfig.APP_SHORT_NAME, root_path) %>
+<%= t 'user_mailer.invite_increase_notification.html', login: style_bold(@user.login), total: @total, invitation_page: style_link("your invitations page", user_invitations_url(@user)) , archive_name: style_link(ArchiveConfig.APP_SHORT_NAME, root_url) %>
@sarken

sarken Jul 26, 2017

Owner

Nice catch -- thank you!

features/admins/admin_post_news.feature
@@ -148,10 +148,10 @@ Feature: Admin Actions to Post News
Scenario: If an admin post has characters like & and < and > in the title, the escaped version will not show on the various admin post pages
Given I am logged in as an admin
When I follow "Admin Posts"
- And I follow "Post AO3 News"
+ And I follow "Post AO3 News"
@sarken

sarken Jul 26, 2017

Owner

This lost its indenting (and the When on line 154 appears to have gained an indent. Generally, we just indent anything that's an And or a But.)

@@ -23,7 +23,7 @@ Feature: Tag Wrangling - Unsorted Tags
And I go to the unsorted_tags page
And I follow "2"
And I press "Update"
- Then I should see "2" within ".pagination span.current"
+ Then I should see "2" within ".pagination .current"
@sarken

sarken Jul 26, 2017

Owner

Just a note for my future self and/or other reviewers that I double-checked the CSS and this (the underlying loss of the span, that is) shouldn't cause a load of styling.

@@ -5,7 +5,7 @@ require 'resque/scheduler/tasks'
namespace :resque do
task :setup do
require 'resque'
- require 'resque/scheduler'
+ require 'resque/scheduler/tasks'
@sarken

sarken Jul 26, 2017

Owner

@zz9pzza I know we've had some trouble getting this right in the past and our tests didn't notice, so can you confirm this is right?

@zz9pzza

zz9pzza Aug 1, 2017

Contributor

I can't at this instant, I will be more free next week.

@zz9pzza

zz9pzza Aug 1, 2017

Contributor

However it's an easy fix, so I wouldn't treat it as blocking.

I'm puzzled by the logic here, possibly because I'm more to used to seeing if (thing exists) && (thing != "thing") logic in contexts where things blow up if thing is null, rather than if (thing != "thing") && (thing exists). Why are we checking that params[:importing_for_others] exists after checking that it isn't "false"? Is it to ensure that importing_for_others is false if params[:importing_for_others] is absent?

(I also have plans to rip some of this out and trample on it some day, so it's not a blocker either way!)

Member

WendyBeth replied Aug 1, 2017

params[:importing_for_others] will return true if it points to the string "false". So this is checking that the parameter exists, but just in case it exists and it's the string "false", it'll still evaluate to false. It also ensures it'll evaluate to false if the param doesn't exist or points to some false-y value.

If it exists but is "false" we can stop evaluating because as far as we're concerned "false" is false-y. That's why it's first, so we can short-circuit the check as soon as we have enough information to know that the value indicates we're not importing for others.

The type-checking that existed on line 528 before failed with the ugprade because the new ActionController::Parameters object in Rails 5 has changed the way it processes certain values - I think it automatically reads "false" and "1" as false when the parameters are first created. I left the type-check present to avoid false positives coming from places I can't see, since it's not always obvious how the params change once they're handed to the controller.

Thank you very much for the explanation, Wendy! 👍

@@ -4,6 +4,19 @@ class Creatorship < ActiveRecord::Base
before_destroy :expire_caches
+ validate :unique_index
@sarken

sarken Jul 30, 2017

Owner

This code looks good, but we were wondering why it's necessary -- is there something specific that was causing creatorships to be invalid due to a non-unique index?

@WendyBeth

WendyBeth Aug 1, 2017

Contributor

Took me a moment to remember: I used it to make debugging easier when I was trying to figure out why creatorships were being created twice in some callbacks. This had to do with the order of the callbacks being defined that referenced associated models through join models (hence why it's in the same commit that moves the import Taggable line). Instead of an error message indicating that something had failed to save, I wanted an error message that told me explicitly why, and writing this is how I found it.

Since it's valid and indicates what's required explicitly I never removed it.

app/models/comment.rb
+ end
+ end
+
+ def notify_user_of_own_comments?(user)
@sarken

sarken Jul 31, 2017

Owner

It looks like this was a protected method when we were using an observer. Is it possible to have this (and the other formerly-protected methods) be protected here in the model? Or does moving them to the model mean we shouldn't worry about protecting them?

(Here's the full list of methods that were protected in the observer for quick reference: notify_parent_comment_owner(comment), have_different_owner?(comment, parent_comment), not_user_commenter?(parent_comment), content_too_different?(new_content, old_content), add_feedback_to_inbox(user, comment), update_feedback_in_inbox(user, comment), notify_user_by_email?(user), notify_user_by_inbox?(user), notify_user_of_own_comments?(user))

@WendyBeth

WendyBeth Aug 1, 2017

Contributor

Whoops! I'll get these protected again. There's nothing that should prevent them from being so.

WendyBeth added some commits Aug 1, 2017

@WendyBeth WendyBeth referenced this pull request Aug 2, 2017

Merged

AO3-5034 Rails 5 dot 1 upgrade #2980

5 of 5 tasks complete

sarken approved these changes Aug 2, 2017

This should be ready to go now -- thank you so much!

@sarken sarken merged commit 04db750 into otwcode:master Aug 7, 2017

3 checks passed

Scrutinizer 53 new issues, 36 updated code elements
Details
continuous-integration/travis-ci/pr The Travis CI build passed
Details
hound 315 violations found.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment