3623 cards
View
Repeats

How to search through logs on staging or production environments

We generally use multiple application servers (at least two) and you have to search on all of them if you don't know which one handled the request you are looking for.

Rails application logs usually live in /var/www/<project-environment-name>/shared/log.
Web server logs usually live in /var/www/<project-environment-name>/log.

Searching through single logs with grep / zgrep

You can use grep in this directory to only search the latest logs or zgrep to also search older (already zipped) logs. zgrep is used just like grep a…

During deployment: "You are trying to install in deployment mode after changing your Gemfile"

While deploying an Ruby update to an old application these days, we encountered the following misleading error:

*** [err :: some-host.makandra.de] You are trying to install in deployment mode after changing
*** [err :: some-host.makandra.de] your Gemfile. Run `bundle install` elsewhere and add the
*** [err :: some-host.makandra.de] updated Gemfile.lock to version control.
*** [err :: some-host.makandra.de] 
*** [err :: some-host.makandra.de] You have deleted from the Gemfile:
*** [err :: some-host.makandra.de] *

We found out a newe…

Repeats

Authorize allowed values with assignable_values

All our projects have enum-like requirements like this:

  • An attribute value must be included in a given set of values.
  • The list of allowed values must be retrievable in order to render <select> boxes.
  • Each value has a humanized label.
  • Sometimes there is a default value.

Most of the time, this requirement is also needed:

  • The list of assignable values depends on the user who is currently signed in.

In our past projects there are many different solutions for these related requirements, e.g. ChoiceTrait, methods like `available_…

Linked contentRepeats

Databases don't order rows unless you tell them so

There is no such thing as a "default order" of rows in database tables.

For instance, when you paginate a result set: When using LIMIT, it is important to use an ORDER BY clause that constrains the result rows into a unique order. Otherwise you will get an unpredictable subset of the query's rows. You might be asking for the tenth through twentieth rows, but tenth through twentieth in what ordering? The ordering is unknown, unless you specified ORDER BY.

In Rails, if you use Record.first or Record.last, it will default to orderin…

Repeats

Enumerators in Ruby

Starting with Ruby 1.9, most #each methods can be called without a block, and will return an enumerator. This is what allows you to do things like

['foo', 'bar', 'baz'].each.with_index.collect { |name, index| name * index }
# -> ["", "bar", "bazbaz"]

If you write your own each method, it is useful to follow the same practice, i.e. write a method that

  • calls a given block for all entries
  • returns an enumerator, if no block is given

How to write a canonical each method

To write a metho…

Repeats

Imagemagick: Batch resize images

Trick: Do not use convert but mogrify:

mogrify -resize 50% *

This overwrites the original image file.

In contrast, convert writes to a different image file. Here is an example if you need this:

cd /path/to/image/directory
for i in `ls -1 *jpg`; do convert -resize 50% $i "thumb_$i"; done
Repeats

How to Work With Time Zones in Rails

With different time zones

When dealing with time zones in Rails, there is one key fact to keep in mind:

Rails has configurable time zones, while
Ruby is always in the server's time zone

Thus, using Ruby's time API will give you wrong results for different time zones.

For consistency, you should only use Rails' methods, but the hard thing is to know which method originates from Ruby and which from Rails. To simplify this, adhere to the following suggestion:

Use Time.zone for everything time-related

```
# Examp…

Linked content

How to doubleclick in Selenium

Put the attached file into features/support/.

Example usage:

When /^I open the task named "(.+?)"$/ do |task_name|
  task = page.all('.task').detect do |t|
    t.find('.label').text.downcase == task_name.downcase
  end
  
  task.double_click
end

Note: only Selenium understands doubleclicks.\ Credits: the attached Capybara issue discussion.

Why you can't use timezone codes like "PST" or "BST" for Time objects

Rails' ActiveSupport::TimeWithZone objects have both a timezone code and offset, e.g. Thu, 28 Mar 2019 16:00:00 CET +01:00. Ruby's stdlib TZInfo also has time zones, but with different identifiers.
Unfortunately, not all timezone codes can be used to parse strings or to move time objects into another time zone.

