1. Vacuum, I/O performance, and query performance gains. 2. JSON_TABLE for converting JSON documents into tables. 3. More features added to MERGE. 4. Simpler upgrades when using logical replication + failover!
1. Support for multiple apps. 2. Support for gapless deploys. 3. Automatic Let's Encrypt integration. 4. Command aliases and simplified secrets management.
This is a regrouping of Hotwire components used for mobile app development to increase clarity, and make it easy to reap the benefits of Hotwire on mobile.
Last but not least, @dhh delivered a passionate keynote where he laid out the next steps for conceptual compression: this time eliminating PaaS from the equation. 👏
Definitely worth watching to understand where Rails is going.
🎓 If you enjoy learning about Rails and would like to keep learning more then follow me @gregnavis.
You can help spread that knowledge by liking and retweeting the thread.
🙇🏻♂️ Thank you! I'll see you in another thread soon.
💡 Rails tip: Rails 7 shipped with error handling infrastructure
It's a small module, but I find it extremely useful, especially when integrating with third-party APIs, as you usually want to gracefully inform the user the API is down, but still report that internally.
Ready?
At a high level:
- there are multiple subscribers registered with the error reporter
- each error is passed to each subscriber
- the reporter offers methods for detecting, reporting, and swallowing exceptions thrown by the app
Let's take a close look at those methods.
Rails.error.handle - runs the block, swallows and records any exceptions raised by it
If no exceptions are raised then the block value is returned.
If an exception is raised then nil is returned, unless a fallback is given, but more on that in a minute.
💡 Ruby meta-programming: lazy accessors are simple to implement and more robust than lazy computations via ||=
Meta-programming can be fun, productive, and helpful. Let's have a look at another example, including a bigger engineering lesson.
⬇️ Let's go!
What's a lazy accessor?
It's an accessor with a block of code to determine a value. That block of code is called only on first use; subsequent calls reuse the value the block returned.
In short: lazy accessor = laziness + caching
What are its applications?
Primarily, deferring expensive computations until needed and ensuring they are run only once.
Example: expensive database reporting query with further result processing in Ruby.
Let's have a look at the idiomatic way of handling that in Ruby ...
💡 Ruby meta-programming idea: final classes can be easily implemented in Ruby
I've actually published a gem whose first feature is exactly that. More on that later though. Let's understand the concept of final classes first.
Ready? Set? Go!
What's a final class?
A final class is a class that cannot be inherited from. Any attempt to subclass it would result in an error (compile-time or runtime, depending on the language).
It's a foreign concept in Ruby land, so let's have a look at other languages.
In UIKit, Apple's UI framework, there's a view controller called UIAlertController for displaying all sorts of alerts.
Technically, it's NOT final, but the documentation says it should be used as-is and not subclassed.
💡 Rails tip: as_json can be used to convert models into ... no, not JSON ... into hashes
It can be useful when building and working with APIs, so it's always a good idea to understand how it works. It's implemented by Active Model and is quite generic.
Let's dive in! 🤿 😅
Called without arguments it returns a hash including all columns in the model.
Is this a good idea? NO!
⚠️ Do that in a public API and it's guaranteed you'll leak sensitive data sooner or later. Therefore, you should use this rarely, if ever.
What's the alternative?
You can whitelist or blacklist columns (and wrap the output in a hash).
My recommendation: whitelist by default, unless you're sure blacklisting is better
You may think whitelisting and blacklisting are two sides of the same coin but they are NOT!
💡 Ruby tip: hierarchical logger can be built in under 20 lines
Motivated by helping active_doctor_users identify specific parts of their code base that break the tool.
Logs benefit from structure, and it's trivial to add _some_ structure even if they're text-based.
Here's how
Text logs shown as a sequence of lines fail to capture the call stack structure.
If line A is followed by line B then it's difficult to tell whether B is from the same function, a caller function, a callee function, or another place entirely.
Fortunately, it's easy to fix.
Indentation can be used to introduce structure into otherwise purely text-based logs. It's like indenting source code to make it more readable.
The best part: doing that in Ruby in trivial, but elegant!