Short Ruby - edition #15

Briefly about everything happening in Ruby world

If you want a short excerpt of this newsletter containing only some of the images with code, I created one here. But I invite you to read the entire newsletter as it has excellent content 😊.

This edition was created with support from @adrianthedev from Avo for Ruby on Rails (a friendly full-featured Rails admin panel) and from @jcsrb, who sent me recommendations to include in the newsletter.

👉 Lucian Ghinda shared a thread about the growing Ruby community:

I also see a lot of new projects happening in #Ruby world: - new gems solving more problems or adding more features - more FE-oriented libraries - new podcasts - more videos and new channels - new newsletters - new books While also seeing steady progress on existing projects

👉 Brandon Weaver shared a poll about the behavior of Hash.new([]):

Ruby folks: Do you find Hash.new([]) confusing? array=[] hash=Hash.new(array) hash[:a] << 1 # => [1] hash[:b] << 2 # => [1, 2] hash[:c] << 3 # => [1, 2, 3] hash # => {} array # => [1, 2, 3]

Joel added an excellent rule that could be applied when doing code review:

Josh Cheek showed a funny way to use the Hash.new with arguments (source code Github)

🤘 = Hash.new(Lol = Class.new) 🤘[🤘].define_method(:bbq) { 🤘[🤘] } class Omg < 🤘[:😈] instance_eval { alias wtf new } end Omg.wtf.bbq # => Lol

Rein Henrichs replied with some more examples of using Hash.new:

Here is the official documentation about Hash.new([]):

Note that the default value is used without being duplicated. It is not advised to set the default value to a mutable object: synonyms=Hash.new([]) synonyms[:hello] # => [] synonyms[:hello] << :hi # => [:hi], but this mutates the default! synonyms.default # => [:hi] synonyms[:world] << :universe synonyms[:world] # => [:hi, :universe], oops synonyms.keys # => [], oops To use a mutable object as default, it is recommended to use a default proc

Brandon submitted a feature request to Ruby with some proposal to change or warn when calling Hash.new with non-value objects.

You should read the entire discussion on Twitter as it has more explanations.

👉 Thiago Massa shared a code sample about using include to add methods to objects:

Ruby Gems frequently use the `include` method to integrate with your Application. What does it do? Why is it that Gems like it so much? 🧐 There are a few ways to add methods to your class in Ruby, such as inheritance, "include" is also a good option 😉 Let's take a look 👀👇

👉 Greg Navis shared a Rails tip about Active Record error messages to enable full message customization, defining attribute error format and providing an arbitrary error message:

💡Rails tip: Active Record error messages often provide poor UX. Fortunately, they can be easily overridden! 1️⃣Enable full message customization 2️⃣Define attribute error format 3️⃣Provide an arbitrary error message Result: full control over the error message!

👉 Brandon Weaver asked about how to find dead code in Ruby:

Ruby folks: What's your favorite method of finding and removing dead code? I was trying with CTags a bit ago but didn't have much luck getting it to run.

Here are some of the answers:

👉 Emmanuel Hayford shared a tip for Rails 7 to define a to_s on the module and use it with link_to:

TIL that in Rails 7, when you define a to_s in your model you can pass a single argument to link_to. Thanks to @olivierlacan

👉 Greg Navis shared code sample about complex validations in Ruby:

💡Rails tip: complex validation logic can be encapsulated in specialized validator classes 👉🏻Example: invoicing app that allows users to customize their invoices via an HTML template. The template must be validated before use. 🎉Solution: a specialized validator class.

👉 Thiago Massa shared a code sample about using include and extend and the difference between them:

Ruby's methods "include" and "extend" can be confusing. 😵‍💫 Let's clear up the difference once and for all. 😉 Include: Adds methods to the instance of the class (most commonly used) Extend: Adds class methods to the class Example:

Jean Boussier shared is a concise explanation about the difference between extend and include:

He also shared a code sample explaining include and prepand:

👉 Maciej Mensfeld shared a warning about using rest_client gem:

🦠💥 #rubyfriends watch out! rest_client (not rest-client) went rogue just now! With over 2.6mln downloads(!), it now collects host info upon requirement: https://t.co/fs4DOwkUJP Detected by @Mend_io #ruby #rubygems #supplychain #opensource #cybersecurity

👉 Jason Swett shared an explanation about the difference between after_commit and after_save/after_destroy:

 PSA: after_commit is NOT equivalent to after_save + after_destroy. after_save/after_destroy run inside the db transaction. after_commit runs after the transaction has been committed. Ignorance of this distinction can result in some surprising and pernicious bugs!

See the official documentation here.

👉 David shared a short bit of knowledge about ActiveRecord toggle method:

TIL ApplicationRecord toggle. A nice little helper to switch a boolean attribute 👌 There is also toggle! which will update the field in the database.

