All direct child directories of app
are automatically added to the eager- and autoload paths. They do NOT create a module for namespacing. This is intuitive, since there normally is no module Model
, or module Controller
. If you want to add a new base directory, there's no additional config needed.
app
├── controllers
├── helpers
├── inputs # No config needed
├── mailers
├── models
├── uploaders # No config needed
├── util # No config needed
└── workers # No config needed
Sometimes it's handy to group files wit...
While upgrading CarrierWave from version 0.11.x to 3.x, we encountered some very nasty fails. Below are the basic changes you need to perform and some behavior you may eventually run into when upgrading your application. This aims to save you some time understanding what happens under the hood to possibly discover problems faster as digging deeply into CarrierWave code is very fun...
The following focuses on extension allowlisting, but it is the exact same thing for content type allowlisting with the `content_ty...
The old Chrome downloads bar had several advantages over the new subtle downloads dropdown:
They say the flag might be removed in the future, but for now it gets the downloads bar back.
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 ...
Reminder of what you can do with Geordi.
Note: If you alias Geordi to something short like g
, running commands gets much faster!
Note: You only need to type the first letters of a command to run it, e.g. geordi dep
will run the deploy
command.
Guided deployment, including push, merge, switch branches. Does nothing without confirmation.
Run something for all Capistrano environments, e.g. geordi cap deploy
When you just clon...
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...
On the Rails console, assigning an object to a variable can lead to this strange error (without stacktrace):
irb > recipient = Recipient.find(123)
Traceback (most recent call last):
TypeError (nil can't be coerced into Integer)
irb > recipient
#<Recipient ...
The error is only in the output – the assignment is working. It only occurs when using the --nomultiline
option, and thus [only with IRB 1.2.0+ and before Ruby 3](https://github.com/makandra/geordi/blob...
TLDR
Using
.includes
or.eager_load
with 1-n associations is dangerous. Always use.preload
instead.
Consider the following ActiveRecord query:
BlogPost.eager_load(
:comments
:attachments,
).to_a
(Let's assume we only have a couple of blog posts; if you use pagination the queries will be more complicated, but the point still stands.
Looks harmless enough? It is not.
ActiveRecord will rewrite this into a query using LEFT JOIN
s which looks something like this:
SELECT "blog_posts...
In the discussion of the difference between include
and extend
in Ruby, there is a misconception that extend
would add methods to the singleton class of a ruby object as stated in many posts on this topic. But in fact, it is added to the ancestors chain of the singleton class! Even though it is technically not the same, practically this can be considered the same in most use cases.
This means, that we are able to overwrite these methods or call the parent version with super
depending in which order and in whi...
Most of our applications use CarrierWave for file uploads. CarrierWave has an integrated processing mechanism for different file versions with support for ImageMagick through CarrierWave::MiniMagick
(which requires the mini_magick
gem). In case your processing runs into an error, CarrierWave will just swallow it and rethrow an error with a very generic message like Processing failed. Maybe it is not an image?
which does not help you finding out what the actual problem is. CarrierWave probably does this for security purposes, but does n...
I recently stumbled over a problem that my feature tests broke in CI because of a mismatching chromedriver version.
In this specific project we have a fixed Chromium version in a Debian 12 environment instead of Chrome. The tests however used a recent chrome version instead.
$ chromedriver --version
ChromeDriver 117.0.5938.149 (e3344ddefa12e60436fa28c81cf207c1afb4d0a9-refs/branch-heads/5938@{#1539})
$ chromium --version
Chromium 117.0.5938.149 built on Debian 12.1, running on Debian 12.1
> WARN Selenium [:selenium_manager] The chromed...
Given you have an array column like this:
create_table "users", force: :cascade do |t|
t.integer "movie_ids", default: [], array: true
end
You might think that the following queries yield the same result:
User.where(movie_ids: [16, 17])
User.where(movie_ids: [17, 16])
Turn's out - they are not! They do care about array ordering more than I do.
To query for identical arrays independent of their order you have to either:
Jasmine is a great way to unit test your JavaScript components without writing an expensive end-to-end test for every small requirement.
After we integrated Jasmine into a Rails app we often add an E2E test that opens that Jasmine runner and expects all specs to pass. This way we see Jasmine failures in our regular test runs.
In a [feature spec](https://relishapp.com/rspec/rspec-rails/docs/feature-spec...
Collection of useful tools in the Chrome JavaScript console.
This is not special to Chrome, but still a clever thing:
document.body.contentEditable=true
You can easily measure the time on the console with named timers:
console.time('myTime'); // Start timer
console.timeEnd('myTime'); // End timer and print the time
Variables $0
, $1
, ... $n
reference the nth-last inspected Element. $0
...
When you allow file uploads in your app, a user might upload content that hurts other users.
Our primary concern here is users uploading .html
or .svg
files that can run JavaScript and possibly hijack another user's session.
A secondary concern is that malicious users can upload executables (like an .exe
or .scr
file) and use your server to distribute it. However, modern operating systems usually warn before executing files that were downloaded from t...
You can use git worktree
to manage multiple working trees attached to the same repository. But why should I use git worktree
?
You can use more than one working tree to ...
... run tests while working on another branch
... compare multiple versions
... work on a different branch without disturbing your current branch
Creating a new working tree is as simple as creating a new branch. You only need to execute git worktree add <path> <branch>
. When you are done, you can remove the working tree with git worktree remove <Worktree>
...
TL;DR Use user.update!(remove_avatar: true)
to delete attachments outside of forms. This will have the same behavior as if you were in a form.
As you know, Carrierwave file attachments work by mounting an Uploader
class to an attribute of the model. Though the database field holds the file name as string, calling the attribute will always return the uploader, no matter if a file is attached or not. (Side note: use #present?
on the uploader to check if the file exists.)
class User < ApplicationRecord
mount :avatar, ...
Basically, you now need to know if your project uses a "real" time zone or :local
, and if config.active_record.time_zone_aware_attributes
is set to false
or not.
With time zones configured, always use .current
for Time
, Date
, and DateTime
.
ActiveRecord attributes will be time-zoned, and .current
values will be converted properly when written to the database.
Do not use Time.now
and friends. Timezone-less objects will not be converted properly when written to the database.
With no/local time zone use Time.now
, `...
View specs are a powerful tool to test several rendering paths by their cases instead of using a more costing feature spec. This is especially useful because they become quite convenient when used with Capybara::Node::Finders and Capybara::RSpecMatchers. This allows within view specs to isolate specific parts of the render...
rspec >= 3.1 brings a method and_wrap_original
. It seems a bit complicated at first, but there are use cases where it helps to write precise tests. For example it allows to add expectations on objects that will only be created when your code is called.
If you have older rspec, you could use expect_any_instance_of
, but with the drawback, that you can't be sure if it really was the correct instance which got the message.
The example model uses different validators based on a flag:
class MyModel < ApplicationRecord
...
Whenever is a Ruby gem that provides a nicer syntax for writing and deploying cron jobs.
Leading zeros are important for whenever if you use the 24-hours format!
This schedule.rb
:
every 1.day, at: '3:00', roles: [:primary_cron] do
runner 'Scheduler.delay.do_things'
end
will lead to this crontab entry (crontab -l
) with the default configuration:
0 15 * * * /bin/bash -l -c 'cd /var/www/my-project/releases/20180607182518 && bin/rails runner -e production '\''Scheduler.delay.do_things'\'''
Which would run on 3...
RSpec provides a nice diff when certain matchers fail.
Here is an example where this diff is helpful while comparing two hashes:
{a:1}.should match(a:1, b:2)
Failure/Error: {a:1}.should match(a:1, b:2)
expected {:a=>1} to match {:a=>1, :b=>2}
Diff:
@@ -1,3 +1,2 @@
:a => 1,
-:b => 2,
Unfortunately, this diff is not as clever as it would need to. RSpec's instance_of
matchers will look like errors in the diff (even if they are not), and time objects that differ only in milliseconds won't appear in the ...
The recommended additional setup of the spreewald gem, a useful set of cucumber steps, includes adding a file for defining custom selectors which can be used as prose within steps:
When I follow "Edit" within the controls section
Where the controls section
can be any arbitrary defined css selector within selectors.rb
Often it can be useful to select the nth element of a specific selector. Luckily, this can ...
We regularly have tasks that need to be performed around a deploy. Be it to notify operations about changed application behavior, be it to run a little oneline script after the deploy. Most database-related stuff can be handled by migrations, but every once in a while, we have tasks that are much easier to be performed manually.
Here is how we manage the deploy tasks themselves: