πŸ”– Issue #10 - 12-18 September 2022

The one about RSpec

Hello,

I’m @lucianghinda, the curator of this newsletter. 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 😊.

If you like it and want to help me reach a wider audience, I would kindly ask you to leave some feedback/short written testimonial that I can display on the About page.

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.

If you have any feedback or ideas about this newsletter, please reach out on Twitter or via email at [email protected]

πŸ‘‰ Thiago Massa shared about how to do a proper Ruby memoization in Ruby

Memoization in Ruby can be very tricky. πŸ€” Yesterday I've shared the wrong ❌ example with the Ruby idiom for memoization. @mhenrixon pointed out that if the response is nil, it won't memoize and subsequent calls will make the HTTP request again. Did you know that?πŸ‘‡

πŸ‘‰ Shino Kouda shared an example of how to use enum in Rails with integer type and this generated a good discussion about possible issues generated by this approach and how to overpass them:

πŸ‘‰ Josh Cheek shared that when using Postgres, one can define a Postgres Enum type. Here is the gist he created that works by adding the enum type with raw SQL. If you want to do this with Rails 7 it added support for this enum type:

If you want to add a new enum, you will need to write raw SQL with ALTER TYPE. See Rails 7 guides for enumerated types

About using integers for enums, here is a good discussion explaining the pros and cons:

Agreed. + enums as integers is not a good way to go. Once the system might change requirements to delete existing status or split it into two. Data migration is hard in this case. Also, it's hard for analysing data directly in DB as you need to keep in mind this match. Enums as integers in the database is a trade off. It can save a lot of memory and give you better performance in large tables. But it’s usually not necessary. LiteralEnums can be integers or strings. But they’re strings by default.

Joel Drapper then proposed using a gem he wrote:

Example of usage for gem literal_enums-rails

πŸ‘‰ Kirill Shevchenko shared  an example of encoding and decoding JSON with gRPC:

πŸ‘‰ Stefan Vermaas shared how to display flash messages with Turbo in Rails:

Played around today with some ideas to display flash messages automatically for Turbo requests in Rails. I believe this it's a decent way to show flash messages as it requires minimal effort to use them. Just use `set_flash_message` and you're good to go.

πŸ‘‰ Nate Berkopec shared how to profile an entire Rails boot sequence:

Is there actually a good way to profile the _entirety_ of a Rails boot sequence? I threw my profiler around the Rackup file (config-ru) today and it only caught like 25% of actual wall clock time I was seeing w/rails runner.

There is a good discussion there about various ways to achieve that. While replying to the thread, Jean Boussier did a PR to stackprof  gem to make this happen quickly with the following command:

πŸ‘‰ Shino Kouda shared code sample about parsing a JSON and instantiating objects using a feature of JSON.parse:

Nice way to parse JSON in Ruby, using a poorly documented object_class option (found on SO). Far easier to dig then.

Just note that using OpenStruct will affect your performance. Here is what the official Ruby documentation says about OpenStruct:

πŸ‘‰ Tim Riley shared a thread about making Hanami faster:

As we near the @hanamirb 2.0 release, we’ve been running some benchmarks to make sure the house is in order. We learnt that hanami-controller wasn’t as memory efficient as we’d hoped! A big part of it seemed to be with dry-configurable.

πŸ‘‰ Kirill Shevchenko shared a code sample to show how to open IRB console within the current scope:

IRB supports binding.irb feature, which allows you to open the IRB console within the current scope. This can be useful when you want to quickly play around with some snippets without even installing debug gems. #ruby

πŸ‘‰ Benito Serna shared a sample code about polymorphic rendering with ActiveModel and ActionView:

You can build powerful polymorphic rendering with ActiveModel and ActionView. #ruby #rails #rubyonrails In this example we have an inputs array with different kind of input objects, but as all of them are ActiveModels all of them now to how to be rendered.

πŸ‘‰ Justin Searls shared his opinion about why he recommends people to avoid RSpec.

Top of mind things I think are problematic about Spec (literally just typing as I think of stuff): 1. Its implementation is inscrutably complex, so if you have an issue, inspecting the source is not productive solution 2. Its DSL defeats most attempts at automated introspection (Ctags, lang server, etc.) which means navigating the code is very difficult compared to tests of classes/methods 3. The DSL also allows for combinatorial explosions in runtime performance cost via incredibly terse and tidy APIs, most notably via shared_example_groups 4. The DSL provides numerous ways to structure tests and everyone has a different opinion (subject is great, subject is evil, let is good/bad, nesting is good/bad), leading to terrific inconsistency on projects as individuals express their own favorite way on the specs they write unless you dictate a style in a really authoritarian way 5. The rspec-rails tie-ins are often years late to be updated to reflect changes in Rails itself, and when a failure occurs in that gem's indirection, it is very very difficult to workaround as a user. It adds another point of failure for little marginal value 6. Generating specs by looping over data structures is incredibly easy and convenient and often leads to an entire category of bugs (often pointed out by Jim Weirich in his talks) where you might oop over a data structure to generate 100 specs and unwittingly realize that the final test case was actually generated and run 100 times 7. The above is caused by the fact that It's two-pass system: first the specs are loaded and a tree of example groups is constructed dynamically, then a second pass in which the tests are executed. Because it's a DSL and not class/method, it's very easy for developers to fail to grok that there are two runtime contexts and they will often be confused when describe or it or expect behaves differently based on which method the current block is being passed to 8. People who advocate RSpec for the real Dan North BDD purpose it was created will very often tout its utility as a feature behavior elucidation tool, but in practice 99.9% of specs are just symmetric unit and integration tests of code. This creates a lot of tension, as the thing that RSpec is advertised as ("decouple your specs from the implementation class, describe the feature's outcomes instead!") often exacerbates the problem of unclear indirection (when I want to update class X, which spec do I need to drive that change through?). It's just another opportunity for ideological conflict to result in inconsistency and confusion in the test suite I have a lot more but didn't want to spend more than 10 minutes dunking on Spec today

This generated a lot of responses. You should read the entire thread and also click the quoted tweets. Here is just a summary, but please read those two links to make up your own conclusion:

πŸ‘‰ Kirill Shevchenko shared a code sample showing curry for procs

Ruby has a curry method for procs. This allows partially applied procs to be returned when they are called with fewer arguments than required. #ruby

πŸ‘‰ Thiago Massa shared a code sample with .() shorthand syntax for .call:

Joel Drapper also added the double dot notation works, and it does the same:

πŸ‘‰ Nate Hopkins shared a script to work with libraries that are incompatible with Turbo Drive as they assume that the document head is loaded and parsed on every page visit:

Here's a hack/fix that you can use to force such libs to work with Turbo Drive. It's inefficient from a compute perspective but allows you to use Turbo Drive with incompatible libs. Also for anyone unaware, Turbo Drive provides UX similar to SPAs with minimal developer effort.

πŸ‘‰ Dave Paola shared that they launched a new project - a development agency with the mission to be the place where Junior Ruby on Rails developers start their careers:

πŸ‘‰ Meghan Gutshall asked a question about how to explain a Ruby class:

Here are some replies, but you can find more in the thread:

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

Related (but not Ruby specific)

Celso de SΓ‘ asked about what it means to be a mid-level Ruby developer. Here are some of the answers to this question:

My definition of a mid-level developer is (short version): An engineer who can be trusted to work on a project without much guidance. And who generally delivers good results in expected time frames | (source: @spickerman) Difference to a senior developer: Senior need to be able to plan and lead complex projects. Additionally, they need to be able to manage stakeholders, do hiring interviews, and mentor and train other developers | (source: @spickerman) Ultimately, it doesn't matter. We need to understand what the customer wants, 1st. & understand how we ensure everything is customer driven. That should be a junior requirement imo The fullstack being customer <-> code :) Then we need to learn to collaborate with other devs | (source: @alterisian)

I think you should also take a look at β€œgeekery skillset” proposed by GeePaw Hill:

I propose that there are four (rough and approximate) evolutions in geekery skillset: 1) Thinking in syntax. 2) Thinking in code. 3) Thinking in <paradigm>. 4) Thinking in change.

Joe Masilotti πŸ“— shared a nice trick to skip running Github Actions:

TIL that you can skip running your GitHub Actions by adding [skip ci] to a commit message. [skipci] (no space), however, does NOT skip CI.

Read the documentation for this here.

Tobias Petry.Sql shared a database tip about making the index invisible:

