RSSAmplifier

Blog

Benito Serna

Tips and articles for Ruby on Rails developers

bhserna.comRSS feed ↗90 posts

Latest posts

You can ask your coding agent for a selector to compare UI options

One of the ways I have been using coding agents these days is to prototype small UI changes in an existing project. I use them as a tool to explore. In this usage mode, I am not interested in the code. I am interested in how the options look. My objective is to extract ideas from the LLM, choose what I want, and later work on the real change in a different chat. Ask for a selector to compare One…

Make a method a recurring task with solid queue

This week I made a refactor to remove a job ( ActiveJob::Base ) that was used only in recurring.yml , and call a class method directly instead. Sometimes it is ok to have a job, but sometimes using the method can help you write a little less code. And these days it is just a prompt away. The example I was working on a follow-up flow for users who had not updated their profile in over a year. The…

MdRecord: File-backed models for Rails

I just released md_record , a Ruby gem that provides an ActiveRecord-like interface for markdown files with YAML frontmatter. Why? I needed a simple way to manage content like blog posts and guides in my Rails apps without a database. I wanted something that felt like ActiveRecord but worked with markdown files. Installation gem "md_record" Basic Usage Create a model that inherits from…

Fixing a bug in my lateral joins queries with rails

I have some posts about using lateral joins in rails to fetch the “top N” of each record. Some months ago Ben Sheldon helped me see a performance problem on the queries that I was using. Here I try to explain the problem, the solution proposed by him, and also an introduction about a tool he published to build this kind of “top N” queries using lateral joins . The problem…

Simple Searchable module for searching with Rails and SQLite's LIKE

Yesterday, I found myself struggling with “litesearch” , and in my frustration, I decided to create a simple “Searchable” module to perform a “LIKE” search but with a cleaner interface/API. If you’re looking for a straightforward way to implement a search feature in your application using “LIKE”, this post might be helpful to you.…

Copy shoes.rb and use stacks and flows to build layouts

I was reading about shoes.rb and, while scanning the book and walkthrough, I discovered a pattern that caught my attention for its power and simplicity. The combination of “stacks” and “flows” allows you to build complex layouts, like the following example in Ruby: Shoes . app do background "#EFC" border ( "#BE8" , strokewidth: 6 ) stack ( margin: 12 ) do para "Enter your…

Fix n+1 queries by caching computed values

N+1 queries are not always a problem, but I have seen that most of the n+1 queries that are really a problem are when we need to fetch data to compute something. Here I will try to share some examples of posible expensive computations candidates to be cached and some patterns that you could use to save different kind of values. Some examples of possible expensive computations I think the most…

Truncate in the middle with truncate rails helper

