Git: Show commits that have touched specific text in a file
If you want to find the commits that touched a specific text in a file, use
git log -S 'text in the code' -- path/to/file
If you use tig you may run a similar command to get a navigatable list of affected files:
tig -S'text in the code'
Example
Here is an example, where the move of the convert_number_column_value(value)
method in active record is traced (simplified output):
git log -n 1 --pretty=oneline -S 'convert_number_column_value(value)' -- activerecord/lib/active_record/base.rb
ceb33f84933639d3b6...
How Rails chooses error pages (404, 500, ...) for exceptions
When your controller action raises an unhandled exception, Rails will look at the exception's class
and choose an appropriate HTTP status code and error page for the response.
For instance, an ActiveRecord::RecordNotFound
will cause Rails to render a red "The page you were looking for doesn't exist" with a status code of "404" (not found).
The mapping from exception classes to error types is a hash in Rails.configuration.action_dispatch.rescue_responses
. The...
Case sensitivity in PostgreSQL
PostgreSQL, unlike MySQL, treats strings as case sensitive in all circumstances.
This includes
- comparison with
=
andLIKE
- collision detection in unique indexes
Usually this is fine, but some strings (like emails and usernames) should typically be treated as case insensitive.
There are a few workarounds available:
- use the citext extension (not recommended)
- use
ILIKE
instead ofLIKE
- use Postgres'
lower()
function - add an index on
lower(email)
Probably th...
Stop animations and network polling when the document tab isn't visible
Is your application doing something expensive every few seconds? Maybe an animated slider that rotates images? Maybe you are updating data over the network every five minutes?
It's a good idea to pause this if the your document tab is not even visible to the user. This saves your user's battery and data plan.
You can ask document.visibilityState
whether this tab is visible:
function pulse() {
if (!document.visibilityState || document.visibilityState...
How to find out what is running on a port on a remote machine
By convention, common protocols use a defined port, like 80 for HTTP or 443 for HTTPS.
You can use nmap
to find out what service is running behind a given port, and most often see some details about it. This can be helpful if servers don't offer the services you expect for some ports. If you'd like to see what ports are listing on your local machine, you might want to use netstat
instead of nmap
.
Note that nmap's service discovery may trigger several requests.
Example
When using nmap, adding the -A
switch ...
Building web applications: Beyond the happy path
When building a web application, one is tempted to claim it "done" too early. Make sure you check this list.
Different screen sizes and browsers
Desktops, tablets and mobile devices have all different screen resolutions. Does your design work on each of them?
- Choose which browsers to support. Make sure the page looks OK, is usable and working in these browsers.
- Use @media queries to build a responsive design
- If you do not suppo...
How to force horizontal panel layout for Chrome
Chrome's developer tools automagically choose vertical or horizontal panel layout, based on their width. You can disable that magic.
In the developer tools, klick the cogwheel icon (or press F1
when focusing the dev tools) to open the settings overlay.
Under "Preferences", in the "Appearance" section, find the "Panel layout" option. Set it to your liking.
Alternatively, press Ctrl+Shift+P and search for "panel layout".
Wat?
Vertical means that the DOM tree is next to the styles/etc panel, like so:
.to receive(:foo).with('arg1', 'arg2')
This expectation would be met with this call:
object.foo('arg1', 'arg2')
But what if the argument is expected to be an object with a given set of methods? E.g. this class with #first_name
and #last_name
methods:
class Person
def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end
attr_reader :first_name, :last_name
end
``...
Stretching an HTML page to full height
This card existed before, but was outdated due to browser implementation changes. The information below is validated for the current list of browsers we support.
By default your html
and body
elements are only as high as the actual page content inside their container. If you only have two lines of text in your page, your html
and body
elements will only be around 40 pixels high, regardless of the size of your browser window.
You might be surprised by this, since setting a background
on either html
and `body...
Heads up: RSpec's diffs may not tell the truth
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 ...
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...
Rails route namespacing (in different flavors)
TL;DR There are three dimensions you can control when scoping routes:
scope module: 'module', path: 'url_prefix', as: 'path_helper_name' do
resources :examples, only: :index
end
as
→ prefixes path helpers: path_helper_name_examples_path
and path_helper_name_examples_url
path
→ prefixes URL segments: /url_prefix/examples
module
→ nests the controller: controller Module::ExamplesController
, found at app/controllers/module/examples_controller.rb with views in app/views/module/examples/.
These options work with ...
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...
RSpec 3 argument constraints use weak equality
If you expect method calls in RSpec 3, be aware that the argument matchers use very liberal equality rules (more like ===
instead of ==
).
For example:
expect(subject).to receive(:foo).with(MyClass)
subject.foo(MyClass) # satisfies the expectation
subject.foo(MyClass.new) # also satisfies the expectation
expect(subject).to receive(:bar).with(/regex/)
subject.bar(/regex/) # satisfies the expectation
subject.bar('regex') # also satisfies the expectation
This is usually not an issue, except when your method ...
HTTP 302 redirects for PATCH or DELETE will not redirect with GET
A HTTP 302 Found
redirect to PATCH
and DELETE
requests will be followed with PATCH
or DELETE
. Redirect responses to GET
and POST
will be followed with a GET
. The Rails form_for
helper will use a workaround to send POST
requests with a _method
param to avoid this issue for PATCH
/DELETE
.
If you make requests yourself, watch out for the following behavior.
When you make an AJAX request PATCH /foo
and the /foo
action redirects to /bar
, browsers will request PATCH /bar
. You probably expected the second requ...
Make Nokogiri use system libxml2
The nokogiri gem provides different packages for several platforms. Each platform-specific variant ships pre-built binaries of libxml2
, e.g. x86_64-linux
includes binaries for 64bit Linux on Intel/AMD. This significantly speeds up installation of the gem, as Nokogiri no longer needs to compile libxml2
.
However, this also means that for each security issue with libxml2
, Nokogiri maintainers have to update their pre-built binaries and release a new version of the gem. Then, you need to update and ...
Defining and calling lambdas or procs (Ruby)
Ruby has the class Proc
which encapsulates a "block of code". There are 2 "flavors" of Procs
:
- Those with "block semantics", called
blocks
or confusingly sometimes alsoprocs
- Those with "method semantics", called
lambdas
lambdas
They behave like Ruby method definitions:
- They are strict about their arguments.
-
return
means "exit thelambda
"
How to define a lambda
-
With the
lambda
keywordtest = lambda do |arg| puts arg end
-
With the lambda literal
->
(since Ruby 1.9.1)
...
Keeping web applications fast
Our applications not only need to be functional, they need to be fast.
But, to quote Donald Knuth,
premature optimization is the root of all evil (or at least most of it) in programming
The reasoning is that you should not waste your time optimizing code where it does not even matter. However, I believe there are some kinds of optimizations you should do right away, because
- they are either obvious and easy
- or they are very hard to do optimize later
This is an attempt to list some of those things:
On the server
...
Recommended Git workflow for feature branches
This is a guide on how to effectively use Git when working on a feature branch. It is designed to get out of your way as much as possible while you work, and ensure you end up with clean commits in the end.
We assume you are the only person working on this branch. We also assume the branch has never been "partially" merged into master.
You want to start a feature branch
git checkout master
git checkout -b my-feature-branch
git push -u origin my-feature-branch
You've added code that works ind...
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 m...
Escape a string for transportation in a URL
To safely transport an arbitrary string within a URL, you need to percent-encode characters that have a particular meaning in URLs, like &
or =
.
If you are using Rails URL helpers like movies_path(:query => ARBITRARY_STRING_HERE)
, Rails will take care of the encoding for you. If you are building URLs manually, you need to follow this guide.
Ruby
In Ruby, use CGI.escape
:
# ✅ good
CGI.escape('foo=foo&bar=bar')
=> "foo%3Dfoo%26bar%3Dbar"
Do not ever use `URI.en...