Database Tip Deleting an unused index is still a risky operation: If you are wrong (and it is still needed) the database will become slow. Before deleting it, you can make the index invisible first and make it visible again instantly if you still need it.

Brandon Weaver shared about seniority and self-marketing:

I'll need to write this one up later, but had an interesting conversation and idea today around self-marketing. At very senior levels it's absolutely mandatory to do your job well, but what does that look like? Well it turns out that part is far more complicated.

You can read the full thread here or the article Brandon wrote expanding this on this blog: Beyond Senior – The Peacock, the Hermit, and the Counsel

Articles and Videos

Courses or Books or Communities

Brandon Weaver shared launched a new community focused on learning Ruby. The discord invitation is this one, and the main website is rubylearning.dev. This week we already started working as a group on the book Rebuilding Rails by Noah Gibbs.

Kasper Timm Hansen shared an update about his course called Product Focused Ruby.

Something to read

Soutaro Matsumoto shared their presentation slides from RubyKaigi about how to use Ruby types. See the slides here.

Newsletters

Andrew Mason shared a new issue of The Ruby Radar. Read 68: Hack the Planet! 

David Colby shared a new issue of Hotwiring Rails. Read Hotwiring Rails - September 2022

Awesome Ruby Newsletter released their 330 newsletter. Read 330 Awesome Ruby Newsletter

RubyWeekly published its 620 newsletter. Read Ruby Weekly #620

Articles

Something to watch πŸŽ₯ or listen 🎧

Videos

πŸŽ₯ Drifting Ruby shared a new episode of the video newsletter for This week in rails. Watch β†’ This Week in Rails Sept 17th, 2022

πŸŽ₯ Joel Drapper shared a session where he started converting a large ERB to Phlex and then discovered and fixed a bug. Watch β†’ Just trying out

πŸŽ₯ The Rubber Duck Dev Show shared a new episode with Brittany Martin and Josh Gaastra about Engineering Managers and Product Managers. Watch β†’ EM vs PM! with Brittany and Josh

πŸŽ₯ Avo shared a video doing a walkthrough of the new features they released. Watch β†’ Avo Admin 2.15 for Ruby on Rails

Audio & Podcasts

🎧 Jason Sweet launched a new episode of the Code with Jason podcast where he invited Adrian Marin to talk about Avo and how it is to make tools for developers. Listen β†’ 161 - Adrian Marin, Founder of Avo Admin

🎧 JoΓ«l Quenneville shared a new episode of The Bike Shed with Sara Jackson where they talk about The History of Computing. Listen β†’ 354: The History of Computing

🎧 Ruby For All shared a new episode about Bridgetown. Listen β†’ Episode 8: What is Bridgetown. If you like this you should consider joining the Jared White Discord community The Spicy Web

🎧 Remote Ruby shared a new episode where they invited Joel Drapper to talk about Phlex: Listen β†’ Phlexing with Joel Drapper

Gems, Libraries, and Updates

🧰 Avo shared they released a new version with a lot of features. See the changelog

🧰 Postmodern shared they added ruby 3.2.0 preview 2 to ruby install. See the changelog here. Thus now, the following command should work:

Added ruby-3.2.0-preview2 to ruby-versions, so ruby-install should now be able to safely download and install it. #ruby $ ruby-install --latest ruby-3.2.0-preview2

🧰 JRuby Dev Team shared they released version 9.3.8.0 which includes β€œa CVE fix for the Psych YAML library, support for lightweight fibers using Java 19 virtual threads, and a bunch of compatibility and bug fixes”. See changelog

🧰 Marco Roth shared that Turbo 7.2 rc1 was released. See the changelog

🧰 Postmodern shared a gem named sord that will transform YARDoc into o Sorbet definitions.

🧰 Mike Perham shared they released Sidekiq Pro 5.5.4 β€œfixes a batch race condition which could cause the batch pending count to read -1”. See changelog

🧰 Rubygems News shared an update for a library called Spy which is a new way of mocking:

🧰 Nate Berkopec shared a new library fixture_factory that helps to work with fixtures like factories. Here is a code sample:

🧰 Andrew Mason shared a new library they discovered Capybara Test Helpers. Here is what it looks like:

Please consider sharing this on social media or with your colleagues:

If you have any feedback or ideas about this newsletter, please reach out on Twitter or via email at [email protected]

Reply

or to participate.