Unfreeze a frozen ActiveRecord

You can freeze any Ruby object to prevent further modification.

If you freeze an ActiveRecord and try to set an attribute you will an error like this:

can't modify frozen hash

This is because ActiveRecord delegates #freeze to its attributes hash.

You can unfreeze most Ruby objects by creating a shallow copy of the frozen object by calling #dup on it:

user = User.find(3)
user.freeze
unfrozen_user = user.dup

Notes for Rails 2 users
-----------------...

Installing multiple MySQL versions on the same Linux with mysql-sandbox

Ubuntu has a package mysql-sandbox that lets you install multiple MySQL versions into your user home:

  1. Install mysql-sandbox
sudo apt install mysql-sandbox
  1. Download the version of MySQL you want to use from mysql.com:
    https://dev.mysql.com/downloads/file/?id=480427
    Make sure to choose "Generic Linux" instead of "Ubuntu" so you get a .tar.gz instead of .deb

  2. cd into the directory the mysql binaries will be extracted to

mkdir -p ~/bin/sandbox_dist
cd ~/bin/sandbox_dist
  1. Build the sandbox
make_sandbo...

Fix "couldn't parse YAML" error after upgrading Bundler

If you just upgraded to Bundler 10.0.10 you might get the following error when bringing up Rails:

/usr/lib/ruby/1.9.1/psych.rb:148:in `parse': couldn't parse YAML at line 17 column 14 (Psych::SyntaxError)

This is caused by Rails localization files (en.yml, de.yml, etc.) using symbols for various translation strings, and Bundler 10.0.10 defaults to a new YAML engine which cannot handle symbols.

You can switch back to the old YAML engine by ...

Understanding database cleaning strategies in tests

TLDR: In tests you need to clean out the database before each example. Use :transaction where possible. Use :deletion for Selenium features or when you have a lot of MyISAM tables.

Understanding database cleaning

You want to clean out your test database after each test, so the next test can start from a blank database. To do so you have three options:

  • Wrap each test in a transaction which is rolled back when you're done (through DatabaseCleaner.strategy = :transaction or `config.use_transactional_fi...

Unpoly 2: Don't try to download files through AJAX requests

Rails has the handy controller method send_file which lets us download files easily. We can decide whether the file should be downloaded (disposition: 'attachment') or shown in the browser (disposition: 'inline'). The default is disposition: 'attachment'.

Downloading files will not work when you are calling the controller action from an AJAX request. The browser will try to render the file and insert it in the DOM, which is never what you want.

Unpoly 2