Some timezone codes like CET are supported by ActiveSupport extensions like String#in_time_zone, while many codes will actually not work:

``` » '2019-03-01 12:00'.in_time_zone('PST')
ArgumentError (Invalid Timezone: PST) …

Repeats

Custom error pages in Rails 3.2+

Starting with Rails 3.2, there is a nicer way to display custom error pages (i.e. "page not found") that does not interfere with ExceptionNotifier. (I'm not sure about Airbrake et al.)

José Valim has posted this on his blog, here is a slightly more verbose rundown:

  1. Register your own app as the application responsible for showing error pages by adding

    config.exceptions_app = self.routes
    

    to your config/application.rb.

  2. Add rout…

Linked content

Git: Revert one or more commits

Reverting a commit means creating a new commit that undoes the old changes.

Imagine the following commit history:

* commit_sha3 [Story-ID 1] Fixup for my feature 
* commit_sha2 [Story-ID 5] Other feature
* commit_sha1 [Story-ID 1] My feature 

You can revert a single commit using the following syntax:

git revert commit_sha2

To revert changes that are split across multiple commits, use the --no-commit flag.

git revert --no-commit commit_sha3
git revert --no-commit commit_sha1
git commit -m "Revert Story 1"
Repeats

MySQL: Creating many records works faster in a transaction

When you need to insert many records into the same table, a fast way to do it is to have a single INSERT statement describing multiple rows. Unfortunately there is no way to do this through ActiveRecord.

What you can do to save time is to open a transaction and save multiple records within that transaction:

transaction do
  500.times { Model.create! }
end

Although you will still trigger 500 INSERT statements, they will complete considerably faster.

When I trie…

CSS: Flex and "min-width"

min-width is known as a CSS property that can be set to define a least width for an element. Surprisingly, it can also be used to set something that feels like max-width.

min-width in a flex context

While the default min-width value is 0 (zero), for flex items it is auto. This can make block elements take up much more space than desired, even stretching their container beyond the screen edge on small screens.

Image

[…

Using local fonts with Webpack / Webpacker

When we want to use our own (or bought) fonts in an application with Webpack(er), we have two options. We can

  • put the fonts directly into your Webpack's assets folder or
  • write an npm package with an own sass file that can be imported from the Webpack manifest.

Load fonts from your assets folder

The first option turns out to be straightforward: Import the stylesheets in the index.js of the pack you're using:

```javascript
// webpack_source_path/application/index.js

import './stylesheets/reset'
import…

rails_state_machine 1.1.2 released

Fixed bugs where calling valid? would change the record's state.

How to fix parallel_tests with Redis on powerful machines

When you have a powerful machine with many CPU cores, you might run into an error like

ERR DB index is out of range (Redis::CommandError)

This is because Redis defaults to at most 16 databases (0 to 15) and running tests in parallel might exceed that (your tests might run on databases 1..n or 2..(n+1)).

You can increase that limit:

  1. Get number of CPUs of your machine.

    nproc --all
    
  2. Open up Redis configuration file.

    sudo vim /etc/redis/redis.conf
    
  3. Find databases row and increase it, e.g. set to CPU cou…

Repeats

Shortcut for getting ids for an ActiveRecord scope

You can use .ids on an ActiveRecord 4+ scope to pluck all the ids of the relation

User.where("users.name LIKE 'Foo Bar'").ids

# same as
User.where("users.name LIKE 'Foo Bar'").pluck(:id)
Repeats

MySQL: Careful when using database locks in transactions

We tend to use database transactions as a magic bullet to get rid of all our concurrency problems. When things get really bad, we might even throw in some locking mechanism, but then are usually done with it.

Unfortunately, transactions semantics in databases are actually very complicated, and chances are, your making some incorrect assumptions.

The MySQL innodb engine actually has [four different modes](ht…

This website uses cookies to improve usability and analyze traffic.
Accept or learn more