Today I Learned

A Hashrocket project

Ready to join Hashrocket? Find Openings here and apply today.

215 posts about #rails

Nested table querying with ActiveRecord

Sometimes you need to query a joined table in ActiveRecord. This can be easily done via the hash syntax:

User.where(greetings: {text: "HOWDY"}).to_sql

=> SELECT "users".* FROM "users" WHERE ("greetings"."text" = 'HOWDY')

Note: the key here (greetings) is pluralized because we’re referencing a table name and not a potential relationship that ActiveRecord knows about.

Note: I’ve ommited a join to the greetings table that would have this query make sense

Cool: so we can do that but there’s even an alternative way to handle this using dot notation

User.where("greetings.text": "HOWDY"}).to_sql

=> SELECT "users".* FROM "users" WHERE ("greetings"."text" = 'HOWDY')

Under the hood, ActiveRecord will convert dots from the string key and interpret them as table and column names.

Start multiple processes in dev env with bin/dev

Rails comes with bin/dev to start multiple processes from a Procfile.dev

# Procfile.dev
web: bin/rails server -p 3000
css: bin/rails tailwindcss:watch
jobs: bin/good_job
firebase: firebase emulators:start --import=./emulator-data

So that you can run everything at once:

$ bin/dev
08:36:10 web.1  | started with pid 40038
08:36:10 css.1  | started with pid 40039
08:36:10 firebase.1 | started with pid 40040
08:36:11 firebase.1 | i  emulators: Starting emulators: auth, firestore, storage
08:36:11 firebase.1 | i  firestore: Firestore Emulator logging to firestore-debug.log
08:36:11 web.1  | => Booting Puma
08:36:11 web.1  | => Rails 7.0.2.3 application starting in development
08:36:11 web.1  | => Run `bin/rails server --help` for more startup options
08:36:12 web.1  | Puma starting in single mode...
08:36:12 web.1  | * Puma version: 5.6.4 (ruby 3.1.2-p20) ("Birdie's Version")
08:36:12 web.1  | *  Min threads: 5
08:36:12 web.1  | *  Max threads: 5
08:36:12 web.1  | *  Environment: development
08:36:12 web.1  | *          PID: 40038
08:36:12 web.1  | * Listening on http://127.0.0.1:3000
08:36:12 web.1  | * Listening on http://[::1]:3000
08:36:12 web.1  | Use Ctrl-C to stop
08:36:12 css.1  |
08:36:12 css.1  | Rebuilding...
08:36:12 css.1  | Done in 300ms.

Make numbers more readable in a Rails view

Rails has a number of handy helper methods.

Specifically, in ActionView::Helpers::NumberHelper there is the method number_with_delimiter

If you want to display the number 100000 and have people know right away whether it is 1 million or 100 thousand, just pass it to number_with_delimiter and it will return "100,000".

Some useful optional keyword parameters:
delimiter:"🍔" replaces the default , delimiter. (100000 becomes 100🍔000)
separator:"🍕" replaces the default . separator. (100.56 becomes 100🍕56)

Prevent rails' file server from serving index.html

You can prevent rails’ file server from serving index.html, while continuing to serve other files from the public directory by changing the index_name:

class Application
  config.public_file_server.index_name = "other-index.html"
end

Rails.application.routes.draw do
  get :dashboard, to: "application#dashboard"
  root to: redirect("/dashboard")
end

Visiting the root path / will no longer serve public/index.html if you define another route for /

Implicit order column

ActiveRecord has a class method implicit_order_column= that allows you to override the behavior of the .first and .last methods.

class User < ApplicationRecord
  self.implicit_order_column = "email"
end

User.first
User Load (3.2ms)  SELECT "users".* FROM "users" ORDER BY "users"."email" ASC, "users"."id" ASC LIMIT $1  [["LIMIT", 1]]

Get database value of model instance

AR instances have a method #attribute_in_database. Sometimes things don’t make sense, someone has created a method with the same name as the column:

create table users (id int, email citext);
class User < ApplicationRecord
  def email
    Time.current.strftime("%A, %B %C")
  end
end

User.first.email
=> "Thursday, March 20"

But you actually wan the email:

User.first.attribute_in_database("email")
=> "admin@example.com"

Rails composed_of

I learned that Rails ActiveRecord has composed_of method which allow us to group model attributes under a common PORO like object. Let’s say we have an User with address_street and address_city fields, stored in the same table, so we can still group the address attributes:

