ActiveRecord subselects - Today I Learned
Apparently you can pash a second scope to a hash-condition and the whole thing will be evaluated as a second SELECT
statement with a subselect.
Note that sub-queries are extremely slow in MySQL, but they can make cases easier where performance does not matter so much (e.g. a migration on 50K records).
has_one association may silently drop associated record when it is invalid
This is quite an edge case, and appears like a bug in Rails (4.2.6) to me.
Update: This is now documented on Edgeguides Ruby on Rails:
If you set the :validate option to true, then associated objects will be validated whenever you save this object. By default, this is false: associated objects will not be validated when this object is saved.
Setup
# post.rb
class Post < ActiveRecord::Base
has_one :attachment
end
# attachm...
Download Ruby gems without installing
You can download .gem
files using gem fetch
:
gem fetch activesupport consul
This will produce files like active-support-5.0.0.gem
and consul-0.12.1.gem
in your working directory.
Dependencies will not be downloaded.
Linux: Find out which processes are swapped out
Processes in Linux might be put into Swap ("virtual memory") occasionally.
Even parts of a single process might be removed from memory and put into Swap.
In order to find out which processes remain within Swap, run this:
sudo grep VmSwap /proc/*/status | egrep -v "0 kB"
Keep in mind Swap is not evil by definition. Some bytes per process beeing put to Swap will not have that much of performance influence.
If you want the Linux virtual memory manager (which is responsible for the decision if and which processes are moved to Swap) to be...
Tasks, microtasks, queues and schedules - JakeArchibald.com
The way that Javascript schedules timeouts and promise callbacks is more complicated than you think. This can be the reason why callbacks are not executed in the order that they are queued.
Please read this article!
This is an extract of the example in the article which demonstrates the execution order of tasks and microtasks.
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0);
Promise.resolve().then(function() {
console.log('promise1');
}).then(function() {
console.log('promise2');
})...
Rails Env Widget
Have you ever mistaken one Rails environment for another? The attached helper will help you to never do it again.
Save the attached file to app/helpers/ and use the widget in your layout like this:
%body
= rails_env_widget unless Rails.env.production?
It'll render a small light gray box in the top left corner of your screen, containing the current Rails environment. On click, it'll disappear. Actually, it has the same UX as our Query Diet widget.
Dynamically uploading files to Rails with jQuery File Upload
Say we want …
- to create a
Gallery
that has a name andhas_many :images
, which in turn have a caption - to offer the user a single form to create a gallery with any number of images
- immediate uploads with a progress bar per image
- a snappy UI
Enter jQuery File Upload. It's a mature library that can do the job frontend-wise. On the server, we'll use Carrierwave, because it's capable of caching images.
(FYI, [here's how to do the u...
UI Sortable on table rows with dynamic height
UI sortable helps reordering items with drag 'n drop. It works quite fine.
Proven configuration for sorting table rows
When invoking the plugin, you may pass several options. This set is working fine with table rows:
$tbody.sortable # Invoke on TBODY when ordering tables
axis: 'y' # Restrict drag direction to "vertically"
cancel: 'tr:first-child:last-child, input' # Disable sorting a single tr to prevent jumpy table headers
containment: 'parent' # Only drag within this container
placehol...
Javascript: Wait until an image has finished loading
The attached ImageLoader
helper will start fetching an image and return an image that is resolved once the image is loaded:
ImageLoader.load('/my/image.png').then(function(image) {
...
});
The image
argument that is yielded to the promise callback is an HTMLImageElement
. This is the kind of object you get when you call new Image()
.
How to fix: "rake db:rollback" does not work
When you run rake db:rollback
and nothing happens, you are probably missing the latest migration file (or have not migrated yet).
$ rake db:rollback
$
If that happens to you, check your migration status.
$ rake db:migrate:status
up 20160503143434 Create users
up 20160506134137 Create pages
up 20160517112656 Migrate pages to page versions
up 20160518112023 ********** NO FILE **********
When you tell Rails to roll back, it tries to roll back the latest change that was mi...
postgres_ext: additional Rails bindings for PostgreSQL
Adds missing native PostgreSQL data types to ActiveRecord and convenient querying extensions for ActiveRecord and Arel for Rails 4.x
Common table expressions
- Relation#with
- Model.from_cte
Arrays
Face.where.contains tags: %w[happy smiling] # Matching faces have both 'happy' and 'smiling' tags
Face.where.overlap tags: %w[happy smiling] # Matching faces have at least one of these tags
Face.where.any tags: 'happy' # Matching faces include the 'happy' tag
Face.where.all tags: 'dunno' # Not documented, try for yourself
...
How to explain SQL statements via ActiveRecord
ActiveRecord offers an explain
method similar to using EXPLAIN
SQL statements on the database.
However, this approach will explain all queries for the given scope which may include joins
or includes
.
Output will resemble your database's EXPLAIN style. For example, it looks like this on MySQL:
User.where(id: 1).includes(:articles).explain
EXPLAIN for: SELECT `users`.* FROM `users` WHERE `users`.`id` = 1
+----+-------------+-------+-------+---------------+
| id | select_type | table | type | possible_keys |
+----+-----...
Introducing Helix: Rust + Ruby, Without The Glue
Helix allows you to implement performance-critical code of your Ruby app in Rust, without requiring glue code to bridge between both languages.
See attached article for a longer write-up about the why and how.
rroblak/seed_dump
This gem gives you a rake task db:seed:dump
do create a db/seeds.rb
from your current database state.
The generated db/seeds.rb
will look this:
Product.create!([
{ category_id: 1, description: "Long Sleeve Shirt", name: "Long Sleeve Shirt" },
{ category_id: 3, description: "Plain White Tee Shirt", name: "Plain T-Shirt" }
])
User.create!([
{ password: "123456", username: "test_1" },
{ password: "234567", username: "test_2" }
])
Install MySQL 5.6 in Ubuntu 16.04
Instead of using this hack you might want to use MariaDB 10.x which can work with both old and new apps.
An alternative could be to use the MySQL Docker image which is still updated for 5.6.
Ubuntu 16.04 only provides packages for MySQL 5.7 which has a range of backwards compatibility issues with code written against older MySQL versions.
Oracle maintains a list of official APT repositories for MySQL 5.6, but those repositories do...
VCR: An OAuth-compatible request matcher
OAuth requires a set of params to be carried along requests, among which a nonce. Some libraries pass these along as headers, some as query parameters. All fine.
When you're using VCR, the latter case is an issue. By default, requests are matched on method and URI. However, no request URI will equal another when they include a nonce. You won't be able to match these requests with VCR.
Solution
Obviously you need to...
Postgres Index Types
When creating an index using
CREATE INDEX
, Postgres will create a B-Tree type index by default. The B-Tree type is great for general purpose indexes but there are special cases when other types provide better results.
jQuery promises: done() and then() are not the same
jQuery's deferred objects behave somewhat like standard promises, but not really.
One of many subtle differences is that there are two ways to chain callbacks to an async functions.
The first one is done
, which only exists in jQuery:
$.ajax('/foo').done(function(html) {
console.debug("The server responded with %s", html);
});
There is also then
, which all promise libraries have:
$.ajax('/foo').then(function(html) {
console.debug("The server resp...
MySQL / MariaDB: Show disk usage of tables and columns
You can find out about disk space usage of all tables within your database by running this:
SELECT table_name AS `Table`, round(((data_length + index_length) / 1024 / 1024), 2) `Size (MB)` FROM information_schema.TABLES WHERE table_schema = "$your_database";
Replace $your_database
here.
To find out the disk usage of a single column:
SELECT sum(char_length($your_column))/1024/1024 FROM $your_table
Result is in megabytes again.
Stackprof - sampling call-stack profiler for ruby
Stackprof is a sampling call-stack profile for Ruby 2.1+.
Instead of tracking all method calls, it will simply collect the current stack trace of a running program at fixed intervals. Methods that appear on top of the stack trace most often, are the methods your program spends most of its time in.
The big advantage of this is that it is very fast. You can even enable it in production and collect real performance data. See the README on how to add it as a middleware. It will dump its data to the tmp
directory.
Sampling is by default base...
Linux: Open a file with the default application
If you are on a Linux shell and want to open a file with whatever default application is configured for that type, this often works:
xdg-open Quote.odt
xdg-open invoice.pdf
xdg-open index.html
Pro Tip
Make an alias so you have a simpler API (like Mac OS): alias open=xdg-open
or alias x=xdg-open
.
Background
You can choose your "Default applications" via UI in the Ubuntu "Settings" application (gnome-control-center
). This is just a very rough setting (e.g. open Photos with Shotwell Viewer).
If a certain file...
Testing ActiveRecord callbacks with RSpec
Our preferred way of testing ActiveRecord is to simply create/update/destroy the record and then check if the expected behavior has happened.
We used to bend over backwards to avoid touching the database for this. For this we used a lot of stubbing and tricks like it_should_run_callbacks
.
Today we would rather make a few database queries than have a fragile test full of stubs.
Example
Let's say your User
model creates a first Project
on cr...
Testing ActiveRecord validations with RSpec
Validations should be covered by a model's spec.
This card shows how to test an individual validation. This is preferrable to save an entire record and see whether it is invalid.
Recipe for testing any validation
In general any validation test for an attribute :attribute_being_tested
looks like this:
- Make a model instance (named
record
below) - Run validations by saying
record.validate
- Check if
record.errors[:attribute_being_tested]
contains the expected validation error - Put the attribute into a valid state
- Run...
record a logstalgia video
Cause logstaglia is so cool you may want to record a video. We're lucky: Logstalgia has a parameter for an ppm-stream output: --output-ppm-stream FILE
. We can pipe this to ffmpeg or avconv to record a h264 encoded video.
record command when using ffmpeg (for e.g. with ubuntu 12.04)
cat some_acces.log | logstalgia --sync -1920x1080 --output-ppm-stream - | ffmpeg -y -r 60 -f image2pipe -vcodec ppm -i - -vcodec libx264 -preset ultrafast -pix_fmt yuv420p -crf 1 -threads 0 -bf 0 logstalgia.mp4