How to migrate CoffeeScript files from Sprockets to Webpack(er)
If you migrate a Rails application from Sprockets to Webpack(er), you can either transpile your CoffeeScript files to JavaScript or integrate a CoffeeScript compiler to your new process. This checklist can be used to achieve the latter.
- If you need to continue exposing your CoffeeScript classes to the global namespace, define them on
window
directly:
-class @User
+class window.User
- Replace Sprocket's
require
statement with Webpacker's...
Vortrag: Content Security Policy: Eine Einführung
Grundidee
CSP hat zum Ziel einen Browser-seitigen Mechanismus zu schaffen um einige Angriffe auf Webseiten zu verhindern, hauptsächlich XSS-Angriffe.
Einschub: Was ist XSS?
XSS = Cross Site Scripting. Passiert wenn ein User ungefiltertes HTML in die Webseite einfügen kann.
<div class="comment">
Danke für den interessanten Beitrag! <script>alert('you have been hacked')</script>
</div>
Rails löst das Problem weitgehend, aber
- Programmierfehler weiter möglich
- manchmal Sicherheitslücken in Gems oder Rails
Lösungsid...
Introducing GoodJob 1.0, a new Postgres-based, multithreaded, ActiveJob backend for Ruby on Rails
GoodJob is a new background worker gem. It's compatible with ActiveJob.
We're huge fans of Sidekiq for its stability and features. One advantage of GoodJob over Sidekiq is that GoodJob doesn't require Redis. So in cases where you don't have Redis or don't want to pay for a Redis HA quorum node, this might be an alternative worth checking out.
Automatically validating dependency licenses with License Finder
"Open-source software (OSS) is great. Anyone can use virtually any open-source code in their projects."
Well, it depends. Licenses can make things difficult, especially when you are developing closed-source software. Since some OSS licenses even require the employing application to be open-sourced as well (looking at you, GPL), you cannot use such software in a closed-source project.
To be sure on this, we have developed a project-level integration of Pivotal's excellent [license_finder](https:/...
ActiveRecord: String and text fields should always validate their length
If you have a :string
or :text
field, you should pair it with a model validation that restricts its length.
There are two motivations for this:
- In modern Rails, database types
:string
and:text
no longer have a relevant size limit. Without a validation a malicious user can quickly exhaust the hard drive of your database server. - In legacy Rails (or database schemas migrated from legacy Rails), database types
:string
and:text
had a database-side length constraint. When the user enters a longer string, the ActiveRecord valida...
FactoryBot: Traits for enums
FactoryBot allows to create traits from Enums since version 6.0.0
The automatic definition of traits for Active Record enum attributes is enabled by default, for non-Active Record enums you can use the traits_for_enum
method.
Example
factory :user do
traits_for_enum :role, %w[admin contact] # you can use User::ROLES here, of course
end
is equivalent to
factory :user do
trait :admin do
role { 'admin' }
end
trait :contact do
role { 'c...
PostgreSQL: Difference between text and varchar columns
TL;DR PostgreSQL handles Rails 4+ text
and string
columns the same. Some libraries may still reflect on the column type and e.g. render differently sized text fields.
PostgreSQL offers three character types for your columns:
-
character varying(n)
(also calledvarchar
or juststring
): Contents are limited to n characters, smaller contents are allowed. -
character(n)
: All contents are padded with spaces to allocate exactly n characters. -
text
: There is no upper or lower character limit (except for the absolute...
How to use Active Job to decouple your background processing from a gem
In a web application you sometimes have tasks that can not be processed during a request but need to go to the background.
There are several gems that help to you do that, like Sidekiq or Resque.
With newer Rails you can also use ActiveJob as interface for a background processing library. See here for a list of supported queueing adapters.
For ...
Howto: Select2 with AJAX
Select2 comes with AJAX support built in, using jQuery's AJAX methods.
...
For remote data sources only, Select2 does not create a new element until the item has been selected for the first time. This is done for performance reasons. Once an has been created, it will remain in the DOM even if the selection is later changed.
If you have a huge collection of records for your select2 input, you can populate it via AJAX in order to not pollute your HTML with lots of <option>
elements.
All you have to do is to provide...
The JavaScript Object Model: Prototypes and properties
Speaker today is Henning Koch, Head of Development at makandra.
This talk will be in German with English slides.
Introduction
As web developers we work with JavaScript every day, even when our backend code uses another language. While we've become quite adept with JavaScript at a basic level, I think many of us lack a deep understanding of the JavaScript object model and its capabilities.
Some of the questions we will answer in this talk:
- How does the
new
keyword construct an object? - What is the differen...
Legacy CarrierWave: How to generate versions with different file extensions
We use CarrierWave in many of our projects to store and serve files of various formats - mostly images. A common use case of CarrierWave's DSL is to "process" the original file in order to create multiple "versions", for example different resolutions of the same image.
Now we could go one step further: What if we want to create versions that have a different file extension than the original file? For example, let's assume we'd like to create a ve...
How to evaluate CSS media queries in JavaScript
To make CSS rules dependent on the screen size, we use media queries:
@media (max-width: 500px) {
// rules for screen widths of 500px or smaller
}
Browsers will automatically enable and disable the conditional rules as the screen width changes.
To detect responsive breakpoints from JavaScript, you may use the global matchMedia()
function. It is supported in all brow...
ActiveRecord: Named bindings in conditions
In Active Record you can use named bindings in where
-conditions. This helps you to make your code more readable and reduces repetitions in the binding list.
Example without named bindings
User.where(
'name = ? OR email = ?',
params[:query],
params[:query]
)
Example with named bindings
User.where(
'name = :query OR email = :query',
query: params[:query]
)
Rails: Concurrent requests in development and tests
With puma
you can have concurrent requests. There are two concepts on how Puma can handle two incoming requests: Workers and Threads.
Workers
Puma can have multiple workers. Each worker is a process fork from puma and therefore a very heavy instance and can have multiple threads, that handle the incoming requests.
Example: A Puma server with 2 workers
and 1 thread
each can handle 2 request in parallel
. A third request has to wait until the thread of one of the workers is free.
Threads
Rails is thread-safe since version 4 (n...
Bundler in deploy mode shares gems between patch-level Ruby versions
A recent patch level Ruby update caused troubles to some of us as applications started to complain about incompatible gem versions. I'll try to explain how the faulty state most likely is achieved and how to fix it.
Theory
When you deploy a new Ruby version with capistrano-opscomplete, it will take care of a few things:
- The new Ruby version is installed
- The Bundler version stated in the Gemfil...
How to: Throttle CPU in Google Chrome
Chrome allows you to throttle the Network and the CPU. Both settings are useful to measure the performance of you application and reproduce performance issues (Example Debugging frontend performance issues with Chrome DevTools).
You find the settings in: DevTools
> Performance
> Capture Settings (Gear icon in the right corner)
> `CPU: No...
ActiveRecord: Specifying conditions on an associated table
We can use ActiveRecord's where
to add conditions to a relation. But sometimes our condition is not on the model itself, but on an associated model. This card explains multiple ways to express this condition using ActiveRecord's query interface (without writing SQL).
As an example we will use a User
that has many Post
s:
class User < ApplicationRecord
has_many :posts
scope :active, -> { tra...
How to write modular code
Or: How to avoid and refactor spaghetti code
Please note that I tried to keep the examples small. The effects of the methods in this card are of course much more significant with real / more complex code.
What are the benefits of more modular code?
Code is written once but read often (by your future self and other developers who have to understand it in order to make changes for example). With more modular code you reduce the scope of what has to be understood in order to change something. Also, naming things gives you the opportunity t...
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: Validate dynamic attributes / JSON in ActiveRecord
PostgreSQL and ActiveRecord have a good support for storing dynamic attributes (hashes) in columns of type JSONB
. But sometimes you are missing some kind of validation or lookup possibility (with plain attributes you can use Active Record's built-in validations and have your schema.rb
).
One approach about being more strict with dynamic attributes is to use JSON Schema validations. Here is an example, where a project has the dynamic attributes analytic_stats
, that we can use to store analytics from an external measurement tool.
- A g...
Structuring Rails applications: the Modular Monorepo Monolith
Root Insurance runs their application as a monolithic Rails application – but they've modularized it inside its repository. Here is their approach in summary:
Strategy
- Keep all code in a single repository (monorepo)
- Have a Rails Engine for each logical component instead of writing a single big Rails Application
- Build database-independent components as gems
- Thus: gems/ and engines/ directories instead of app/
- Define a dependency graph of components. It should have few edges.
- Gems and Engines can be extracted easier once nece...
Always convert and strip user-provided images to sRGB
Debugging image color profiles is hard. You can't trust your eyes in this matter, as the image rendering depends on multiple factors. At least the operation system, browser or image viewer software and monitor influence the resulting image colors on your screen.
When we offer our users the possibility to upload images, they will most likely contain tons of EXIF metadata and sometimes exotic color profiles like eciRGB. We want to get rid of the metadata, as it might contain sensitiv...
Defining new elements for your HTML document
Browsers come with a set of built-in elements like <p>
or <input>
. When we need a new component not covered by that, we often build it from <div>
and <span>
tags. An alternative is to introduce a new element, like <my-element>
.
When a browser encounters an unknown element like <my-element>
, the browser will proceed to render <my-element>
's children. The visual rendering of your page will not be affected.
If you care about their HTML being valid, your new element should contain a dash character (-
) to mark it as a *custom el...
Effectively Using Materialized Views in Ruby on Rails · pganalyze
It's every developer's nightmare: SQL queries that get large and unwieldy. This can happen fairly quickly with the addition of multiple joins, a subquery and some complicated filtering logic. I have personally seen queries grow to nearly one hundred lines long in both the financial services and health industries.
Luckily Postgres provides two ways to encapsulate large queries: Views and Materialized Views. In this article, we will cover in detail how to utilize both views and materialized views within Ruby on Rails, and we can even take...