Today I Learned

hashrocket A Hashrocket project

16 posts by craighafer

!important property

If you ever find yourself with conflicting rules on an element, and want one to take precedence even over rules with higher specificity. you can add the !important property, to override all other rules.

Here is an example:

#id {
  background-color: blue;
}

.class {
  background-color: gray;
}

p {
  background-color: red !important;
}
<p>This is some text in a paragraph.</p>

<p class="class">This is some text in a paragraph.</p>

<p id="id">This is some text in a paragraph.</p>

In this case, all of these <p> tags will have a red background.

Select options with option groups

ActionView::Helpers::FormOptionsHelper#grouped_options_for_select lets you pass in a nested array of strings, and returns a string of option tags wrapped with optgroup tags:

The first value serves as the optgroup label while the second value must be an array of options.

grouped_options = [
  ["North America",
    ["United States", "Canada"]],
  ["Europe",
    ["Denmark", "Germany", "France"]]
]

Next, simply call it from a form helper in the view, passing in your grouped options.

<%= f.select :location, grouped_options_for_select(grouped_options) %>

Voila! You should now have something like this: image

Endless Range

If you have a Range that you want to extend infinitely in either direction, just simply leave it blank.

Here’s a simple example:

def age_category(age)
  case age
  when (...0)
    "unborn"
  when (0..12)
    "youngling"
  when (13..17)
    "teenager"
  when (18..64)
    "adult"
  when (65..)
    "old"
  end
end
>> age_category    0 => "youngling"
>> age_category   13 => "teenager"
>> age_category   18 => "adult"
>> age_category   65 => "old"
>> age_category  999 => "old"
>> age_category -999 => "unborn"

In a situation like this it’s nice to extend infinitely, rather than having to come up with some kind of arbitrary cutoff age like 100, that could in rare cases cause problems.

H/T Matt Polito for showing me this.

Nil is actually NilClass

If for whatever reason you wanted to modify something inside nil, the class name is NilClass

🤯 Yes it’s very mind blowing, I know 🤯

Example of bad code I couldn’t figure out why it wasn’t working

class Nil
  def to_i
    -1
  end
end

The fix needed to make it behave as expected

class NilClass
  def to_i
    -1
  end
end

CSS Filter Property

There is a CSS property filter which allows you to manipulate properties of an element such as their blur, brightness, contrast, grayscale, opacity, and more. This is most often applied to images, but does work on any element.

.single-filter {
  filter: opacity(50%);
}
.multiple-filters {
  filter: blur(5px) grayscale(100%);
}

Here comes our friendly neighborhood Pikachu to help show us what this looks like: image

Here is a good reference for what filter can do.

Returning to normal mode

When my keyboard randomly lost functionality of the ESC key, I was left unable to escape out of insert mode, back into normal mode.

If you ever find yourself in this conundrum, you can use CTRL-C to escape back to normal mode.

The caveat to this is that CTRL-C does not trigger abbreviations or the InsertLeave event.

Saving screenshots to clipboard on Mac

Have you ever needed to take a screenshot just to send it to somebody, but then you are left with the cumbersome chore of having to actually delete the screenshot before they pile up on your desktop like a pile of dirty laundry?

Well, I am here to save you those 5 seconds you’ve been missing out on so you can enjoy that next sip of coffee–guilt free.

When taking a screenshot with CMD + shift + 3, hold down control as well.

When taking a screenshot with CMD + shift + 4, hold down control while dragging the crosshairs to select a section of screen to capture.

Now, instead of saving to your default screenshot location, it will just copy it to your clipboard. You can now just paste the image into your message with no cleanup necessary.

TL;DR
Hold down control when taking a screenshot to copy it to the clipboard.

Alternate ways to quit out of Vim

In an effort to increase my Vim knowledge, I stumbled across a blog post by rocketeer alumnus Josh Branchaud. His post covers a few ways to quit out of vim and it is worth the read.

In there I found these two useful ways for quitting out of Vim from Normal mode, as opposed to Command mode.

ZZ in normal mode is equivalent to :x   in command mode.
ZQ in normal mode is equivalent to :q! in command mode

Logging data as a table in the console

I’m sure you’re already familiar with console.log() to debug, but did you know that there is a similar console.table() that is great for displaying arrays and objects?

Here are some examples,

Assuming you had an array of names > img

Assuming you had a person object > img

Assuming you had an array of person objects > img

There is also an optional columns parameter, which takes an array containing the names of columns you want to include in the output.

console.table(data)
console.table(data, columns)

Match strings with regular expressions

In Ruby you can use String#=~ to compare a string with regexp, returning the first index where it is found. For example let’s search for the first ? in this string:

"www.example.com/search?meatloaf" =~ /\?/ 
=> 22

If there is no match, it returns nil

"www.example.com" =~ /\?/ 
=> nil

BONUS: When using Regexp#=~, which functions very similarly, you can use a regexp with named captures to store them in local variables.

/(?\?.+)/ =~ "www.example.com/search?lasagna"
=> 22
search_params
=> "?lasagna"

Make numbers more readable in a Rails view

Rails has a number of handy helper methods.

Specifically, in ActionView::Helpers::NumberHelper there is the method number_with_delimiter

If you want to display the number 100000 and have people know right away whether it is 1 million or 100 thousand, just pass it to number_with_delimiter and it will return "100,000".

Some useful optional keyword parameters:
delimiter:"🍔" replaces the default , delimiter. (100000 becomes 100🍔000)
separator:"🍕" replaces the default . separator. (100.56 becomes 100🍕56)

String concatenation in Ruby

My first instinct when it comes to concatenating strings would be to use the += operator:

name = "Peter"
=> "Peter"

name.object_id
=> 15320

name += " Parker"
=> "Peter Parker"

name.object_id
=> 34480

However, as you can see, doing this creates a new object. Instead, << should be used to maintain the same string object and also improve performance when working on larger batches of strings.

name = "Peter"
=> "Peter"

name.object_id
=> 54960

name << " Parker"
=> "Peter Parker"

name.object_id
=> 54960