class User < ActiveRecord::Base
  composed_of :address, mapping: [%w(address_street street), %w(address_city city)]
end

This way, besides the user.address_street and user.address_city, we can also access the same values as:

address = user.address
puts address.street
puts address.city

Rails AR readonly!

ActiveRecord has some readonly features that marks a model (or relation) not to be updated. This way if we try:

irb> user = User.last
=> #<User id: 123, ...>

irb> user.readonly!
=> true

irb> user.update(updated_at: Time.current)
   (0.3ms)  SAVEPOINT active_record_1
   (0.3ms)  ROLLBACK TO SAVEPOINT active_record_1
ActiveRecord::ReadOnlyRecord: User is marked as readonly

Then we get a rollback with the readonly error.

An interesting thing is that the touch AR method does not respect this readonly feature (I tested on rails 6.0.4.1), check this out:

irb> user = User.last
=> #<User id: 123, ...>

irb> user.readonly!
=> true

irb> user.touch
   (0.3ms)  SAVEPOINT active_record_1
  User Update (1.4ms)  UPDATE "users" SET "updated_at" = $1 WHERE "users"."id" = $2  [["updated_at", "2022-03-08 20:39:40.750728"], ["id", 123]]
   (0.2ms)  RELEASE SAVEPOINT active_record_1
=> true

Easy conditional style class names in Rails

How many times do you see something like this?

<%= 
  link_to("Somewhere", "#",
    class: "class-1 class-2#{" class-3" if true}"
  )
%>

# <a href="#" class="class-1 class-2 class-3">Somewhere</a>

Gross right!?

Take advantage of a token list instead.

It’s also got a great alias in class_names

<%= 
  link_to("Somewhere", "#", 
    class: class_names("class-1 class-2", {"class-3": true})
  )
%>

# <a href="#" class="class-1 class-2 class-3">Somewhere</a>

As you see it can be passed different types and still generates down to a string list.

It works great with the current_page helper.

<%= 
  link_to("Home", root_path, 
    class: class_names({"active": current_page?(root_path)})
  )
%>

# <a href="/" class="active">Home</a>

Rails ActiveRecord count on groups

Rails ActiveRecord can count queries with GROUP BY clauses, and in this case the result is not just an integer, but a Hash with the grouped values and the count for each group. Check this out:

Project.group(:status, :city).count
# SELECT COUNT(*) AS count_all, "projects"."status" AS projects_status, "projects"."city" AS projects_city
# FROM "projects"
# GROUP BY "projects"."status", "projects"."city"
=> {
  [:pending, "Jacksonville Beach"] => 21,
  [:finished, "Jacksonville Beach"] => 1061
  [:pending, "Chicago"] => 10,
  [:finished, "Chicago"] => 980,
}

So rails manipulates the select statement to have all grouped by fields and the count(*) as well, which is pretty neat.

Rails scopes might just return all resources

ActiveRecord’s scopes are meant to be composable and intended to only ever return an ActiveRecord relation.

If you make a mistake with your scope and have it return something like a nil or false, Rails will return all records for that class in order to maintain composability.

If you are intentionally writing something that might return an empty value, use a class method rather than adding a scope in order to prevent bugs

Comparison Validate more than Numbers in Rails

As of Rails 7 we can now use comparisions in validations for more than just numbers!

Previously we could do this but only against an integer

class Procedure
  validates :appointment_count, numericality: { less_than: 5 }
end

Now we can compare against many other types. Here is a quick example validating that an end date is further in the future than a start date.

