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 (sin...
It is generally discouraged to load your JavaScript by a <script src>
tag in the <head>
:
<head>
<script src="app.js"></script>
</head>
The reason is that a <script src>
tag will pause the DOM parser until the script has loaded and executed. This will delay the browser's first contentful paint.
A much better default is to load your scripts with a <script src defer>
tag:
<head>
<script src="app.js" defer></script>
</head>
A deferred script has many useful properties:
The attached compiler()
function below applies JavaScript behavior to matching HTML elements as they enter the DOM.
This works like an Unpoly compiler for apps that don't use Unpoly, Custom Elements or any other mechanism that pairs JavaScript with HTML elements.
The compiler()
function is also a lightweight replacement for our legacy [$.unobtrusive()
](https://makandracards.com/makandra/4-unobtrusiv...
Given you have a strict CSP that only allows <script src>
elements from your own domain:
Content-Security-Policy: script-src 'self'
This will block JavaScript handlers inlined as attribute into your HTML elements. Clicking on the following link will only log an error with a strict CSP:
<a href="javascript:alert('hello')">click me</a>
<a href="#" onclick="alert('hello')">click me</a>
The recommended solution is to move the handler from the HTML to the allowed ...
Often people need links which are not linked directly, but should trigger execution of JavaScript.
You can find a lot of workarounds for that:
<a href="#">Do something with js!</a>
This defines an empty anchor. This may lead the browser to let the page jump to the top when the link is clicked, unless you call preventDefault
on the event. This is probably not what you want.
<a href="#!">Do something with js!</a>
This tells the browser to jump to an anchor !
. It depends on the browser implementation wha...
Our gem spreewald supports a few helpers for development. In case you notice errors in your Cucumber tests, you might want to use one of them to better understand the underlying background of the failure. The following content is also part of the spreewald's README, but is duplicated to this card to allow repeating.
Pauses test execution and opens an IRB shell with current cont...
Formerly 301 (Moved Permanently) and 302 (Found) were used for redirecting. Browsers did implement them in different ways, so since HTTP 1.1 there are some new status codes which allow for finer distinctions.
The interesting part is how non-GET requests are handled by the redirect. It is preferrable to use the newer status code to avoid unexpected behavior.
The response to the request can be found under anot...
When giving a presentation where you do some coding, the font size you usually use is probably a bit too small and makes code hard to read for users on smaller screens or low-bandwidth connections when the image quality is lower.
Here are two solutions.
RubyMine offers a "Presentation Mode" which you can use. Simply navigate to View → Appearance → Enter Presentation Mode to enable it.
This will increase your code editor's font size as well as your UI and works nicely when sharing a single file.
However, some control...
When testing JavaScript functionality in Selenium (E2E), you may need to access a class or function inside of a evaluate_script
block in one of your steps. Capybara may only access definitions that are attached to the browser (over the window
object that acts as the base). That means that once you are exporting your definition(s) in Webpacker, these won't be available in your tests (and neither in the dev console). The following principles/concepts also apply to Sprockets.
Say we have a StreetMap
class:
// street_map.js
class S...
Table of content for the linked article:
1. The `loading=lazy` attribute
2. Email, call, and SMS links
3. Ordered lists `start` attribute
4. The `meter` element
5. HTML Native Search
6. Fieldset Element
7. Window.opener
8. Base Element
9. Favicon cache busting
10. The `spellcheck` attribute
11. Native HTML sliders
12. HTML Accordion
13. `mark` tag
14. `download` attribute
15. Performance tip
16. Video thumbnail
17. input type="search"
For matching whitespaces in a regular expression, the most common and best-known shorthand expression is probably \s
.
It matches the following whitespace characters:
However, in some cases these may not be good enough for your purpose.
Sometimes a text may contain two words separated by a space, but the author wanted to ensure that those words are written in the same lin...
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.
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 ...
To attach files to your records, you will need a new database column representing the filename of the file. To do this, add a new migration (rails g migration <name>
) with the following content:
class AddAttachmentToNotes < ActiveRecord::Migration[6.0]
def change
add_column :notes, :attachment, :string
end
end
Don't forget to rename the class and change the column details to fit your purpose. Run it.
The first way is to store your Carrierwave attachments not ...
In Ruby (almost) everything is an Object
. While this enables a lot of powerful features, this concept might be confusing for developers who have been programming in more static languages, such as Java or C#. This card should help understanding the basic concepts of Ruby's object model and how things behave.
When working with objects in Ruby, you might think of a "container" that holds metadata, variables and methods. Metadata describes stuff like the object's class or its object_id
whi...
The ActionDispatch module of Rails gives you the helper method flash
to access the flash messages in a response.
describe PostsController, type: :request do
describe 'update' do
it 'shows a success message on update' do
post_record = create(:post)
put "/posts/#{post_record.id}"
# Same as @request.flash[:alert]
expect(flash[:alert]).to eq('Post updated successfully.')
end
end
end
CarrierWave comes with a set of default configuration options which make sense in most cases. However, you should review these defaults and adjust for your project wherever necessary.
You will also find suggestions on what to change below.
Here is the current default config for version 2:
config.permissions = 0644
config.directory_permissions = 0755
config.storage_engines = {
:f...
Recently I made an upgrade from Bootstrap 3 to Bootstrap 4 in a bigger project. Here are some tips how to plan and perform such an upgrade. The effort will scale with the size of the project and its structure. If your stylesheets already follow strict rules, it may take less time to adapt them to the new version.
There are several gems and libraries that works well with bootstrap or provide at least stylesheets/plugins to easily integrate the bootstrap theme. But very often they only work with specific version or are no long...
Consider the following models and form models:
class Parent < ApplicationRecord
has_many :children, class_name: 'Child', foreign_key: 'parent_id'
end
class Parent::AsForm < ActiveType::Record[Parent]
change_association :children, class_name: 'Child::AsForm', foreign_key: 'parent_id', autosave: true, inverse_of: :parent
accepts_nested_attributes_for :children
validates_associated :children
end
class Child < ApplicationRecord
belongs_to :parent, inverse_of: :children
end
class Child::AsForm < ActiveType::Reco...
Rails 6 includes a WYSIWYG editor, Action Text. It works out of the box quite well, but chances are that you want to add some custom functionality. This card contains some tips how to achieve this.
Basically, follow the guide in the Rails documentation. The automated script may not work with the way webpacker is configured in your project, but it should be easy to fix.
If you don't want the default c...
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...
I just finished migrating a project from the Asset Pipeline to Webpacker, this is what my diff to master looks like:
5.825 files changed, 44.805 insertions(+), 529.948 deletions(-)
warning: inexact rename detection was skipped due to too many files.
warning: you may want to set your diff.renameLimit variable to at least 5134 and retry the command.
There is no way me or my peer reviewer is able to parse 500k+ lines of code. Fortunately, git has ...
The Truemail gem (not to be confused with truemail.io) allows validating email addresses, e.g. when users enter them into a sign-up form. It runs inside your application and does not depend on an external SaaS service.
Truemail supports different validation "layers":
TinyMCE is a WYSIWYG editor which is quite customizable.
tinymce.init({
// ...
toolbar: 'myCustomButton',
setup: function(editor) {
editor.ui.registry.addButton('myCustom Button', {
...
The linked blog post contains some background information about the alt
attribute and the figure
/ figcaption
element. It is interesting, that a figure is not only for images but also for captions, code snippets, quotations and more.