Imagine that you want to truncate a filename, but you want to keep showing the extension of the file. Like “A big file name that…awesome.pdf”. How would you do it? The omission parameter With the :omission string the last characters will be replaced (defaults to “…”) for a total length not exceeding length : string = "And they found that many people were sleeping better." string . truncate ( 25 ,…

A form with two buttons with formation and formmethod

Imagine that you are building a custom CMS. Within the form to edit an Article , you need to have two buttons: a normal “Save” button and a new “Save and publish” button. And maybe, additionally, you will need a third button to delete the article. To achieve this, you can use the formaction and formmethod attributes. Changing the action with formaction To add the…

What to do when you need a button_to within a form in Rails

Imagine that you have a form to update a record (let’s say a product record) and inside the form, you are showing a list of images, and each image needs a button to remove it. You tried to use button_to but it doesn’t work because in html you can have form within a form. What do you do? You can use the “form” attribute You can use a button tag and define its form attribute . The value…

Simple image manager with active storage

If you want to add images to a record but you don’t want to use a JavaScript plugin or write any custom JavaScript, you can use a regular file field, Active Storage, and vanilla Rails. If you want to be able to: Attach many images on create Keep adding many images on every update Display the images in a gallery Be able to remove the images one by one Here is a tutorial to help you accomplish…

Add many attachments without deleting previous ones using ActiveStorage

If you want to add many attachments to a record using just a file field, but you don&rsquo;t want to remove the previous images from the record on every update, like in the following code: <%= form_with ( model: product ) do | form | %> <%= form . label :images %> <%= form . file_field :images , multiple: true %> <%= form . submit %> <% end %> And instead, on every update you want to add the new…

Use after_touch to avoid to handle race conditions saving computed values

When saving computed values in the database in your rails app, you must be aware that is possible to find unexpected errors in the result thanks to race conditions. I have already shared an exercise to help you get more sensitivity about when an implementation can save a wrong value thanks to race conditions. Here I want to share one tip to help you avoid save the wrong value due race conditions…

Use with_lock to handle race conditions saving computed values

When saving computed values in the database in your rails app, you must be aware that is possible to find unexpected errors in the result thanks to race conditions. I have already shared an exercise to help you get more sensitivity about when an implementation can save a wrong value thanks to race conditions. Here I want to share one tip to help you avoid save the wrong value due race conditions…

Pick a safe previous date to avoid race conditions saving computed values

When saving computed values in the database in your rails app, you must be aware that is possible to find unexpected errors in the result thanks to race conditions. I have already shared an exercise to help you get more sensitivity about when an implementation can save a wrong value thanks to race conditions. Here I want to share one tip you can try to avoid race conditions when saving a computed…

Touch + fragment caching to avoid race conditions saving computed values

When saving computed values in the database in your rails app, you must be aware that is possible to find unexpected errors in the result due to race conditions. I have already shared an exercise to help you get more sensitivity about when an implementation can save a wrong value due to race conditions. Here I want to share one tip you can try to avoid race conditions when saving a computed value.…

Will it save the wrong value?

I have already written about how you should be aware about race conditions when saving a computed value , because you could save a wrong value. Here I want to share with you an exercise to help you (and me 😅) get more sensitivity about when an implementation can save a wrong value thanks to race conditions. Your task I will show you some excercises with different ways/methods to calculate the…

Saving incorrect computed values thanks to race conditions

When saving computed values in the database in your rails app, you must be aware that is possible to find unexpected errors in the result thanks to race conditions. Here I want to help you visualize how race conditions can make you save incorrect values even when your calculation is correct. I will show you how it can happen with different ways of saving the same value and show you a tool that you…

Examples to explore possible race conditions when caching custom computed values in Rails

In Rails, sometimes you will need to save counts or custom computed values, where the default counter cache will not be enough. Maybe you want to… Update a counter cache when a value change and not only when the association is created or deleted. Have a counter cache for complex “has many through” associations. Keep a count for a scope of the association, like just the “positive reactions”, or the…

Broadcast multiple actions with broadcast_render

Imagine that you are creating a record (let’s say a tweet), and on creation, you want to add the tweet to the page and also update the tweets count in the page&hellip; But you want to update the content, not just for the current user, but for all the users in the page, you want to broadcast the changes. How would you do it? Well, here I want to show you how you can use broadcast_render or its…

Building a dynamic data grid with search and filters using rails, hotwire and ransack

Do you want to build powerful admin interfaces with little code, but you are not sure if you want to jump into a full admin solution like Active Admin, Administrate or Avo? Here I want to show you an alternative! A step by step guide to build a dynamic data grid with search and filters for your admin interfaces, using rails, the ransack gem and hotwire. What are you going to build? You are goint…

Fetching the top n per group with window functions

Have you ever needed to get the most recent N posts for each user in rails, but didn&rsquo;t know how to do it without using map? Or maybe something similar like: The first or last X comments for each post The first or last Y payments for each customer The first or last Z reviews for each customer Sometimes could be ok to just fetch all elements and filter with ruby, but sometimes it is not…

Fetching the top n per group with a lateral join with rails

Have you ever needed to get the most recent N posts for each user in rails, but didn&rsquo;t know how to do it? Or maybe something similar like: The first or last X comments for each post The first or last Y payments for each customer The first or last Z reviews for each customer Sometimes it could be ok to just fetch all elements and filter with ruby, but sometimes it is not possible. Also it can…

Active Record Playground Runner Introduction

Have you ever wanted to just create an active record example to someone in your team without thinking in the database setup? Or maybe send two different models designs with some examples to see the difference, but the setup what just to difficult? Or like me, create a bunch of examples to teach an Active Record concept? If you have had one of this problems, maybe this tool can help you. A tool to…

Mistakes we make with counts in rails

Display the count of an association could look like a simple task, but in some cases it can give you real troubles. It is very easy to end with n+1 queries. Counting with ruby sometimes can be ok, but sometimes could be impossible. Counting via sql is usually ok, but sometimes could be slow or maybe unnecessary. Here I will share five mistakes with counts I have made and seen. It could help you to…

A tool and examples to help you implement the first or last per record in rails with one query

Have you ever needed to get the most recent post for each user in rails, but didn&rsquo;t know how to do it without using map? Or maybe something similar, like: The first or last comment for each post The first or last payment for each customer The first or last review for each customer Here is an example of a simple way to do it when you can use the id column to sort the records. class Post <…

Solve n+1 queries and slow counts with counter caches

Sometimes calculating the count of a collection on every page render, even in SQL, is not the best option. Imagine that you need to render a post, with its count of likes and comments, but the post has thousands of likes and comments. That would be slow. One solution is to save the count of those comments and likes in the record, and when you need to render the post, instead of counting the…

4 things you can try before using a counter cache in rails

Maybe you have heard about the counter cache feature. A counter cache makes finding the number of belonging objects more efficient by keeping a column with the count. Rails makes it easy to implement it, but is not free. Sometimes it may be better not to use it. Here are four things you could try before or instead of using a counter cache, without introuducing n+1 queries. 1. If you don’t need the…

When do you need a counter cache in rails?

Maybe you have heard about the counter cache feature. It makes finding the number of belonging objects more efficient, by keeping a column with the count. But&hellip; When should you use it? Do you need to have a counter cache for every association count in your app? Here are three situations when you could need a counter cache. When you have slow counts in your views Even if you do the count via…

Use dom_id helper on capybara with rspec and rails

At least for me it is very common to use the within method in capybara, to match the dom_id output. And is very common to do it with code like "#user_#{user.id}" or #project_#{project.id} . In this way: within "#user_ #{ user . id } " do expect ( page ). to have_text user . name end # or... within "#project_ #{ project . id } " do expect ( page ). to have_text project . name end If you do it one…

How to preload counts in a list with ActiveRecord

Imagine that you need to put the number of likes for each post in a list, but avoiding n+1 queries. posts . each do | post | post . likes . count # n+1 queries end One way to avoid n+1 queries here, is to preload the association and the count the records in ruby. But if the association has too many records, you could introduce a performance problem . posts . preload ( :likes ). each do | post |…

Difference between count, length and size in an association with ActiveRecord

With Rails/ActiveRecord, you can count the records in an association using three methods .count , .length , .size . As a rails newbie, when you first discover this, it can be confusing&hellip; Why do we need three methods? Is there any advantage to using one method over the other? How are they different? Here are 6 characteristics of this three methods that you should know. They will help you…

Active record playground, for rails developers that want an easy way to practice with active record in isolation

I want to share with you my “Active record playground template”. It is a template that you could use as a guide or by cloning the repo and following the instructions in the README if you want to play with some Active Record models in isolation and without creating a full rails app. I was repeating my self over and over I was setting up the structure of this template from scratch over and over…

Specific preloading with scoped associations

It is very common the need to preload an association then filter that association and then use the filtered collection. For example, imagine that you need to render a list of posts with just its &ldquo;popular&rdquo; comments, where &ldquo;popular&rdquo; means &ldquo;with a likes_count greater than or equals to X&rdquo;. Approach without scoped association So you can define Comment#popular? like…

How to use react with hotwire?

I have seen that some people think that you have to forget about Rails and Hotwire, if you want to use React or another Javascript framework to build a Single Page Aplication, but this idea is not true. You can use Rails and Hotwire as the base of your app, and plug your React app to be shown where is needed. In this way you can use both frameworks, and pick the one that you think that will help…

Should you split your rails app into backend and frontend?

When you start a new app or when things start to get complicated on the frontend side of your rails app, I think that it is normal to start thinking if you should split the app into a rails backend and a frontend with react, vue, or other javascript framework. I am a rails developer that normally prefers the “majestic monolith”, and I will normally recommend to not doing it, and even I sometimes…

How the turbo_frame_tag helper transforms an object to an html id?

If you are new with rails and hotwire, it could be useful to know that you can pass an object to the turbo_frame_tag and it will use a string representation of that object as an id. For example if you have a Product record, you can do: product = Product . find ( 1 ) turbo_frame_tag ( product ) And it will return: <turbo-frame id= "product_1" > < /turbo_frame> And if you do product = Product . new…

Styler and tachyons examples

I built a tool to comples css classes like this&hellip; styles = Styler . new do style : default , [ "pa3" , "white" , "bg_blue" ] style : danger , [ default - "bg_blue" , "bg_red" ] end styles . default . to_s # => "pa3 white bg_blue" styles . danger . to_s # => "pa3 white bg_red" &hellip; because I think that, although css is awesome (really!), I think that it misses is the ability to compose…

Inline CRUD with rails and hotwire

This is a guide to help you build &ldquo;inline CRUDs&rdquo; with rails and hotwire, where you create and edit records in the same page. Instead of a &ldquo;new product&rdquo; page it shows the form in the same page Instead of an &ldquo;edit product&rdquo; page it shows the form on the same page by replacing the product item. Like in the next video&hellip; The example app You can find the code of…

Remote modals with rails, hotwire and bootstrap

Here I want to show you how you can build “remote modals” (modals where the content is requested to the server), submit forms embedded in them and handle errors, with rails, hotwire and bootstrap. Example app I will show you how to build is something like this&hellip; Where you can&hellip; Click a link that requests content to the server and then shown inside a modal. Submit a form and display the…

Dynamic filters with rails and hotwire

A very common task as a Rails developer is to let the user filter a list with a combination of search fields and selects. Here I want to show you one way of doing it using turbo and stimulus.js from hotwire, with an example app. Play with the code The code of the app is on github.com/bhserna/dynamic filters hotwire , you can clone it and play with it. What does the app do? The app displays a…

Styler, a tool to compose css classes with ruby

One of the things that I want from css is to have to possibility to compose already defined styles, to define new ones&hellip; If you try to write &ldquo;Semantic CSS&rdquo;, you will find a hard time trying to avoid the repetition on things that look the same but are different things, like when you want to render a &ldquo;card&rdquo; for the an author and then for an article. You can create…

Capybara cheatsheet as pdf

If you work with capybara and you are constantly searching for capybara helpers, maybe to have this little cheatsheet at hand could work for you. I already have share it on as a blog post , but now I want to share it with you as a pdf.

Preloading associations cheatsheet

Maybe you are already familiar with includes or preload , but you know that a lot of the time you will need more than just preload(:comments) . I have already share with you a guide for preloading associations &hellip; It starts with the basics, with just a regular has_many , preload or includes , and build from this to then show you things like… How to preload nested associations How to define…

How to detect n+1 queries by watching the logs

Although there are tools that can help you detect n+1 queries before they hit production, I think that is good to be able to identify n+1 queries directly by watching your logs&hellip; Not all the tools will tell you exactly that you have n+1 queries, and sometimes the ones that will tell you, can give you false negatives. Also I think that, although there is hardly no training anywhere for this…

How can I determine if my n+1 queries fix can hurt the performance?

Maybe you already know that &ldquo;fixing&rdquo; an n+1 queries problem can hurt the performance of your app&hellip; But even if you already know it and also understand how it can happen, it could not be obvious how to know if this is will happen with your fix. Some things that you can try are to&hellip; Compare the requests time Compare the queries load time Compare the produced allocations…

Joins does not preload

When you are working with SQL, to use information from other tables you would use a JOIN&hellip; And if you are just starting to learn ActiveRecord comming from SQL, you could think that by using the joins method you will be able to later use the data from the associations without doing a new query. And this is true and false at the same time&hellip; It will let you use the association on the…

Example app to understand why some times fixing some n+1 queries can hurt performance

I want to share with you an example application to help you visualize why &ldquo;fixing&rdquo; an n+1 queries problem, can hurt the performance of your application if you preload assocations with too many records. It simulates the index page of a blog application. And appart from the rack-mini-profiler gem, it shows the logs in the page to help you visualize easily the queries, request time and…

Why some people say that fixing some n+1 queries could hurt performance?

Sometimes people say that &ldquo;fixing&rdquo; some n+1 queries could hurt performance&hellip; Maybe this phrase can be confusing, because if you have not been exposed to a lot of n+1 queries problems, it could be hard to imagine how it can be possible. And also is probably contrary to what you have always heard&hellip;. That n+1 queries are bad. You can preload too much data Although a lot of the…

Preload object on the guide for preloading associations

I want to tell you that I have added a new section to the guide for preloading associations in rails , to introduce you to something I call &ldquo;Preload objects&rdquo; that will help you build complex preloads for those cases when you can&rsquo;t find a way to do what you need to do, with the standard rails mechanisms. Visit the new section You can visit the new section on Guide for preloading…