Rails: Talking to the database without instantiating ActiveRecord objects
Instantiating ActiveRecord objects comes expensive. To speed up things, you can choose a more direct way to talk to your database: the ActiveRecord::ConnectionAdapters::DatabaseStatements
module.
Using the module and its methods is not suggested in the usual in-app workflow, as validations, callbacks, custom getters/setters etc. are ignored. However, for database-centered stuff like migrations, these fill the gap between writing pure SQL and full...
Nested ActiveRecord transaction pitfalls
When working with custom transactions and use ActiveRecord::Rollback
you may encounter unexpected behaviour if you try to roll back your changes.
tl;dr
When using nested transactions, ActiveRecord::Rollback
might not do what you expect, since it will only roll back the inner, but not the outer transaction.
You can fix this behavior by using transaction(joinable: false)
but this leads to a bunch of different problems.
When you don't need an explicit ActiveRecord::Rollback
, don't worry about any of this and just use a plan `tran...
Configure how VCR matches requests to recorded cassettes
VCR lets you configure how it matches requests to recorded cassettes:
In order to properly replay previously recorded requests, VCR must match new
HTTP requests to a previously recorded one. By default, it matches on HTTP
method and URI, since that is usually deterministic and fully identifies the
resource and action for typical RESTful APIs.You can customize how VCR matches requests using the `:match_requests_on casse...
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...
Debugging flickering VCR tests
We often use VCR to stub external APIs. Unfortunately VCR can have problems matching requests to recorded cassettes, and these issues are often hard to debug.
VCR's error messages mostly look like this and are not very helpful:
An HTTP request has been made that VCR does not know how to handle:
POST http://another-site.de:9605/json/index
VCR fails if the request does not exactly look like the request it has recorded. If the request is d...
Styling SVGs with CSS only works in certain conditions
SVG is an acronym for "scalable vector graphics". SVGs should be used whenever an image can be described with vector instructions like "draw a line there" or "fill that space" (they're not suited for photographs and the like). Benefits are the MUCH smaller file size and the crisp and sharp rendering at any scale.
It's a simple, old concept brought to the web – half-heartedly. While actually all browsers pretend to support SVG, some barely complex use cases get you beyond common browser support.
In the bas...
Git error: "badTimezone: invalid author/committer line - bad time zone"
You might get the above error message when cloning certain git repositories (for example the rails repository). It indicates that there is a malformed timestamp in some commit, and your git installation is configured to validate it.
As a workaround, you can disable the validation using
git config --global fetch.fsckobjects false
This settings seems to be the default for most git installations anyways.
makandra/gemika: Helpers for testing Ruby gems
We have released a new library Gemika to help test a gem against multiple versions of Ruby, gem dependencies and database types.
Here's what Gemika can give your test's development setup (all features are opt-in):
- Test one codebase against multiple sets of gem dependency sets (e.g. Rails 4.2, Rails 5.0).
- Test one codebase against multiple Ruby versions (e.g. Ruby 2.1.8, Ruby 2.3.1).
- Test one codebase against multiple database types (currently MySQL or PostgreSQL).
- Compute a matrix of all possib...
Sass: How to convert an RGBA color to its RGB look-alike
Say you have an RGBA color that you need as a non-transparent color because of reasons.
Basically, this is possible. Just understand that you will convert your RGBA color for exactly one base background color as you are giving up transparency.
Most likely, your background is white, so you'll use #fff
as that for examples below.
Simple approach
When your know the RGBA color's base RGB color (e.g. your brand color that you RGBA'd for some hover effect), you can simply use the mix
function instead of rgba
.
Before:
backgroun...
VCR fails if the same request is triggered multiple times
Same requests are recorded only once in vcr. Replaying a test fails, if you trigger the same request multiple times. The error message is somehow confusing, as your cassette contains the request:
An HTTP request has been made that VCR does not know how to handle
If you want to allow to match a request multiple times, you need to configure this explicit with allow_playback_repeats: true. Some exa...
Hack of the day: One-liner to run all changed Cucumber features
Similar to our snippet that runs all Cucumber features matching a given string, the following will run all modified or new Cucumber features by looking at your git status:
git status --short | grep -v '^ D ' | grep '.feature' | sed 's/.. //' | tr '\n' ' ' | xargs geordi cucumber
If you want to know what each of the above commands does, see [explainshell](http://explainshell.com/explain?cmd=git+status+--short+%7C+grep+-v+%27%5E+D+%27+%7C+grep+%27.feature%27+%7C+sed+%27s%2F..+%2F%2F%27+%7C+tr+%27%5Cn%27+%27+%27+%7C...
How to use Haml in your helpers
You know those helper methods that just render some HTML but look weird because of content_tag
s all over the place? You could also use Haml instead.
Example
Consider the following helper.
def greeting
message = ''.html_safe
message << 'Welcome to '
message << content_tag(:span, Rails.env, class: 'greeting--location')
content_tag :div, message, class: 'greeting'
end
That looks clumsy and is hard to read.
Wouldn't it be nicer to say something like this?
def greeting
render_haml <<-HAML
...
Minidusen: Low-tech record filtering with LIKE queries
We have a new gem Minidusen which extracts Dusen's query parsing and LIKE
query functionality.
Minidusen can no longer index text in MySQL FULLTEXT columns, which was hardly used and didn't always help performance due to the cost of reindexing.
Minidusen is currently compatible with MySQL, PostgreSQL, Rails 3.2, Rails 4.2 and Rails 5.0.
Basic Usage
Our example will be a simple address book:
class Contact < ActiveRecord::Base
validates_presence_of :name, :street, :city, :e...
Geordi 1.5.1 released
- Improve
geordi cucumber
: Only attempt @solo run when the specified files contain the @solo tag, skip @solo run if any filename is passed with a line number (e.g.features/example.feature:3
) - Improve
geordi deploy
: Find stages by their prefix (e.g.s
-> staging,m
-> makandra), bundle if needed, check the selected stage exists - Improve
geordi server
: Takes port as argument (e.g.geordi ser 3001
), option--public
(-P
) starts the server with-b 0.0.0.0
to make it accessible from other machines in the local network, e.g. ...
Capistrano: exclude custom bundle groups for production deploy
Capistrano is by default configured to exclude the gems of the groups development
and test
when deploying to the stages production
and staging
. Whenever you create custom groups in your Gemfile
, make sure to exclude these, if they should not be deployed to the servers. The gems of these groups might not be loaded by rails, however, the deployment process will take longer as the gems will be downloaded and installed to the server.
e.g. to exclude the groups cucumber
and deploy
, add the following to `config/deploy/production.rb...
Using Spring and parallel_tests in your Rails application
You want Spring for super-fast binstubs like bin/rails
or bin/rspec
which avoid Rails boot time.
You want parallel_tests to speed up full test runs of large test suites.
Unfortunately, you do not want parallel_tests to use your Spring binstubs as those parallelized tests will share data and/or loose some information. There are some issues about this on GitHub and there is a suggested [workaround](https:...
Git: how to work with submodules
Sometimes you might need to nest a git-project inside another git-project. The right strategy is to use submodules in this case.
How git submodules work
- Each submodule is a own git repository
- Once you commit changes in a submodule, the parent repository can link the new
sha
as its reference - You need to take care manually that your git submodules are up-to-date and changes in the submodules are linked in the parent repository
Add a submodule
Here is how you add a nested project inside your parent project
$ git submodule...
MySQL: How to dump single tables instead of a complete database
Sometimes you want to test migrations with production or staging data. Dumping single tables makes sense if a complete dump would be to big.
mysqldump -u deploy_user -p application_production table1 table2 table2 > table1_table2_table2.sql.dump
Hint: If a table has to many constraints, a complete dump could be more handy.
Further reading:
- How to load only a subset of a massive MySQL dump
- [How to import production database dump t...
Angular directive scope binding with = (equals)
Angular directives with isolate scopes have three different variable binding strategies, of which one is =
. Example:
# HTML
<panel value="parent.someFn() && false" twoway="parent.someProperty"></div>
# Coffeescript
@app.directive 'panel', ->
scope:
evaluated: '=value'
bound: '=twoway'
link: ->
scope.evaluated # = false
scope.bound = 'foo' # Updates parent.someProperty
HTML attributes bound with =
(value
, twoway
) have their value evaluated as Angular expression in the parent scope's context and have the ...
Angular isolate scopes: Calling a parent scope function with externally defined arguments
Isolate scopes offer three kinds of variable binding. One of them is &
, allowing to bind a property of the isolate scope to a function in the parent scope. Example:
# HTML
<panel proxy="parent.someFunction(arg1, arg2)"></div>
# Coffeescript
@app.directive 'panel', ->
scope:
parentFn: '&proxy'
link: (scope) ->
scope.parentFn(arg1: 'first', arg2: 'second')
In this dumb example, the panel
directive will call its scope's parentFn()
function with two arguments, which proxies to parent.someFunction('first', 'second')
...
Sass: How to do math with shorthand values inside variables
If you need to modify (e.g. add 2px) a Sass variable that defines multiple values as one (e.g. for short-hand CSS definitions such ass padding
), you can by using nth
. It's ugly.
While you could split up such variables into multiple values (e.g. combined padding into one for vertical and one for horizontal padding) in your own Sass definitions, when using some framework definitions like bootstrap-sass
, those variables are defined outside your reach.
The following is helpful if you really want to use values from such variables. However...
How to human-join an array in JavaScript
To simulate Rails' to_sentence
in your JavaScript application, you can use these few lines of CoffeeScript code:
joinSentence = (array) ->
if array.length > 1
array[0..-2].join(', ') + ', and ' + array[-1..]
else
array.join ', '
Examples:
> joinSentence(['cats', 'dogs', 'pandas'])
# => 'cats, dogs, and pandas'
^
> joinSentence(['llamas'])
# => 'llamas'
Here is some plain JavaScript, should you prefer that:
function joinSentence(array) {
if (array.length > 1) {
return ar...
Your browser might silently change setTimeout(f, 0) to setTimeout(f, 4)
When you're nesting setTimeout(f, 0)
calls, your browser will silently increase the delay to 5 milliseconds after the fourth level of nesting.
This is called "timeout clamping" and defined in the HTML spec:
If nesting level is greater than 5, and timeout is less than 4, then set timeout to 4.
Timeouts are clamped harder in background tabs
On a similar note, all major browsers have implemented throttling rules for setInterval
and setTimeout
calls from tabs...
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 ...