Rails Tricks


10 Oct

Rack Attack 404 errors and custom response message - Rails Tricks Issue 20

This week I will show you another Rack Attack trick.

But before I get to that, I’d like to let you know that my book is finally done and if you want to learn about how to avoid security issues during code review, you should read it: Secure code review for Rails Developers .

Read more

26 Sep

Rails form_with

This week I want to tell you about the form_with Rails helper. It was introduced in Rails 5.1, and the goal of this helper was to unify the form_for and the form_tag helpers. form_for requires a model instance or a scope and puts the attributes into a hash, so usually when you needed a form in the past where you didn’t want to put them scoped into a hash, you used form_tag.

Read more

05 Sep

Throttling Rails logins with Rack Attack


This week, I will show you how to rate-limit your authentication endpoints with Rack::Attack.

Rack::Attack is a middleware for blocking or throttling requests based on rules. It uses the configured cache store of Rails to store the necessary data, but a separate data store can be configured too.

Read more

29 Aug

Dependent Dropdowns with Hotwire - Rails Tricks Issue 17

This week I will show you how to make dependent dropdowns with Hotwire!
I will use a toy app as an example. This app will have a page where addresses can be created. The address will consist of a country, a state, a city, and a postcode. Except for the postcode, we will have a list of options coming from the database and when the user selects the country, we load the states for the selected option. When the user selects the state we will load the cities in that state. Let’s start by generating a Rails app, the necessary models and a scaffold for the address.

Read more

22 Aug

Active Record upsert - Tricks Issue 16

This week, I will show you how to make data imports blazing fast with Active Record.

I recently built a subscriber import functionality into the newsletter tool I am working on. The requirements were the following:

  • a CSV file is uploaded
  • then on the next screen the columns of the file can be mapped to the importable attributes
  • a subscriber is created unless it already exists on the list

This second part could have a few naive implementation with a query to check if a matching record already exists, or by doing a find_or_create_by with each row of the import, but luckily Active Record supports upsert and even have an upsert_all method.

What upsert does in SQL, is it either updates a record if found or creates a new one, and since it happens on the database level, it is way more performant than doing it in Ruby.

The Active Record method takes the attributes as the first parameter and a list of optional parameters:

  • on_duplicate: a SQL update sentence that will be used on conflict. By default it is update
  • update_only: a list of column names to update on conflict. nil by default which means it updates all columns provided in the query.
  • returning: an array of attributes to return for all successfully returned records. By default it returns the primary key. This works in PostgreSQL only.
  • unique_by: by default, rows are considered to be unique based on every unique index on the table, but in PostgreSQL and SQLite, you can speficy the attributes or an index name you want to use. If you provide the attribute or attributes, you have to have a unique index on them.
  • record_timestamps: whether to record the timestamps on the table or not. This uses the model’s record_timestamps by default.

Now let’s see an actual example. Let’s imagine we are receiving a list of subscribers in the params and we want to upsert them:

carbon (10).png 363 KB

The above code will be pretty performant.

That’s it for this week!