👉 Kirill Shevchenko shared a code sample showing how to remove a method from a class:

In Ruby, there are several ways to remove a method from a class: undef_method removes the method and prevents the method from being looked up in the parent class. remove_method removes the method, but still looks for the method in the parent class.

Chris Seaton shared a concise way to explain undef_method

👉 EK shared a quick tip about lazy loading images in Rails and specifying multiple sources:

👉 Steve Polito shared a code sample about updating all columns all at once:

Did you know, #rails provides a mechanism to update all records at once by using existing values per record? 🪄 This is useful if you’re adding a new column that needs to be backfilled with data from an existing column.

👉 Marc Busqué shared a code sample about functional idiomatic ruby and currying:

Functional objects have definitely become a common idiom in #ruby. One thing I'd love is to have a way to coerce an object responding to "call" to a Proc. That way, we could have polymorphism between actual procs and functional objects, and the circle would be complete 😋

Marc also submitted a feature request to Ruby.

👉 Zilvinas Kucinskas shared a code sample about return in lambda vs procs:

💎 In lambdas, "return" means “exit from this lambda”. In regular procs, "return" means “exit from embracing method”.

👉 Matt Swanson shared a code sample with two Rails methods to_sentence and squish

Some Rails methods you'll kick yourself for not knowing 🤦

👉 Greg Navis shared a code sample about validation contexts in Rails:

💡Rails tip: Active Record supports custom validation contexts ❓How would you implement this: regular users can pick logins that are 6+ characters long but admins can change them to any length? ✅Contexts to the rescue! 👇🏻Some important keeps to thing in mind ...

👉 Janko Marohnić shared a code sample showing how to work with window function with Sequel:

I frequently learn new SQL concepts while reading Sequel’s documentation. TIL about the frame clause for window functions💡 They allow you to specify a subset of the current partition. Curious about the use cases 🤔

👉 Greg Navis shared the strict option for Rails validates, which will raise an exception when validation fails:

💡Rails tip: strict validation can be used to enforce internal rules Regular validations don't raise and add user-facing error messages. But not all validations work like that! Some validations are for internally managed columns, so reporting their errors could be confusing.

👉 Tom Stuart shared a code sample showing that in Ruby 3.2 a hash pattern can be used to extract regular expressions named captures:

I was excited to learn from @paracycle that https://t.co/2Jf15unEpZ has been merged, so in Ruby 3.2 we’ll be able to use a hash pattern to extract regular expression named captures without needing to `refine MatchData`. Thank you @keystonelemur & @palkan_tula & @k_tsj! 🎉

👉 Lucian Ghinda shared a code sample showing how to use forward argument notation:

👉 Bridgetown shared the registration is open for BridgetownConf:

Registration for BridgetownConf 2022 is now open! The full website with program and speaker list is now available: https://t.co/R5HC70yZvp We hope you'll join us (for free!) on Monday, November 7, 2022 for a wonderful time of discovery and camaraderie as Ruby & Web developers.

👉 Kevin Newton shared a code sample showing that any expression can be part of the left-hand side of defining a method on an object:

class Foo end class Bar end def (rand > 0.5 ? Foo : Bar).baz end TIL Any expression is allowed on the left-hand side here. Didn't know that before deciding a new parser was a great idea lol.

👉 Kirill Shevchenko shared a code sample showing how to turn a Class into an Enumerator:

A trick to turn any Class into an Enumerator with enum_for, yield and block_given?

If you have read so far and you like the content, maybe you take into consideration sharing this and subscribing:

Related (but not Ruby-specific)

Mayank shared a simple trick to make attribute selectors case-insensitive:

i was looking inside UA stylesheets (don't ask why) and learned that you can make attribute selectors case-insensitive by adding an "i" at the end 🤯 e.g. [data-visible="true" i] matches all of these: <div data-visible=true> <div data-visible="True"> <div data-visible="TRUE">

Xavier Noria reminded us that when using the library, we should only use the public API and no private methods:

The public API of your library is what the documention says, not what you see in the source code. Libs may need to access internal-only methods across classes, so they have to be public, but they are not for end-users. Look at the docs, not the source code!

 Vitaly Friedman shared an article written by UX team leader from WIX about how to write a good error message:

👉 Robby Russell shared a tip about using take command with a git repo:

ProTip: Pass your git repo to the take command via #ohmyzsh.

Andrew Mason asked about favorite VSCode extensions:

👀 What's one or your favorite @code extensions? Bonus points if I wouldn't find it on a "Top 10 VS Code Extensions of 2022" blog post 😉

Here are some of the answers:

🧐 Adrian Marin shared a tip about Tailwind 3.2 and usage of new variants for data-* attribute:

💡Rails tip: ✅ Tailwind 3.2 will support new variants for data-* attributes. ✅ You can target and style elements by their data attributes. ✅ Especially useful when you're dealing with dynamic values in your Stimulus JS controllers. #rubyonrails #Tips

🧐 Dr Nic asked a question about the security risks of including magic links in emails:

Security question: if my app sends you an email, is it ok for the links to be "magic login" links that last an hour or two? If you get the email and click on my links, is it ok for me to automatically log you in? What are the scenarios/reasons for which this is bad?

Among recommendations:

  • Make the magic link valid for only 20 minutes

  • Use an Ajax post of click to log in that submits a form to mitigate the risk of link checkers logging in users.

  • Be aware of where you include this link, as people might forward an email without knowing there is a magic link

🧐 Nate Hopkins presented a kind of architectural challenge about running multiple SQLite instances:

Seriously wondering what the downside of a single beefy server running multiple Sqlite instances (1 per customer) would be compared to the distributed cloud equivalent... at around 4k concurrent users. Now, consider a multi-region deployment with this setup.

You should read the entire conversation. Here are some of the recommended links there:

🧐 Jason Swett shared a new metaphor to think about technical debt:

I think tech debt is a poor analogy. One I like better: blades. Each piece of code is a blade which is either sharp or dull. A dull blade is ok if you never cut with it. Often-used blades should be kept sharp. Blades naturally dull with use, and require regular sharpening.

🧐 Alex Russell shared a tread about Frontend development:

The frontend community wants to wash its hands of the decade we lost without naming the causes and consequences of the dogma that swept away better, more grounded approaches and replaced them with MBs of JS. That's not a recipe for healing what was broken.

Maybe you might consider also reading the HN discussion for this tweet and the thread that Jared White shared quoting Alex Russell.

Articles and Videos

Courses/Books

Noel Rappin shared they are working on a new edition of Programming Ruby - the Pickaxe book. Soon available on The Pragmatic Bookshelf

Ben Orenstein shared they will start a new The 30-Day Code Quality Challenge in January.

Something to read

🗞 Newsletters

🗞 Ruby Weekly shared a new edition 625 - Puma 6.0 release 

🗞 Ruby LibHunt published a new edition of the Awesome Ruby Newsletter

✍🏾 Articles

Adrian Marin shared an article about open source Open-Core Companies Are Not Incentivized To Make Their Projects Good. But you should also read the thread where he shared how he thinks about open-source and how he positions Avo 

Yaroslav Shmarov shared an article they published about sending messages to Slack using Slack API. Send text, markdown, and files to Slack

Joel Drapper shared a new article they wrote about Magic template methods. You should also read the code in Github where Joel added some explanations.

Vladimir Dementyev shared the second part of the series about View Component: ViewComponent in the Wild II: supercharging your components

Martin Spickermann shared an article written by Andy Croll about compressing HTML responses from within Rails: Compress Your HTML Responses 

Maciej Mensfeld shared a new article about the security incident with rest_client written by Maria Korlotian: To use rest_client, or to use rest-client, that is the question

Adrian Valenzuela shared an article about building web apps: 12 Factor App Revisited

Ruby Lib Hunt shared an article about Top 10 highest paid programming languages in 2022 that includes Ruby in the 7th position.

Dr Nic shared an article they wrote about Friendly IDs for Ruby on Rails

The Ruby Dev shared an article written by Trevor Vardeman about Seed Dump: Rails - A Hidden Gem: Seed Dump

Something to watch 🎥 or listen 🎧

🎥 Videos

🎥 Drifting Ruby shared new episode about authentication using Magic Links

🎥 Yaroslav Shmarov published a new video about sending messages to Slack: Ruby on Rails #93 Slack API.

🎧 Audio & Podcasts

🎧 Joël Quenneville shared a new episode where DoodlingDev discusses the role of Ruby class methods: The Bike Shed: 358: Class Methods

🧰 Gems, Libraries, and Updates

🧰 R7kamura shared a new gem rubocop-migration implementing rules that check migrations. See the source code on Github

🧰 Dry Rb shared the list of dry gems that are using Zeitwerk. Read the article dry-rb adopts Zeitwerk for code loading

🧰 Bozhidar Batsov shared a new release of Rubocop 1.37. Read the changelog to see the new cops added:

🧰 Alessandro Rodi shared a new gem passkit:

Your out-of-the-box solution to start serving Wallet Passes in your Ruby On Rails application. 

🧰 Jeremy Evans shared they released a new version of Rodauth 2.26.0

🧰 Rubygems News shared a new version of tailwindcss-rails is released

🧰 Koichi Ito shared a new release of Rubocop Rails v. 2.17.0

🧰 Yasuo Honda shared that the Pull Request to support exclusion constraints was merged to Rails, and it will be released with Rails 7.1

🧰 Andrey Novikov shared they created a new gem that created a yabeda plugin for Sidekiq: yabeda-sidekiq

Reply

or to participate.