😄 Hi folks! There's a time and a place for April Fools' jokes — today is certainly the right time (someone might want to tell Volkswagen that) but this isn't the place, so fingers crossed there aren't any stories that catch me out this week... :-) Also, Jemma is a back with a tip of the week at the end of this issue, so be sure to enjoy that. __ Peter Cooper, editor | |
A Rubyist's Walk Along the C-side: Hello World!— The first in a coming eight part series that takes an accessible tour through the often thorny world of implementing a Ruby extension in C. This introductory post gives you the quickest way to creating a barebones extension. Peter Zhu |
An Interview with David Heinemeier Hansson— While it does cover Rails’ beginnings, there’s also thoughts on open source and DHH’s campaign against the big tech monopolies and the work on Basecamp’s latest project, the Hey.com email system. Ben Rometsch |
Rails 7 to Allow Run Queries on a Background Thread Pool— load_async will let ActiveRecord schedule queries to run asynchronously on a thread pool in a reasonably transparent way. This should open up some nice performance optimizations though potentially some bugs too. Swaathi Kakarla |
Quick Bits - The always popular Euruko European Ruby conference is back (online this year, due to COVID) and if you want to speak, their call for speakers is open until April 18.
- JRuby 9.2.17.0 has been released. It improves Sorbet support.
- RubyMine 2021.1 beta 4 is out and includes JetBrains' new Code with Me collaborative development feature — the final release is now just around the corner.
- @RubyCards is a Twitter account aiming to help you learn and remember Ruby concepts by way of flashcards.
|
Senior Backend Engineer— As part of adidas, we face the challenge of building a top-class backend infrastructure for our fitness apps every day. Runtastic |
Find Ruby Jobs with Hired— Take 5 minutes to build your free profile & start getting interviews for your next job. Companies on Hired are actively hiring right now. Hired |
Using CockroachDB with Rails— CockroachDB is a scalable, distributed SQL database that boasts being, if set up correctly, almost impossible to take down. Want to use it with Rails? Here’s how. Ali Ibrahim |
Building a Ruby Web App with and without Rails' Libraries— It’s actually an interesting challenge to try and build a Ruby webapp with as few libraries as possible. Sorry, no Sinatra allowed here.. what about going right with the socket library? 😆 This is a bit of a mixed bag, but you’ll probably pick up something. Maple Ong (Shopify) |
Which Is Fastest? ERB vs. HAML vs. Slim— Comparing the speed of different templating approaches took me back to the late 00’s a bit, but it’s nice to still see people running the numbers. They’re all pretty close nowadays. Diogo Souza |
Anything I Want With Sequel and Postgres— Janko demonstrates how the Sequel gem supports advanced features of Postgres, allowing them to bulk import CSV files into a partitioned set of tables that required some obscure PG knowledge. Janko Marohnić |
Timecop vs Rails TimeHelpers— Did you know that Rails has its own TimeHelpers a la Timecop? As Matt demonstrates, you probably won’t be replacing Timecop in your Rails app in the near future (pun intended). Matt Bearman |
Why Write Rails View Tests— Writing integration tests to cover the branches in your views can be time consuming so view tests provide an alternative, says the author. Nikola Đuza |
How I Code Without Service Objects— If you feel like service objects have grown beyond their utility, then Jason’s post will sing to you while showing you how he uses plain-old OOP to get things done. Jason Swett |
Marcel 1.0: Find the MIME Type of Files from Their Contents and/or Filename— If this project sounds familiar, it’s because it was at the center of the MimeMagic/GPL story last week – it now uses a Apache-licensed dataset instead and has dropped the MimeMagic dependency. It’s used by Rails but you can use it just as well from any Ruby code of your own for detecting filetypes. Ruby on Rails Project |
💡 Tip of the Week Effective use of Array#bsearch Binary search is a commonly taught algorithm for finding an element of a sorted array in O(log(n)) time where n is the size of the array. In the context of an array, it takes a sorted array, makes a comparison to a middle element, and then based on that comparison recurses in either the right or left 'half' of the array until it either finds an element where a comparison returns true, or has no more elements to look over. Ruby has an Array#bsearch method to return an element selected by a binary search. Its functionality can be a little tricky to grasp at first. Take a look at this example: |
["tip", "of", "the", "week"].sort.bsearch { _1 == "of" }
=> nil
|
Initially, this result may be counterintuitive. Let's dig into why this happens, so we can effectively use Array#bsearch going forward! There are assumptions Array#bsearch makes about the array it's searching, and the condition on which it's searching: - The array is sorted.
- There are two types of comparisons we can make with the condition against elements of the array:
- If boolean: all
false evaluations precede all true evaluations. - If integer: all positive evaluations precede all zero evaluations which precede all negative evaluations.
It doesn't check these assumptions, however, and can't guarantee results when these assumptions aren't met. So if we look again at our example from above, we see it meets the first assumption: the array is sorted. But on the second assumption, it has boolean results which do not all evaluate to false before true . Let's take a closer look: |
sorted_array = ["tip", "of", "the", "week"].sort
=> ["of", "the", "tip", "week"]
# This violates the second assumption because `false`
# evaluations don't always precede `true` evaluations
sorted_array.map { _1 == "of" }
=> [true, false, false, false]
# There are a few options for how we could fix this:
# If we reverse the array, it'll work
sorted_array.reverse.map { _1 == "of" }
=> [false, false, false, true]
# Tada!
sorted_array.reverse.bsearch { _1 == "of" }
=> "of"
# Or we can use the <=> operator which returns 1,0,-1
# Note we need "of" <=> _1 to hold the ordering property we seek
sorted_array.map { "of" <=> _1 }
=> [0, -1, -1, -1]
# Tada!
sorted_array.bsearch { "of" <=> _1 }
=> "of"
|
And we can see that as long as both of the assumptions hold, we can rely on Array#bsearch to efficiently and effectively search an array. An added bonus, if we're just looking for the index of an element selected by binary search, we can use Array#bsearch_index with the same block as above: |
sorted_array.bsearch_index { "of" <=> _1 }
=> 0
|
|
|