Unpoly (sin...

Fix: esbuild assets are missing after capistrano deploy

Issue: You have an app using jsbundling-rails and esbuild. After deploy, the assets built by esbuild are missing in public/assets.

Solution: Add app/builds to your git repo (by adding a app/builds/.keep file).

Something in sprockets is caching paths and refuses to accept files in "unknown" locations.

AngularJS directive to format a text with paragraphs and new lines

If you are using Angular and want something like Rails' simple_format which HTML-formats a plain-text input into paragraphs and line breaks, this directive is for you.

Any HTML fragments inside that text will still be escaped properly.

Use it like this, where your text attribute specifies something available in your current scope:

<simple-format text="email.message"></simple-format>

This is the directive, in CoffeeScript syntax:

@app.directive 'simpleFor...

When does Webpacker compile?

Webpack builds can take a long time, so we only want to compile when needed.

This card shows what will cause Webpacker (the Rails/Webpack integration) to compile your assets.

When you run a dev server

While development it is recommended to boot a webpack dev server using bin/webpack-dev-server.

The dev server compiles once when booted. When you access your page on localhost before the initial compilation, the page may load without assets.

The ...

How to render an html_safe string escaped

Once Rails knows a given string is html_safe, it will never escape it. However, there may be times when you still need to escape it. Examples are some safe HTML that you pipe through JSON, or the display of an otherwise safe embed snippet.

There is no semantically nice way to do this, as even raw and h do not escape html_safe strings (the former just marks its argument as html_safe). You need to turn your string into an unsafe string to get the escaping love from Rails:

embed = javascript_tag('var foo = 1337;') # This is an h...

include_tags with the asset pipeline

You can include files from app/assets or from the public folder with javascript_include_tag. The subtle difference that tells rails how to build the path correctly is a single slash at the beginning of the path:

<%= javascript_include_tag('ckeditor/config') %> # for assets/ckeditor/config.js
<%= javascript_include_tag('/ckeditor/ckeditor') %> # for public/ckeditor/ckeditor.js

This also applies to stylesheet_link_tag.

Note that when you refer to a Javascript or stylesheet in /assets you need to add it to [the list of asse...

Run specific version of bundler

You can specify the version of bundler to execute a command (most often you need an older version of bundler, but don't want to uninstall newer ones):

bundle _1.0.10_ -v
Bundler version 1.0.10

An example is rails 3.2, which freezes bundler at version ~> 1.0:

Bundler could not find compatible versions for gem "bundler":
  In Gemfile: rails (~> 3.2) was resolved to 3.2.0, which depends on bundler (~> 1.0)

Current Bundler version: bundler (1.13.6)

You can solve this with:

gem install bundler -v 1....

HTML5: Allow to choose multiple files with a vanilla file picker

Modern browsers natively suppport file pickers that allow the user to choose multiple files at once. To activate this feature, set the multiple attribute:

<input type="file" name="images[]" multiple />

Or in a Rails view:

<%= file_field_tag "images[]", multiple: true %>

This works in IE10+.

Make sure that the field name ends in [] so your server-side code will parse the incoming files into an array. Obviously this naming convention is not compatible with default Rails nested attribute setters, so you'll need to write a form ...

simple_format helper for Javascript

The Javascript code below is a rough equivalent to the simple_format helper that ships with Rails:

function simpleFormat(str) {
  str = str.replace(/\r\n?/, "\n");
  str = $.trim(str);
  if (str.length > 0) {
    str = str.replace(/\n\n+/g, '</p><p>');
    str = str.replace(/\n/g, '<br />');
    str = '<p>' + str + '</p>';
  }
  return str;
}

Unlike the Rails helper, this does not preserve whitespace. You probably don't care.

Minified JavaScript and CSS

JavaScripts and CSS should be minified for production use.

In Rails 3.1+ the asset pipeline will take care of this. Thus you're best off using an uncompressed version of your Javascript in development. Also load the non-minified versions of libraries. This way debugging will be easier and you will still get all the minification love once deployed.

In Rails 2.3 and 3.0 you should at least embed external JavaScript libraries in minified form, using something like JavaScript compressor.

Ruby 2.3.0 has a safe navigation operator

As announced before, Ruby has introduced a safe navigation operator with version 2.3.0. receiver&.method prevents NoMethodErrors by intercepting method invocations on nil.

user = User.last
user&.name # => "Dominik"
# When there is no user, i.e. user is nil:
user&.name # => nil

This might remind you of andand, and indeed it behaves very similar. The only difference is in handling of `fa...

Define a route that only responds to a specific format

You won't usually have to do this. It's OK to route all formats to a controller, and let the controller decide to which format it wants to respond.

Should you for some reason want to define a route that only responds to a given format, here is how you do it:

Rails 3

match 'sitemap.xml' => 'feeds#sitemap', :constraints => { :format => 'xml' }, :as => 'sitemap'

Rails 2

map.sitemap 'sitemap.xml', :controller => 'feeds', :action => 'sitemap', :format => 'xml'

Katapult 0.3.0 released

Katapult 0.3.0 brings Rails 5 and Ruby 2.5 support with a new design, plus a ton of smaller features, fixes and improvements.

Features

  • Generating a Rails 5.1.4 app on Ruby 2.5.0
  • Dropped asset pipeline in favor of Webpacker
  • The generated application now has a sleek, simple design based on Bootstrap
  • Employing Unpoly
  • New application model DSL shortcut crud for "create a model and a web UI with crud actions"
  • The generated application model is now a transformable e...

ActiveRecord 3+ auto-converts times to UTC by default. Hilarity ensues.

Remember how Rails 2 came with an awesome feature that broke all code using Time.now or Time.parse?

This behavior is now the default for Rails 3. Disable it by adding the following to your config/application.rb:

config.active_record.default_timezone = :local
config.active_record.time_zone_aware_attributes = false    

ActiveRecord meets database views with scenic

Using Scenic, you can bring the power of SQL views to your Rails application without having to switch your schema format to SQL. Scenic provides a convention for versioning views that keeps your migration history consistent and reversible and avoids having to duplicate SQL strings across migrations. As an added bonus, you define the structure of your view in a SQL file, meaning you get full SQL syntax highlighting in the editor of your choice and can easily test your SQL in the database console during development.

[https://robots.thoughtb...

SSHKit 1.9.0 failure for Capistrano deploy

SSHKit 1.9.0 might fail with the following error, when trying to deploy a Rail application. Upgrading the gem to version 1.21.0 fixed the issue.

Traceback (most recent call last):
	17: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9.0/lib/sshkit/runners/parallel.rb:12:in `block (2 levels) in execute'
	16: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9.0/lib/sshkit/backends/abstract.rb:29:in `run'
	15: from /home/user/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/sshkit-1.9....

Katapult EOL

Katapult was an endeavor to dramatically speed up starting a new Rails application. However, it turned out to save less time than expected, while requiring more time for maintenance than anticipated. Since its benefits fell too low, we have decided to not continue developing Katapult.

You can still use Katapult for generating ready-to-run applications with model CRUD, authentication and all of Katapult's features, but the rapid development of the web will quickly render the generated code antiquated. Nevertheless, its architecture may remai...

How to use helper methods in a controller

Rails 3+

view_context.helper_method('args')

Rails 2

ApplicationController.helpers.helper_method('args')

Also see How to use helper methods inside a model.

Use form_for without the enclosing form tag

In rare cases you might need something like form_for (for using form builder methods on the resulting block element) but without the surrounding form. One such case would be updating some of a form's fields via XHR.

You can simply use Rails' fields_for to do things like this in your views (HAML here):

- fields_for @user do |form|
  = form.label :email, 'E-Mail'
  = form.text_field :email

You will only receive the form content you gave, no hidden inputs incl...

Concerned about Concerns?

With Rails 4, Concerns have become the “official” solution to the big-models problem. However, there’s a fair amount of controversy about this topic in the community. Not everyone is convinced that Concerns are the “right“ solution to the problem of AR models becoming too big.

In this talk we will see what Rails Concerns are and how can we use them to keep our models fit. More interestingly, we’ll discuss the trade-offs of this technique, the different views in the community and a couple of alternatives.