class Procedure
  validates :start_date, comparison: { greater_than: ->(_) { Date.current }
  validates :end_date, comparison: { greater_than: :start_date }
end

Cool thing is you can pass a Proc or Symbol. A symbol can represent a method on the class. The Proc can represent anything. Its argument is the instance of the class.

For more info, check out this PR.

Always declare columns for SQL query in Rails

When ignoring a column in an ActiveRecord query you’ll receive a query that declares the column names of the table explicitly versus using *.

What if you do not want to ignore a column to get this functionality? Rails 7 will introduce an ActiveRecord class attribute to do just this.

class Procedure < ApplicationRecord
  self.enumerate_columns_in_select_statements = true
end
Procedure.all

=> SELECT "procedures"."id", "procedures"."name", "procedures"."created_at", "procedures"."updated_at" FROM "procedures"

When enumerate_columns_in_select_statements is set to true, ActiveRecord SELECT queries will always include column names explicitly over using a wildcard. This change was introduced to provide consistency in query generation and avoid prepared statment issues.

Note: it can be declared at the app configuration level as well.

module MyApp
  class Application < Rails::Application
    config.active_record.enumerate_columns_in_select_statements = true
  end
end

With that change, all ActiveRecord queries will avoid the wildcard.

Ignore columns on ActiveRecord queries in Rails

ActiveRecord models have ignored_columns defined as a class attribute. This allows us to, just like it says, ignore a particular column from our queries and returning ActiveRecords.

class Procedure < ApplicationRecord
    self.ignored_columns = [:created_at, :updated_at]
end

If we perform a lookup, this is what we’ll now see.

Procedure.all

=> SELECT "procedures"."id", "procedures"."name" FROM "procedures"

Notice the subtle difference?

Without the ignored_columns declaration, we’d see a query like this:

Procedure.all

=> SELECT "procedures".* FROM "procedures"

Using NULLS FIRST / NULLS LAST ordering in Rails

Methods nulls_first & nulls_last were added to Arel in Rails 6.1 for PostgreSQL and in most other databases in Rails 7.

In an earlier TIL, I showed how to order using Arel.

Procedure.order(Procedure.arel_table[:name].desc.nulls_first)

=> SELECT "procedures".* FROM "procedures" ORDER BY "procedures"."name" DESC NULLS FIRST
Procedure.order(Procedure.arel_table[:name].desc.nulls_last)

=> SELECT "procedures".* FROM "procedures" ORDER BY "procedures"."name" DESC NULLS LAST

Here the desc method is wrapping the Arel attribute in a node so that it can be utilized in order. nulls_first/nulls_last is just wrapping the previous ordering node.

Procedure.arel_table[:name].desc.nulls_first

=> 
#<Arel::Nodes::NullsFirst:0x00007fb73ebf18f8
 @expr=
  #<Arel::Nodes::Descending:0x00007fb73ebf1920
   @expr=
    #<struct Arel::Attributes::Attribute
     relation=
      #<Arel::Table:0x00007fb735a02dc0
       @klass=Procedure(id: integer, name: string, created_at: datetime, updated_at: datetime),
       @name="procedures",
       @table_alias=nil,
       @type_caster=
        #<ActiveRecord::TypeCaster::Map:0x00007fb735a02cd0
         @klass=Procedure(id: integer, name: string, created_at: datetime, updated_at: datetime)>>,
     name="name">>>

I mention this as you need to define the order before utilizing the nulls methods.

Using Arel in ActiveRecord ORDER Queries

I utilize Arel in ActiveRecord where all the time but it never occured to me that order can also take an Arel node.

Procedure.order(Procedure.arel_table[:name].desc)

=> SELECT "procedures".* FROM "procedures" ORDER BY "procedures"."name" DESC

For such a trivial example I’d say that it’s much clearer to just use ActiveRecord in this case.

Procedure.order(name: :desc)

=> SELECT "procedures".* FROM "procedures" ORDER BY "procedures"."name" DESC

Cool piece of knowledge for possible use in a more complex ordering case.

You MUST use a ws protocol in rails💩actioncable

Rails’ actioncable library is a bit immature compared to other implementations, so there are a lot of rough edges to work around. One of those is the basic createConsumer function.

If your app is running without a DOM (nodejs), the node_module @rails/actioncable is going to fight you.

The rails guides recommend this:

createConsumer('https://ws.example.com/cable')

But that function relies on having a global document that can create <a> tags, which you won’t have in many contexts (node, react-native, etc.)

Also, why does a websocket library depend on HTML anchor tags?

You can work around this limitation by explicitly using a ws or wss protocol:

createConsumer('ws://localhost:3000/cable')

Custom URL helpers in Rails

Ever want a named route for something that’s not necessarily a resource in your Rails app?

In your any of your route files you can utilize direct.

# config/routes.rb

Rails.application.routes.draw do
  get 'foo', to: 'foo#bar'

  direct :get_to_the_goog do
    "https://google.com"
  end
end

This gives a nice named route of get_to_the_goog_url!

This can be even more useful as the return value of the block has to be valid arguments that you would pass to url_for. So you can use pretty much anything you’d normally use to build a url helper.

Let’s modify this just a bit to be more useful.

# config/routes.rb

Rails.application.routes.draw do
  get 'foo', to: 'foo#bar'

  direct :get_to_the_goog, search: nil do |options|
    "https://google.com/search?q=#{options[:search]}"
  end
end

Now we can call get_to_the_goog_url(search: "TIL").

Pretty cool… just take note of a few caveats. You get access to the _path version of the named helper but even if the helper is using a hard coded string (like our example above), it will remove the domain info (rightfully so). Also you are not able to use the direct functionality inside of a namespace or scope, however it will raise an error if you do… so that’s nice.

Break up large routing files in Rails

Breaking apart a routing file could be useful if you have large a different concepts in your app with their own larger route sets.

To do this you can utilize draw

# config/routes.rb

Rails.application.routes.draw do
  get 'foo', to: 'foo#bar'

  draw(:admin)
end

This will try to load another route file at config/routes/admin.rb. That file is just another normal routing file.

# config/routes/admin.rb

namespace :admin do
  resources :users
end

How to use ActiveRecored.pluck without Arel.sql

It is too cumbersome to remember to wrap every string in a class method, so this is a shortcut:

# app/models/application_record.rb

class ApplicationRecord < ActiveRecord::Base
  module ::ActiveRecord::Sanitization::ClassMethods
    define_method(:original_disallow_raw_sql!, instance_method(:disallow_raw_sql!))

    def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
      original_disallow_raw_sql!(args.map { |a| a.is_a?(String) ? Arel.sql(a) : a }, permit: permit)
    end
  end
end

Then you can write sql without the class methods

This can be easier to write:

User.where(payment_due: true)
  .pluck(Arel.sql("coalesce('last_billed_date', 'start_date')"))

Can now just be written as:

User.where(payment_due: true)
  .pluck("coalesce('last_billed_date', 'start_date')")

This can also be useful for .order as well

Subtlety between Rails' #try & Ruby's #&.

Many would say that the safe navigation operator (&.) in Ruby is a drop in replacment for Rails’ #try. However I came across an interesting case where they are not the same.

thing = nil
thing&.something
> nil
thing = nil
thing.try(:something)
> nil

Seems pretty much the same right?

However what happens when the object receiving the message is not nil but does not respond to the message?

thing = Thing.new
thing&.something
> NoMethodError: undefined method 'something' for <Thing:0x0000>
thing = Thing.new
thing.try(:something)
> nil

Hopefully not something you’ll run into often, but definitely be aware of it. It makes the safe navigation operator not necessarily a drop in replacment.

Rails has helpers for uploading spec fixture files

Instead of writing your own helper method in specs:

module HelpMePlease
  def uploaded_file(path)
    Rack::Test::UploadedFile.new(Rails.root.join("spec/fixtures", path))
  end
end

Rails has a built in helper method:

require "rails_helper"

RSpec.describe HelpNeeded do
  describe "something" do
    it "sends the file" do
      post :change_avatar, params: { avatar: fixture_file_upload("spongebob.png", "image/png") }
    end
  end
end

Finding Rails ActiveModel Errors

Rails allows to filter ActiveModel erros by field name and type with the where method. Check this out:

user = User.new(email: "user@test.com")
user.valid?

user.errors.where(:email).map(&:full_message)
# => [
#      "Email has already been taken",
#      "Email is too short (minimum is 20 characters)"
#    ]

user.errors.where(:email, :taken).map(&:full_message)
# => ["Email has already been taken"]

Rails delegated_type

Rails 6.1 added delegated_type for the ones who like polymorphic relations. So in addition to set a regular polymorphic relation in rails you can also call delegated_type method to inject a bunch of useful methods and scopes for you. Check this out:

class Content < ApplicationRecord
  # belongs_to :contentable, polymorphic: true
  delegated_type :contentable, types: %w[ TilPost BlogPost ]
end

class TilPost < ApplicationRecord
  has_one :content, as: :contentable
end

class BlogPost < ApplicationRecord
  has_one :content, as: :contentable
end

And this will produce helper methods like:

content.contentable_class
# => +TilPost+ or +BlogPost+
content.contentable_name
# => "til_post" or "blog_post"

Content.til_posts
# => Content.where(contentable_type: "TilPost")
content.til_post?
# => true when contentable_type == "TilPost"
content.til_post
# => returns the til_post record, when contentable_type == "TilPost", otherwise nil
content.til_post_id
# => returns contentable_id, when contentable_type == "TilPost", otherwise nil

Rails 6 `create_or_find_by`

Rails 6 comes with a new ActiveRecord method create_or_find_by.

User.create_or_find_by(first_name: 'Vinny') do |user|
  user.status = 'pending'
end
# => #<User id: 1, first_name: "Vinny", status: pending>

This method is similar to the already existing find_or_create_by method by it tries to create the model in the database first, then if an unique constraint is raised by the DB then rails rescue the error, it rollbacks the transaction and it finally finds the model.

The idea behind to use this new method instead is to avoid race condition between a find and a create calls to the db.

There’s a few downsides to this process, but one that caught my eyes was that now we’re seeing a lot of ROLLBACK messages in the rails logs, which is the expected behavior now.

When to set `inverse_of` in Rails AR

Rails ActiveRecord does not auto infer bi-directional associations if some of the associations contains a scope or any of the following through or foreign_key options.

class Author < ApplicationRecord
  has_many :books
end

class Book < ApplicationRecord
  belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
end
irb> a = Author.first
irb> b = a.books.first
irb> a.first_name = 'David'
irb> a.id = b.writer.id
=> true
irb> a.object_id = b.writer.object_id
=> false
irb> a.first_name == b.writer.first_name
=> false

To solve this issue we should use inverse_of option, check this out:

class Author < ApplicationRecord
  has_many :books, inverse_of: 'writer'
end

class Book < ApplicationRecord
  belongs_to :writer, class_name: 'Author', foreign_key: 'author_id'
end
irb> a = Author.first
irb> b = a.books.first
irb> a.first_name = 'David'
irb> a.id = b.writer.id
=> true
irb> a.object_id = b.writer.object_id
=> true
irb> a.first_name == b.writer.first_name
=> true

Conditionally Render Rails Links with `link_to_if`

ActionView::Helpers contains some really handy helpers for conditionally rendering links. For example, the link_to_if method will render the link if the given condition is met; otherwise it renders just the text.

<%= link_to_if(current_user.present?, "Admin Panel Tools", admin_tools_path) %>

When current_user.present? is true, yields the following HTML:

<a href="/admin_tools">Admin Panel Tools</a>

But when current_user.present? is false, yields the following:

Admin Panel Tools

https://api.rubyonrails.org/v6.0.2.1/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to_if

Note, there are also methods for link_to_unless and link_to_unless_current

Easily Format Phone Numbers in Rails

Included as part of ActiveSupport, Rails has a handy helper for formatting phone numbers. Passing a number/string to the helper and some optional args and it will take care of the rest.

Here’s a few examples of how it works:

number_to_phone(8858846) # 885-8846
number_to_phone(8778858846) # 877-885-8846
number_to_phone(8778858846, area_code: true) # (877) 885-8846

To see all the options for the method, check out the Rails docs https://api.rubyonrails.org/classes/ActiveSupport/NumberHelper.html#method-i-number_to_phone

Group Related ActiveRecord Validations

Today I learned about the with_options feature of ActiveRecord. It’s used to group validations together in a block. You could use it to transform code like this:

class User < ApplicationRecord
  validates :password, length: { minimum: 10 }, if: :is_admin?
  validates :email, presence: true, if: :is_admin?
end

Into this:

class User < ApplicationRecord
  with_options if: :is_admin? do |admin|
    admin.validates :password, length: { minimum: 10 }
    admin.validates :email, presence: true
  end
end

A use case for this might be a collection of validations that should only be checked when a boolean feature flag like enabled? is true.

accepts_nested_attributes_for in Rails 5.2

Getting accepts_nested_attributes_for to work can be a bit tricky, and most of the walkthroughs I found are a bit dated, so here’s a quick update.

Our models will be User and Address:

class User < ApplicationRecord
  has_many :addresses
  accepts_nested_attributes_for :addresses
end

class Address < ApplicationRecord
end

Now, assuming we have a UsersController, with all the standard resource actions omitted, we try to add addresses to our permitted params:

class UsersController < ApplicationController
  def user_params
    params.require(:user).permit(:name, :email, :addresses)
  end
end

Logically this seems like it would work, but if we look in the rails server logs, we will see:

Unpermitted parameter: :addresses_attributes

So we add it to our permitted params:

  def user_params
    params.require(:user).permit(:name, :email, :addresses_attributes)
  end

and refresh. Lo and behold, we get the same error!

Unpermitted parameter: :addresses_attributes

The secret is that address_attributes is a hash, and we need to communicate that to Rails:

  def user_params
    params.require(:user).permit(:name, :email, addresses_attributes: {})
  end

Et voilà!

Rails `travel_to` changes the value of `usec` to 0

https://github.com/rails/rails/blob/4dcc5435e9569e084f6f90fcea6e7c37d7bd2b4d/activesupport/lib/active_support/testing/time_helpers.rb#L145

In and of itself, not a huge deal. However, when you combine it with the way that active record quotes times:

https://github.com/rails/rails/blob/4dcc5435e9569e084f6f90fcea6e7c37d7bd2b4d/activesupport/lib/active_support/testing/time_helpers.rb#L145

It can lead to some incredibly subtle bugs in your tests that use queries in their assertions. Long story short, if your query relies on a time comparison, you may not return anything. :|

Rails has an Array#exclude? method

In my vendetta against the unless expression in ruby, I came across a use case where I wanted to execute code only if an item was missing from an array.

I could easily do:

unless ['a', 'b', 'c'].include?('d')
  # do a thing
end

But I wanted to replace the unless with an if, which led me to wonder if there was an exclude? method for arrays in ruby.

Turns out, ActiveSupport extended the Enumerable class to introduce exactly what I was looking for!

if ['a', 'b', 'c'].exclude?('d')
  # do a thing
end

Hooray!

Rails Collection#exists?

I’ve been using Rails for almost a decade, and find I still don’t know even close to all it has to offer. Today, I was browsing through an open source app, and stumbled across this code:

unless feed.posts.exists?(@post.id)
  feed.posts << @post
end

I’d never seen or used exists? on a collection before, so I looked it up. And of course, there it is, right in the Rails Guides Association Basics - methods added by has many!

Digging in a bit, what arguments can exists? take? Here’s the reference.

Turns out there a lot of options!. Integer, string, array, hash, false, or no args.

Well that’s kinda neat! So what does the no args do?

Imgur

It seems to behave similar to any?, and return true if there are any members of the collection, false if it’s empty.

TLDR: Read the Rails Guides. A decade in, you’ll probably still learn something!

Access a shadowDOM node from Capybara

Using selenium_headless you can access a node from the shadowDOM using evaluate_script. The trick is knowing where in the showdowRoot.childNodes it’s going to be. If you have a web component called my-dope-component then you could do something like this:

shadow_host = find('my-dope-component')
shadow_child = evaluate_script('arguments[0].shadowRoot.childNodes[<magic-index>]', shadow_host)

The value for <magic-index> depends on the structure of the template that you’re using, as well as the library (if any) that you’re using. You could also write a find style script that iterates the children and locates the correct one based on the tagName property or similar.

For example:

FIND_NODE = <<-SCRIPT
Array.from(arguments[0].shadowRoot.childNodes).map(element => {
  if (element.tagName === arguments[1].toUpperCase()) return element;
}).filter( value => value != undefined)[0]
SCRIPT

Swap between STI classes in Rails

Rails allows you to swap between single table inheritance classes with the becomes method. This method creates a new instance of the desired class, and passes the attributes from the original record to the new instance.

So if I have two classes, User and Admin, where Admin inherits from User:

class User
  # ...
end

class Admin < User
  # ...
end

I can change between the two classes using becomes:

user = User.first # returns an instance of the User class
user.class # => User
user.id # => 1
user.name # => Joe Hashrocket

admin = user.becomes(Admin) # returns an instance of the Admin class
admin.class # => Admin
admin.id # => 1
admin.name # => Joe Hashrocket

Disable Spring in Rails with `DISABLE_SPRING`

This is fairly self explanatory. If you don’t want spring running, because maybe you forget it’s on and then you’re confused when you’re making changes to configuration and you don’t see those changes manifest, then you can disable spring with:

DISABLE_SPRING=true

But be careful about where you put this. If you are using dotenv and you place it in your .env file it will not take effect. dotenv sets its environment after spring has started.

This is something that you should put in bashrc or zshrc.

export DISABLE_SPRING=true

Remove newlines from strings in Rails

Rails has a method called squish that will remove newlines from strings. It works very nicely with heredocs, where you may want readability but don’t really want the newlines.

Without squish:

<<~SQL
  update posts
  set status = 'public'
  where status is null;
SQL
# "update posts\nset status = 'public'\nwhere status is null;\n"

With squish:

<<~SQL.squish
  update posts
  set status = 'public'
  where status is null;
SQL
# "update posts set status = 'public' where status is null;"