Issue #7 - 22 - 28 August 2022

The one with the end of an era

Hello,

I’m Lucian (find me on Twitter @lucianghinda), and I am the curator of this newsletter. Thank you for subscribing to this newsletter.

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.

Any Ruby developer wants to test their debugging skill? Here's a little challenge for you

Amree Zaid shared an excellent summary for Xavier Noria talk “The Journey to Zeitwerk” from the RailsConf 2022. Each tweet has a link to the specific time in the presentation and they also link to issues and discussions from Ruby and Rails projects:

Started to watch RailsConf 2022 beginning with The Journey to Zeitwerk by @fxn It's pretty detailed and I don't exactly understand all of them but I would like to point out how beautifully it was executed with collaboration from various people/organisation 🧶 1/9

I asked a question about how to organise methods in a class:

#ruby #question How do you organize same level methods in a class? For private methods: I organize them in the order they are called from public methods For public methods: I try to organize them in the order of importance (how they will be used)

Some responses said they were ordering them alphabetically:

1. Most abstract to most concrete 2. First called to last called 3. I sometimes group custom setters with their getter counterparts even if not called at the same time. 4. Initialize is the first method, unless I also define self .new 5. Class methods are usually in a self << class block, though not if there’s only one.

And in the same line, Jared White suggested:

Thiago Massa shared a short tip about how to use the debugger in the Ruby 3.1.0 release:

Ruby 3.1 is one of the most interesting releases so far. So many new features, I'm still digesting everything. Have you tried the new and shiny "debug" gem yet? What about YJIT and so many dev ergonomics updates? Check it out: https://t.co/YgoNv4kZl9

Benito Serna shared how to use lateral joins to get the most recent N posts for each user:

Sometimes it could be ok to just fetch all elements and filter with ruby, but sometimes it is not possible. Also it can cause n+1 queries if your are not careful. One way of solving the problem is to use a lateral join like this:

Andrew Mason shared that they are trying to use turbo with tables and received replies with some workarounds or possible solutions for this:

Trying to use turbo with tables instead of lists is way harder than it should be. I wonder if thats why the scaffolds no longer create tables by default for index views.

If you are trying to do this here are some links or responses:

  1. Creating a fake table (see examples here shared by Pedro Schmitt)

  2. An open PR for Turbo to Mix in Turbo Frames to build-in elements shared by Marco Roth

  3. An article was written by Ariel Scherman about “Updating HTML tables with turbo streams”

Janko Marohnić asked about how to organize deep nested ViewComponents:

At work we use ViewComponent extensively, and in principle avoid writing helpers. However, I noticed that following the official naming convention gets cumbersome when nesting components, we end up with classes like ArtistComponent::AlbumComponent::SongComponent.

Among the suggestions:

  • “nesting components under a Views module in Phlex.fun, so you’d have Views::Artists::Index, Views::Album” by Joel Drapper here

  • “Artist::Component | Artist::Album::Component | Artist::Album::Song::Component” by Konnor Rogers here

  • Not use Component in the nested objects by Benito Serna here:

    • ArtistComponent

    • ArtistComponent::Album

    • ArtistComponent::Album::Song

  • Xavier Noria shared a piece of code to namespace all classes in app/components with Components:

Kirill Shevchenko shared a piece of code showing Fibers and how they work with infinite loops:

A little warning: Fiber wouldn't "say" that you've created an infinite loop and a code with Fiber in Ruby

Brandon Weaver asked a question about anonymizing all arguments of a Ruby method, and then he shared exploring various ways of achieving this:

Say that I wanted to anonymize all of the arguments for a Ruby method, such that: test(a, *bs, c: 1, **ds, &fn) becomes: test(_, *_, c: _, **_, &_) What's the fastest way to do that?

Steve Polito shared about how to represent model attributes as value objects. Check the Rails documentation here:

class User < ApplicationRecord # ℹ️ This will create User#name_of_person and User#name_of_person=(name_of_person) composed_of :name_of_person, # ℹ️ This maps the user attributes to the class arguments mapping: [ %w(first_name first), %w(last_name last)] end

Greg Molnar shared on how to implement security improvements while developing with Rails:

3 simple Rails security improvements you can do with a few minutes investment: 🧵👇

