Rails: Comparison of Dates - before? and after?

tl;dr

Since Rails 6+ you can use before? and after? to check if a date/time is before or after another date/time.

Example

christmas = Date.parse('24.12.2022')
date_of_buying_a_gift = Date.parse('12.12.2022')

date_of_buying_a_gift.before?(christmas)
# => true
# Now you are well prepared for Christmas!! ;)

date_of_buying_a_gift = Date.parse('26.12.2022')

date_of_buying_a_gift.after?(christmas)
# => true
# Now you are too late for christmas! :(

Hint

If you want to check if a date/time is between to ot...

Rails: Use STI in Migration

tl;dr

You should decouple migrations from models by embedding models into the migration. To use STI in this scenario you have to overwrite find_sti_class and sti_name.

Tip

When possible, try to avoid STI in migrations by disabling it.

Example

Warning

This is more for the sake of I want to do it but I kno...

Rails: Accessing helper methods from a controller

In Rails 5+ you can access a helper from a controller using the helpers method:

# Inside a controller action
helpers.link_to 'Foo', foo_path

In older Rails versions you can use view_context instead:

# Inside a controller action
view_context.link_to 'Foo', foo_path

Managing vendor libraries with the Rails asset pipeline

The benefit of the Rails asset pipeline is that it compiles your stylesheets and javascripts to a single file, respectively. However, the consequences are startling if you don't understand them. Among others, the raw asset pipeline requires you to have all your asset libraries in the same folder, which quickly becomes confusing as your set of assets grows. To overcome this, we have two different solutions.

Custom solution

We are using a custom workaround to keep library files apart in their own directories. To avoid b...

Reading the Rails session hash from a Rack middleware

To read the Rails session from a Rack middleware, use env['rack.session']. It's an ActionDispatch::Request::Session object.

class MyMiddlware

  def initialize(app)
    @app = app
  end

  def call(env)
    status, headers, body = @app.call(env)
    session = env['rack.session']
    Rails.logger.info("Value of session['foo'] is: " + session['foo'].inspect)
    [status, headers, body]
  end

end

