Accept nested attributes for a record that is not an association

Note: Instead of using the method in this card, you probably want to use ActiveType's nested attributes which is a much more refined way of doing this.


The attached Modularity trait allows you to accept nested attributes for a record that is not an association, e.g.:

    class Site < ActiveRecord::Base
      
      def home_page
        @home_page ||= Page.find_by_name('home')
      end
      
      does 'a...

Rails: Output helpers for migrations

When you're writing migrations that do more than changing tables (like, modify many records) you may want some output. In Rails > 3.1 you have two methods at hand: announce and say_with_time.

In the migration:

class AddUserToken < ActiveRecord::Migration

  class User < ActiveRecod::Base; end

  def up
    add_column :users, :token, :string
    
    announce "now generating tokens"
    User.find_in_batches do |users|
      say_with_time "For users ##{users.first.id} to ##{users.last.id}" do
        users.each do |user|
        ...

Ruby and Rails: Debugging a Memory Leak

A memory leak is an unintentional, uncontrolled, and unending increase in memory usage. No matter how small, eventually, a leak will cause your process to run out of memory and crash.

If you have learned about a memory leak, looking at the number of Ruby objects by type can help you track it down:

> pp ObjectSpace.count_objects
{:TOTAL=>77855,
 :FREE=>4526,
 :T_OBJECT=>373,
 :T_CLASS=>708,
 :T_MODULE=>44,
 :T_FLOAT=>4,
 :T_STRING=>65685,
 :T_REGEXP=>137,
 :T_ARRAY=>984,
 :T_HASH=>87,
 :T_STRUCT=>12,
 :T_BIGNUM=>2,
 :T_FILE=>3,
 :T_D...

Rails: How to find records with empty associations

Imagine these models and associations:

class Deck < ApplicationRecord
  has_many :cards
end

class Card < ApplicationRecord
  belongs_to :deck, optional: true
end

Now you want to find all Decks without any Card or all Cards without a Deck.

Rails 6.1+

Rails 6.1 introduced a handy method ActiveRecord#missing to find records without given associations.

Deck.where.missing(:cards)
SELECT "decks".*
FROM "dec...

Rails: How to check if a certain validation failed

If validations failed for a record, and you want to find out if a specific validation failed, you can leverage ActiveModel's error objects.
You rarely need this in application code (you usually just want to print error messages), but it can be useful when writing tests.

As an example, consider the following model which uses two validations on the email attribute.

class User < ApplicationRecord
  validates :email, presence: true, uniqueness: true
end

Accessing errors

Let's assume we have a blank user:

user = Us...

Rails: Default HTTP status codes when redirecting

When redirecting you should take care to use the right HTTP status code.

From controllers

When redirecting from a controller, the default status code is 302 Found (aka Moved Temporarily):

red...

Rails: Send links in emails with the right protocol

ActionMailer per default uses http as protocol, which enables SSL-stripping. When a logged-in user follows an http link to your application, it sends the cookies along with it. Although the application redirects the user to https and from that point has a secure connection to the user, an attacker may overhear that first unsafe request and hijack your session.

Teach ActionMailer to use the right protocol

If your application is behind SSL, turn on using https application-wide. In your environment file (either global or per environ...

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: 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

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
---------------------------------...

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...

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...

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": "...

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...

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

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...

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"

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.
...