Rob Zolkos shared a small web app that helps to format strftime for Ruby.

Cool little site - https://strftimer.com Paste in how you want your date string to look and it will give you the strftime formatting argument #ruby

Direct link: https://strftimer.com

Facundo Espinosa shared in a short thread how they did infinite scroll with Rails 7 and Hotwire:

I’m using pagy (https://ddnexus.github.io/pagy) for pagination, so I refactored the controller to use it

And here he shared is the HTML part of implementing the infinite scroll:

Xavier Noria shared about autoloading reloadable code from initializers in Rails 7:

Rails 6 deprecated autoloading reloadable code from initializers, and in Rails 7 that is not longer possible. This change coincides in time with the transition to Zeitwerk, but it is unrelated. It is a common misconception to associate both things.

I feel the entire text is very important to understand reloadable code:

Rails 6 deprecated autoloading reloadable code from initializers, and in Rails 7 that is not longer possible. This change coincides in time with the transition to Zeitwerk, but it is unrelated. It is a common misconception to associate both things. (source)

Autoloading reloadable code in initializers doesn't make sense conceptually and this removal would have made sense even if the autoloader was not changed. (source)

Reason is, initializers only run once. If, say, you used model M in an initializer and reload, whatever M was used for is now stale, because the initializer does not run again. So, preventing this made sense regardless. (source)

Xavier recommends reading the Rails guide section: Autoloading When the Application Boots 

Emmanuel Hayford shared what happens when a class is instantiated with a cool code example:

What really happens when you instantiate a class in Ruby? 3 things essentially. In this snippet we implement our own version of `new` to create a new instance of the `Country` class. All this freedom for free in Ruby.

Chris Oliver shared the date for the Rails Hackathon: 17-18 September 2022:

Check the hackathon main website https://railshackathon.com

Nate Berkopec shared their view about moving logic from jobs to POROs and triggered a nice discussion with pros and cons for each approach:

Call me crazy but I don't think that moving all of your background worker's code into another file in app/services is an improvement if you never call it from anywhere else

It is worth reading the arguments of both sides, and there are points worth considering.

Postmodern shared a question about why Active Record returns strings instead of symbols for an enum attribute and triggered a nice discussion about how they work:

Today's fun ActiveRecord WTF: why is ActiveRecord returning Strings instead of Symbols for an enum attribute from a model, which is being returned via find_or_create_by(...) that's given Symbols values.

The discussion got interesting with Andreas Finger suggesting the use of activerecord-postgres_enum while Schneems, Jean Boussier and postmodern discussing if the return of string and not symbol is a historical artefact from when symbols where not GCed (pre ruby 2.2) or maybe because String methods were slowly backported to Symbols.

Jason Charnes shared launched a new project for creating jobs boards. Direct link to jobboardly.com

I'm carrying the torch from @excid3 on the job board software powering the GoRails jobs site. I'm not sure how much "building in public" I'll do, but if you want to start a job board check it out and let me know what you think!

Heroku shared the end of the free tier, and this (rightly so) occupied the attention of many people in the community:

Here are some of the responses to this announcements:

  • David Colby shared more about why Heroku helped to learn: “Heroku discontinuing free dynos is a tremendous bummer. Free dynos were an incredible resource as a learning tool when I was getting started as a developer, and they're still a great tool to demo functionality when I'm writing tutorials now. Sad.”

  • Schneems shared in a thread a collection of tweets about Heroku's decision to remove the free tier. It is worth reading the entire thread and seeing how much good Heroku did in the past for the Ruby and Rails community and how much people valued this product.

  • Brad Gessler shared they wrote a guide to migrate from Heroku to Fly.

Espen shared an option for bundle CLI to see which gems are looking for funding:

Have not noticed this before: "1 installed gem you directly depend on is looking for funding. Run `bundle fund` for details" Great. Hope it will result in more OSS funding.

Petrik De Heus shared a new feature of Ruby language immutable value object:

Looks like Ruby will be getting an immutable value object called Data thanks to @zverok

Greg Molnar shared a new project about sharing password secretes securely via browser:

Do you ever need to send someone a password or API key in a secure manner? I have this free to use tool just for that: https://t.co/2ldbMqDCkx It never has access to the encryption key and it is also open-source!

Direct link to the project: https://secrets.spektrhq.com

Marco Roth shared that they want to add outlets to Stimulus:

 just opened a Pull Request for Stimulus to introduce the Outlets API. Outlets are very similar to Targets, with the exception that Outlets can be anywhere on the page and don't need to be within the scope of the controller element. #hotwire #stimulus

Read the PR here, and it might look like this:

Joe Masilotti launched a new project on RailsDevs: a celebration package when getting hired:

6 hours later and we are live on RailsDevs! What enabled such a fast turnaround? 1. Lots of existing View Components 2. Tailwind UI for the new designs 3. Hours documenting EXACTLY what the feature does

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

Related (but not Ruby specific)

Rose W shared a change of perspective when thinking about what does it mean that someone works at a company for less than 2 years:

I'm thinking this metric should be flipped.... who wants to work at a company that can't keep their employees longer than 2 years? Funny how all these founder types never talk about that...

Erwin Kroon shared advice for juniors to think about code context:

he quickest way from junior to senior is to think about code context in the broadest way, like: - Who will deal with this code too? - Why are we writing this? - How important is it for this code to be perfect? - What is the most likely thing to not work in this solution?

Michael Bolton shared about how to think about what testing is and its relations with various contexts. Read the entire thread, as it has some good perspectives about how to think about testing.

1) We say that we’re testing the product; and of course we are doing that to a degree. But what we’re mostly testing is a set of relationships between the product, its context, its users, and our beliefs about all of these. We must assume there could be errors anywhere in there.

