This cycle our team tackled some big improvements for the Forem ecosystem. This post is a round up of the latest changes from our repository.
Rails 6.1
Upgrading to Rails 6 was a journey for our team that included multiple Forem team members, external contributors, and a lot of conversation.
Shout out to our open source contributors Elia Schito, Phil Coggins, and Alberto Vena who helped drive the conversation in this PR along with Forem core team members @rhymes
, @joshpuetz
, and @vaidehijoshi
.
Upgrade Rails to 6.1.3.1 #11333
What type of PR is this? (check all applicable)
- [ ] Refactor
- [ ] Feature
- [ ] Bug Fix
- [x] Optimization
- [ ] Documentation Update
Description
Rails is at 6.1.0.rc1, so I'm going to use this PR to track it until it's released and our gems have been updated.
update: Rails 6.1 is out: https://weblog.rubyonrails.org/2020/12/9/Rails-6-1-0-release/
Notable changes that might be of interest for us
railties
Change the default logging level from :debug to :info to avoid inadvertent exposure of personally identifiable information (PII) in production environments.
The autoloading guide for Zeitwerk mode documents how to autoload classes during application boot in a safe way.
Add config.generators.after_generate for processing to generated files.
actionpack
Change ActionDispatch::Response#content_type to return the full Content-Type header.
When multiple domains are specified for a cookie, a domain will now be chosen only if it is equal to or is a superdomain of the request host.
ActionDispatch::Static handles precompiled Brotli (.br) files.
brotli FTW
Add raise_on_missing_translations support for controllers.
fixture_file_upload now uses path relative to file_fixture_path
url_for will now use "https://" as the default protocol when Rails.application.config.force_ssl is set to true.
Support rolling deploys for cookie serialization/encryption changes.
neat as we have rolling deploys on Heroku
Add SameSite protection to every written cookie.
(disabled by default)
Bring back the feature that allows loading external route files from the router.
Yes! We can finally split the routes file in more manageable chunks :-)
ActionController::Base.log_at allows setting a different log level per request.
this might be useful during debugging
Add DSL for configuring HTTP Feature Policy.
this might be interesting to control which browser's API are enabled where
actionview
- lazy loading can be turned on for all
image_tag
by default - HTML output can be annotated with the template information
activerecord
where.not now generates NAND predicates instead of NOR.
Add values_at method. Returns an array containing the values associated with the given methods.
Allow associations supporting the dependent: key to take dependent: :destroy_async. :destroy_async will enqueue a job to destroy associated records in the background.
This should help!
Allow where references association names as joined table name aliases. Comment.includes(:children).where("children.label": "child")
finally!
Respect the select values for eager loading.
Allow default to be configured for Enum.
We can finally set a default to enum
!
Add basic support for CHECK constraints to database migrations.
I'm not crying, you're crying
Add ActiveRecord::Base.strict_loading_by_default and ActiveRecord::Base.strict_loading_by_default= to enable/disable strict_loading mode by default for a model. The configuration's value is inheritable by subclasses, but they can override that value and it will not impact parent class. Add support for strict_loading mode on association declarations.
This can be useful if we want to enable it on models we want to ensure they are always loaded eagerly
Add support for if_exists option for removing an index. Add support for if_not_exists option for adding index. add_index :users, :account_id, if_not_exists: true
Add ActiveRecord::Base#previously_new_record? to show if a record was new before the last save.
cool!
Support descending order for find_each, find_in_batches, and in_batches. This change allows reversing the order, batching from newest to oldest. This is useful when you need to process newer batches of records first.
Adds support for if_not_exists to add_column and if_exists to remove_column.
Love this, migrations are getting smarter and smarter
Find orphans by looking for missing relations through chaining where.missing: Post.where.missing(:author)
This is neat!
Allow adding nonnamed expression indexes to be revertible. Previously, the following code would raise an error, when executed while rolling back, and the index name should be specified explicitly. Now, the index name is inferred automatically. add_index(:items, "to_tsvector('english', description)")
YES!
activemodel
Encapsulate each validation error as an Error object. The ActiveModel’s errors collection is now an array of these Error objects, instead of messages/details hash. For each of these Error object, its message and full_message methods are for generating error messages. Its details method would return error’s extra parameters, found in the original details hash
activesupport
require_dependency has been documented to be obsolete in :zeitwerk mode. The method is not deprecated as such (yet), but applications are encouraged to not use it. In :zeitwerk mode, semantics match Ruby's and you do not need to be defensive with load order. Just refer to classes and modules normally. If the constant name is dynamic, camelize if needed, and constantize.
Cool to know!
Add 3rd person aliases of Symbol#start_with? and Symbol#end_with?.
This has been bothering me for the longest time.
Add Date and Time #yesterday? and #tomorrow? alongside #today?.
neat
Support prepend with ActiveSupport::Concern.
Related Tickets & Documents
- Rails 6.1: Horizontal Sharding, Multi-DB Improvements, Strict Loading, Destroy Associations in Background, Error Objects, and more!
- Upgrading from Rails 6.0 to Rails 6.1
- Ruby on Rails 6.1 Release Notes
- Changelogs:
-
Saeloun blog about Rails 6.1: it contains practical examples on how to use the major new features:
- Rails 6.1 adds query method missing to find orphan records
- Rails adds support for if_exists/if_not_exists on remove_column/add_column in migrations
- Rails has added strict loading mode to prevent lazy loading
- Rails 6.1 add Enumerable#pick to complement Relation#pick
- Rails adds support for descending order in find_each, find_in_batches and in_batches
- Rails 6.1 supports
if_not_exists
option for adding index - Rails adds support for annotating HTML output with template file names.
- Rails 6.1 adds support for destroying dependent associations in the background
- Rails 6.1 adds support for check constraints to database migrations
- Rails 6.1 adds query method associated to check for the association presence
- Rails 6.1 adds config option to control image_tag loading attribute
- Rails 6.1 adds ActiveRecord methods
#sole
and#find_sole_by
QA
- boot the app
- click around and test the main areas, create an articles, leave a comment, make sure everything is working
Added tests?
- [ ] Yes
- [x] No, and this is why: we need current tests to pass for the upgrade, new tests are not needed in this upgrade branch
- [ ] I need help with writing tests
Analytics for all Users
This PR removes the “Pro” role that was only available to a select group of users, and gives access to analytics to every user on Forem. You can read more about this change in the post Changelog: Analytics for All!
Changelog: Analytics for All!
Vaidehi Joshi for Forem Core Team ・ Mar 30 ・ 2 min read
If you try out this new feature and find any bugs, please report them in our repository.
If you would like to give feedback on ways this feature can be improved, feel free to create a post here on forem.dev.
Remove pro role + expose analytics to all users via dashboard #13156
What type of PR is this? (check all applicable)
- [x] Refactor
- [x] Feature
- [ ] Bug Fix
- [ ] Optimization
- [x] Documentation Update
Description
Related Tickets & Documents
Closes https://github.com/forem/internalEngineering/issues/403.
QA Instructions, Screenshots, Recordings
To QA this feature, first make sure that you have a user locally who does not have the :pro
role:
pry(main)> u = User.find_by(username: 'your-username-goes-here')
=> #<User id: ...>
]pry(main)> u.has_role? :pro
=> false
QA Instructions, Part I:
- Try going to
/dashboard
. On the bottom left of the sidebar, you should see anAnalytics
option in the menu. Click on that:
- Clicking on that should take you to your "Analytics Dashboard", which previously was the "Pro dashboard". Make sure there is no "pro" language (everything should read "analytics dashboard):
QA Instructions, Part II:
- Create an organization (here's the route to do so).
- Go back to your
/dashboard
. Note that theAnalytics
option still renders as before, only now you also should see anAnalytics [Your Org Name
option as well (click on that one!):
QA Instructions, Part III:
- Assign your user either an
:admin
or:super_admin
role, and go to/admin/users
. Select a user to edit, and scroll down to the "User Status" section of the page. Click the dropdown, and ensure that thePro
role does not show up there:
UI accessibility concerns?
No HTML or UX changes happens as a part of this PR, so I don't think so.
Added tests?
- [ ] Yes
- [x] No, and this is why: I've updated pre-existing tests and added new ones where necessary (but didn't overhaul the testing significantly enough IMO to check the "Yes" box
😉 ) - [ ] I need help with writing tests
[Forem core team only] How will this change be communicated?
Will this PR introduce a change that impacts Forem members or creators, the development process, or any of our internal teams? If so, please note how you will share this change with the people who need to know about it.
- [ ] I've updated the Developer Docs and/or Admin Guide, or Storybook (for Crayons components)
- [ ] I've updated the README or added inline documentation
- [x] I will share this change in a Changelog or in a forem.dev post (I will work with @cmgorton to make sure this is highlighted/announced to the community since we are sharing a feature that was previously only available to handful of folks!)
- [x] I will share this change internally with the appropriate teams
- [ ] I'm not sure how best to communicate this change and need help
- [ ] This change does not need to be communicated, and this is why not: please replace this line with details on why this change doesn't need to be shared
Are there any post deployment tasks we need to perform?
After this feature is out, we will need to delete any Pro
roles from the database. Even with the "pro" code all removed, the role still exists in the database, as evidenced by this screenshot of my local Forem instance, once I added the :pro
role to my own user and deleted the "pro" code (seems like the Role
instance still exists in the database):
I think that this only applies to the DEV community, but I'm not entirely sure about that and could use some gut checks there. My thought was to either write a DataUpdateScript (if this applies to many communities), otherwise maybe we can delete the :pro
role directly via a DEV console?
A script would definitely be more comprehensive, but if no other Forem instance has pro
roles, that feels much more heavyweight than we need it to be.
What gif best describes this PR or how it makes you feel?
@-Mention Autocomplete
This PR adds autocomplete functionality for usernames. This feature is now available for both comments and posts.
You can read more about the component created for this feature and upcoming plans to use it in other areas of Forem in the post Changelog: Autocomplete for user mentions.
Changelog: Autocomplete for user mentions
Suzanne Aitchison for Forem Core Team ・ Mar 31 ・ 1 min read
Add (updated) mention autocomplete to post comments #13061
What type of PR is this? (check all applicable)
- [X] Feature
Description
This PR adds the @mention
autocomplete component to:
- Comments on a post
- Replies to comments on a post
- Replies to post comments in a notification
Related Tickets & Documents
RFC: Create Mention Autocomplete
QA Instructions, Screenshots, Recordings
This will need tested in each of the situations mentioned above, ideally on mobile devices as well as desktop to make sure all's working well.
Steps to test post comments:
- Go to a post
- Click to add a comment
- Start typing, including some
@mentions
(you might want to add some users with similar usernames to your local DB to be able to see fuller lists appearing in the dropdown) - Experiment with selecting options with keyboard (up/down arrows + Enter) and mouse
- Experiment with deleting portions of the mention, ignoring the options and keeping typing, etc - try to break it
😄 - Repeat as above with replies to comments on a post
Video of these test steps:
Steps to test post comment replies in notifications:
- Send a notification to your current user in the console:
user = User.find_by(username: "admin_mcadmin")
other_user = User.first
article = user.articles.last
comment = article.comments.create!(user: other_user, body_markdown: "Test something")
Notification.send_new_comment_notifications_without_delay(comment)
- Refresh the page and go to the notification
- Click reply and repeat the above steps
Video of these test steps:
UI accessibility concerns?
This component should be operable by keyboard alone, and when using a screen reader, should announce the "combobox" functionality, and read the options in the dropdown when populated. This has largely been tested, and concerns documented in the previous PR #13044
Added tests?
- [X] Yes
[Forem core team only] How will this change be communicated?
[optional] What gif best describes this PR or how it makes you feel?
Removed Mod Button on Mobile’s Top Navigation Bar
This PR removes the moderator button in the top nav bar that caused the profile menu button to be pushed off the screen on mobile if a community had a wide logo.
Remove mod button from top nav bar in mobile #12906
What type of PR is this? (check all applicable)
- [x] Bug Fix
Description
Remove the mod button in the top nav bar, since it was causing a bug that pushed off the profile menu button in mobile.
Related Tickets & Documents
Resolves https://github.com/forem/internalEngineering/issues/393
QA Instructions, Screenshots, Recordings
UI accessibility concerns?
Should be okay! Just added a link with nothing special about it.
Added tests?
- [x] No, and this is why: I could add an e2e test but I'd rather not slow down this bug fix. Maybe in a separate PR.
[Forem core team only] How will this change be communicated?
- [ ] Other: I will share this change with moderators in the appropriate Connect channels
[optional] Are there any post deployment tasks we need to perform?
Nope
[optional] What gif best describes this PR or how it makes you feel?
Optimize Finding Articles by Followed Tags
This PR improves the performance of searching for articles by the tags a user followed. It also paves the way for future optimization in more places where users search for articles by tags.
User#followed_articles->Article.cached_tagged_with #13174
What type of PR is this? (check all applicable)
- [ ] Refactor
- [ ] Feature
- [ ] Bug Fix
- [x] Optimization
- [ ] Documentation Update
Description
This should improve performance on StoriesController#index.
On DEV, the mismatch between tagged_with
and cached_tagged_with
is at most 0.007% — the javascript
tag, with 4 mismatches, the last of which was published over 3 years ago.
Running it for all the tags I could think of off the top of my head, I came up with 0 mismatches on all articles published within the last year:
articles = Article
.published
.where('published_at > ?', 1.year.ago)
%w[ruby javascript discuss meta elixir golang rust career performance].map do |tag|
(articles.tagged_with(tag).count - articles.cached_tagged_with(tag).count).abs
end
# => [0, 0, 0, 0, 0, 0, 0, 0, 0]
Added tests?
- [ ] Yes
- [x] No, and this is why: The existing tests should be sufficient to ensure the behavior has not changed
- [ ] I need help with writing tests
[Forem core team only] How will this change be communicated?
Will this PR introduce a change that impacts Forem members or creators, the development process, or any of our internal teams? If so, please note how you will share this change with the people who need to know about it.
- [ ] I've updated the Developer Docs and/or Admin Guide, or Storybook (for Crayons components)
- [ ] I've updated the README or added inline documentation
- [ ] I will share this change in a Changelog or in a forem.dev post
- [x] I will share this change internally with the appropriate teams
- [ ] I'm not sure how best to communicate this change and need help
- [ ] This change does not need to be communicated, and this is why not: please replace this line with details on why this change doesn't need to be shared
Forem Loads on an Apple M1
This PR fixes an error while trying to load a Forem on a M1 Mac. You can read more about the error and how it was fixed in the PR description.
Update http-parser and ffi gems so Forem can load on an Apple M1 #13086
What type of PR is this? (check all applicable)
- [ ] Refactor
- [ ] Feature
- [x] Bug Fix
- [ ] Optimization
- [ ] Documentation Update
Description
I was getting this error trying to load Forem on my M1 Mac:
<snip>/gems/ffi-1.14.2/lib/ffi/library.rb:145:in `block in ffi_lib': Could not open library '<snip>/gems/ruby-2.7.2/gems/http-parser-1.2.2/ext/aarch64-darwin/libhttp-parser-ext.bundle': dlopen(<snip>/gems/http-parser-1.2.2/ext/aarch64-darwin/libhttp-parser-ext.bundle, 5): no suitable image found. Did find: (LoadError)
<snip>/gems/http-parser-1.2.2/ext/aarch64-darwin/libhttp-parser-ext.bundle: mach-o, but wrong architecture
<snip>/gems/http-parser-1.2.2/ext/aarch64-darwin/libhttp-parser-ext.bundle: mach-o, but wrong architecture
My Ruby installation was compiled for the M1:
➜ forem git:(master) file $(which ruby)
<snip>/ruby-2.7.2/bin/ruby: Mach-O 64-bit executable arm64
Updating http-parser
updated the ffi
gem, which fixes the bug on ARM Ruby.
Added tests?
- [ ] Yes
- [x] No, and this is why: the end result should be identical functionality
- [ ] I need help with writing tests
[Forem core team only] How will this change be communicated?
If running Forem was broken for everyone using Ruby compiled for the Apple M1 before this, we may want to communicate that it can now run on an M1-compiled Ruby.
- [ ] I've updated the Developer Docs and/or Admin Guide, or Storybook (for Crayons components)
- [ ] I've updated the README or added inline documentation
- [ ] I will share this change in a Changelog or in a forem.dev post
- [ ] I will share this change internally with the appropriate teams
- [x] I'm not sure how best to communicate this change and need help
- [ ] This change does not need to be communicated, and this is why not:
[optional] Are there any post deployment tasks we need to perform?
Not unless we're deploying to boxes with ARM CPUs.
Top comments (1)
My favourite notification! I have tried @mentions in posts, very very cool!