You may not be able to write to the session this way (I haven't tested this).

Yarn: if integrity check won't let you start rails console

I ran into a situation in which I received the yarn integrity check warning when starting the rails console even though everything was up to date and correct versions in use.

TLDR: run spring stop

I tried starting the rails console without switching to the correct node version first and received the yarn integrity warning.

warning Integrity check: System parameters don't match                                                                                     
error Integrity check failed                                         ...

How to fix: irb / rails console randomly crashing

If your irb or rails console keeps randomly crashing and you can't figure out why then you can try to disable multi-line autocomplete.

Rails 4 introduced collection_check_boxes

Starting from Rails 4.0, you can use a special form options helper called #collection_check_boxes. It behaves similar to #collection_select, but instead of a single select field it renders a checkbox and a label for each item in the collection.

= form_for @post do |form|
  = form.collection_check_boxes :author_ids, Author.all, :id, :name_with_initial

How generated form params look like
---------------------------------...

Rails: Kill spring with fire

To ensure Spring is not running:

bin/spring stop
pkill -f spring

To prevent Spring from starting again:

export DISABLE_SPRING=1

A short overview of common design patterns implemented within Rails

The linked content includes a few design patterns implemented with Ruby on Rails.

What is the card indented to achieve?

  • You can use the pattern names for code reviews, so all parties know with only a few words which change is requested. Example: "Please use a form object here"
  • You can learn about new code patterns
  • You should read the sections "Advantages of using design patterns" and "Disadvantages of using design patterns in a wrong way", since design patterns do not replace good code

Included Design Patterns: Service, Value objec...

Vortrag: Elasticsearch Grundlagen und Rails-Integration mit searchkick

Was ist Elastic?

  • Suchmaschine, basierend auf Apache Lucene
  • größtenteils Open-Source
  • einige kommerzielle Features ("Elastic Stack", früher "X-Pack")
    • Zugriffsrechte (bis vor kurzen)
    • Monitoring
    • Reporting
    • Graph-Unterstützung
    • Machine Learning
  • REST-Api (JSON über HTTP)

Grundlagen

Elastic antwortet per Default auf Port 9200

http GET :9200
{
  "name": "ntK2ZrY",
  "cluster_name": "elasticsearch",
  "cluster_uuid": "Bbc-ix5bQZij5vfFU29-Cw",
  "version": {
    "number": "6.7.1",
    "build_flavor": "...

Rails: Parsing a time in a desired timezone

Sometimes you want to have a time in a given timezone independent from you Rails timezone settings / system timezone. I usually have this use case in tests.

Example

Time.parse('2020-08-09 00:00') will return different results e.g. 2020-08-09 00:00:00 +0200 depending on the Rails timezone settings / system timezone. But in this example we always want to have the given time in UTC because that's what the API returns.

it 'returns a valid API response', vcr: true do
  expect(client.get('/users/1')).to have_attributes(
    name: 'So...

Ruby on Rails: Finding a memory leak

The author describes his little journey in hunting down a memory leak. Maybe his approach and tooling may one day help you in a similar situation.

Tools: rbtrace, ObjectSpace.trace_object_allocations_start, heapy, sheap

Plotting graphs in Ruby with Gruff

Geoffrey Grosenbach has created Gruff for easily plotting graphs. It is written in pure Ruby and integrates with Rails applications.

It provides features as automatic sizing of dots and lines (the more values, the thinner the graph's elements), custom or predefined themes, different styles (bar, line, dot and many more) and multiple graphs in one chart.

Installation

In your Gemfile:

gem 'rmagick', :require => false
gem 'gruff'

Then run bundle install (and don't forget to restart your development server.)

Usage

This i...

Heads up: Rails offers two similar means for text truncation

Rails defines a #truncate helper as well as a method String#truncate.

= truncate("my string", length: 5)
= "my string".truncate(5)

Both are really similar; in fact, the helper invokes the method and improves it with two niceties: support for passing a block (which could e.g. render a "read on" link), and html_safe knowledge.

Prefer the truncate() helper

Warning: truncate() calls html_safe if you're not escaping. FWIW, an HTML string may easily become invalid when truncated, e.g. when a closing tag gets chopped off.
...

Persist Rails or IRB Console Command History After Exit

Create, or edit your ~/.irbrc file to include:

require 'irb/ext/eval_history' # was 'irb/ext/save-history' for versions prior to Ruby 3.3
IRB.conf[:SAVE_HISTORY] = 2000
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-history"

Save ActiveRecord models without callbacks or validations (in Rails 2 and Rails 3)

Rails 2

You can use

record.send(:update_without_callbacks)

or

record.send(:create_without_callbacks)

This can be used as a lightweight alternative to machinist's make or FactoryGirl's create, when you just need objects in the database but don't care about any callbacks or validations. Note that create_without_callbacks does not return the object, so you might want to do

record = Record.new.tap(&:create_without_callbacks)

Rails 3

Rails 3 no longer comes with update_without_callbacks or `crea...

How to include Sidekiq job IDs in Rails logs

When logging in Rails, you can use the log_tags configuration option to add extra information to each line, like :request_id or :subdomain. However, those are only valid inside a request context and have no effect when your application is logging from inside a Sidekiq process.
This includes custom as well as any framework logs, like query logging from ActiveRecord.

Since Sidekiq Workers run inside threads of a single process, running multiple jobs in...

Rails: Rest API post-mortem analysis

This is a personal post-mortem analysis of a project that was mainly build to provide a REST API to mobile clients.

For the API backend we used the following components:

  • Active Model Serializer (AMS) to serializer our Active Record models to JSON.
  • JSON Schema to test the responses of our server.
  • SwaggerUI to document the API.

It worked

The concept worked really good. Here are two points that were extraordinary compared to normal Rails project with many UI components:

  • Having a Rails application, that has no UI components (only...

How to fix: WrongScopeError when using rspec_rails with Rails 6.1

tl;dr: Upgrade the gem to at least 4.0.1

When you use rspec_rails in a version < 4 with Rails 6.1 you may encounter an error like this:

Failure/Error:
  raise WrongScopeError,
    "`#{name}` is not available from within an example (e.g. an " \
    "`it` block) or from constructs that run in the scope of an " \
    "example (e.g. `before`, `let`, etc). It is only available " \
    "on an example group (e.g. a `describe` or `context` block)."
    `name` is not available from within an example (e.g. an `it` block) or from constructs that...

How to fix: Rails query logs always show lib/active_record/log_subscriber.rb as source

Rails 5.2+ supports "verbose query logs" where it shows the source of a query in the application log.
Normally, it looks like this:

  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE ...
  ↳ app/controllers/users_controller.rb:42:in `load_users'

However, you may encounter ActiveRecord's LogSubscriber as the source for all/most queries which is not helpful at all:

  User Load (0.5ms)  SELECT "users".* FROM "users" WHERE ...
  ↳ activerecord (6.0.3.3) lib/active_record/log_subscriber.rb:100:in `debug'

While th...

Fix for "Rails assets manifest file not found" in Capistrano deploy

If you use webpacker in your Rails application, and you have completely disabled Sprockets, you might get the following error when trying to deploy: Rails assets manifest file not found. This happens inside the deploy:assets:backup_manifest task.

This task comes from capistrano-rails. It is build for Sprockets and does not work with Webpacker out of the box.

Solution

Configure capistrano-rails to work with Webpacker

Alternative

If you are using capistrano-rails, but...

Downloading files from Ruby on Rails

To offer files for download, use send_file.

def download(file)
  send_file file.path, :disposition => 'attachment'
end

Note that a send_file replaces the default :render action.

Rails: How to use custom flash types in controllers

Rails supports alert and notice as default flash types. This allows you to use these keys as options in e.g. redirect_to and as a helper in views e.g. <%= notice %> (instead of flash[:notice]).

class SomeController < ApplicationRecord
  def create
    @user = User.create!
    
    redirect_to user_path(@user), notice: "#{@user} created!" 
  end
end

In case you are using Bootstrap as CSS framework you might also want to support flashes like success. This can be done with the add_flash_types method.

class Applicat...