Facundo Espinosa shared advice about how to level up and shared some recommendations for videos from graceful.dev:

fter you're a "senior" or you have +5 years in the industry, and you already face some problems. What is the best way to continue growing? Of course, if you want to continue in the technical field, you must continue facing different problems, but what other things can you do?

Julian Rubisch shared an excellent idea about how to improve the review on large PRs/MRs:

Articles and Videos

Communities

Pedro Schmitt shared they are starting a new podcast with Brazillian devs building with Ruby on Rails: Bullet Rails

Courses or Books

Timnan shared a course they created about Learning Ruby on Rails 7

Paweł Dąbrowski shared that their course Mastering CSV in Ruby is now free for everybody.

Pragmatic Programmers shared shared best sellers and at least two are for ruby on rails: Pragmatic Bookshelf: By Developers, For Developers

Something to read

Newsletters

Ruby Radar shared published a new issue with great content: Read it here → Ruby Radar #65 - Fly Away From Heroku

Joe Masilotti shared a new edition of Hotwire newsletter: Read it here → August 2022 edition

Petrik De Heus created a new issue of This Week in Rails Newsletter: Read it here → Finer-grained error pages and extended routes grepping

Articles

Nate Hopkins shared an older article about choosing to implement pluralization from the start: Preemptive Pluralization is (Probably) Not Evil

Shino Kouda shared an article wrote by them about handling exceptions in Ruby: How to handle Ruby exceptions

Greg Navis shared an article written by them about error handling API integrations: API Integrations: Client Classes and Error Handling

App Signal shared published an article with an introduction to Reactors: An Introduction to Ractors in Ruby

Paweł Dąbrowski shared an article they wrote about comparing objects: Identifying the objects in the Ruby way

Nathan Vaughn ⭐ shared an article they wrote about debugging ruby: Debugging Ruby in VSCode

🇺🇦 Deanin shared a new tutorial about Tailwind and CSS for Rails: Create A Tailwind CSS Project w/ Rails 7, Stimulus

Brandon Weaver shared an article they wrote about recursion in Ruby: Understanding Ruby – Recursion

Something to watch or listen

Videos

Drifting Ruby shared a new episode where they build a question and answer feature with Hotwire: Episode 363 - Hotwire Question and Answer Feature

Go Rails published a new episode about air quality monitor and reporting usage using MQTT. See it here → How to use the MQTT Protocol with Ruby (Example)

Konnor Rogers shared a short video showing a Venn Diagram with CSS frameworks/tools distributions. See it → here

Matt Swanson 😈 shared an old video (2012) by Ben Orenstein about refactoring ruby code: See it here → Aloha Ruby Conf 2012 Refactoring from Good to Great

Drifting Ruby shared a episode of a video log of This week in Rails: See it here → This Week in Rails Aug 26th, 2022

Audio & Podcasts

Stephan Hagemann hosted a second Twitter Space focused on gradual modularization: Listen to it here → Ruby@Scale. Packwerk. Gradual Modularization

Joël Quenneville shared shared a new episode of The Bike Shed with Steve Polito. Listen to it here → 351: Learning in Public

Ruby For All shared shared a new episode about how to contribute to open source: Listen to it here → How to Contribute to Open Source

Gems, Libraries and Updates

Edouard Chin shared a new release of the ci_runnner gem that now has support for Circle CI.

Thomas Countz shared a new gem that is a reimplementation of the scalar-value backpropagation library in Ruby: Check the code here here on Github:

his is an image of a 41 parameter multi-layer perceptron (MLP) trained for binary classification built with a scalar-based neural network (NN) framework called micrograd_rb[1]. And yes, it's written in Ruby! 😱 [CUE MUSIC! 🎶 💃 🎵 🕺 🧮 🤔 🪩]

Guillaume shared that the library Stimulus Components hit 500 stars on Github and has 1.3 million downloads on npm.

Sam Aaron shared an update of the SonicPI:

Just finished the first prototype of a new global time warp system for @Sonic_Pi. These are new controls to shift the timing of *all* scheduled events - internal synth triggers, external MIDI events & OSC messages. You can now live sync tempo and phase to an external rhythm.

Check SonicPI here: https://sonic-pi.net

Nate Berkopec shared a new Puma release v5.6.5 that includes bug fixing. Read release changelog here.

Mike Perham 🇺🇦 shared a new PR that will “allows different queues to be processed with different concurrencies” in Sidekiq.

Cj Avilla shared a new major SDK update for stripe-ruby.

Eric Berry 💜 🇺🇦 shared discovered a great library for adding PSQL specific features to Active Record: GeorgeKaraszi/ActiveRecordExtended. Here are some examples:

# the ANY expression is used for gather record's that have an Array column type that contain a single matchable value within its array. User.where.any(tags: 1) # the ALL expression is used for gather record's that have an Array column type that contains only a single and matchable element. User.where.all(tags: 1) # contains/1 method is used for finding any elements in an Array, JSONB, or HSTORE column type. User.where.contains(tags: [1, 4]) # The overlap/1 method will match an Array column type that contains any of the provided values within its column. User.where.overlap(tags: [1, 3, 8]) # The inet_contains method works by taking a column(inet type) that has a submask prepended to it. User.where.inet_contains(ip: "127.0.0.254") # any_of/1 simplifies the process of finding records that require multiple or conditions. User.where.any_of({ name: "Alice" }, { name: "Bob" }) # The #either_join/2 method is a base ActiveRecord querying method that will joins records based on a set of conditionally joinable tables. User.either_joins(:profile_l, :profile_r) #The #either_order/3 method is a base ActiveRecord querying method that will order a set of columns that may or may not exist for each record. User.either_order(:asc, profile_l: :left_turns, profile_r: :right_turns)

Bram Jetten shared annouced the release of Spina CMS v2.12.0. Read the changelog here

Kasper Timm Hansen shared he created a new gem conventional_extensions. Here is how it might looks like:

Eric Berry shared a gem TurboReady created by Nate Hopkins that extends Turbo Streams to allow control of the DOM:

turbo_stream .invoke("dispatchEvent", "turbo-ready:demo") # fires on window .invoke("document.dispatchEvent", "turbo-ready:demo") # fires on document .invoke("dispatchEvent", "turbo-ready:demo", selector: "#my-element") # fires on matching element(s) .invoke("dispatchEvent", {bubbles: true, detail: {...}}) # set event options .flush turbo_stream .invoke(:animate, [{opacity: 0}, {opacity: 1}], 2000, selector: "#example") .invoke(:dispatch_event, {detail: {converts_to_camel_case: true}}, selector: "#example") .flush

This was a long issue as there was a lot of great content that I discovered in Ruby community.

Please consider sharing this on social media or with your colleagues. I hope I added content for a wide range of developers (beginners to experts)

Reply

or to participate.