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 ss
instead of nmap
.
Note that nmap's service discovery may trigger several requests.
Example
When using nmap, adding the -A
switch will ...
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...
About the HTML and the BODY tag
The <html>
and <body>
tags both come with some non-default behavior that you know from other tags.
Do not try to style html
or body
for positioning, width/heigth, or similar. Every browser has its own caveats and you can not test them all.
Generally speaking:
- Use the
html
tag to define your page's default background color (because on short pages or large screens, yourbody
may not be as tall as the browser window). - Use the
html
tag to define a basefont-size
so you can use [rem
units](https://www.sitepoint.com/underst...
There is no real performance difference between "def" and "define_method"
You can define methods using def
or define_method
. In the real world, there is no performance difference.
define_method
is most often used in metaprogramming, like so:
define_method :"#{attribute_name}_for_realsies?" do
do_things
end
Methods defined via define_method
are usually believed to have worse performance than those defined via def
.
Hence, developers sometimes prefer using class_eval
to define methods using def
, like this:
class_eval "def #{attribute_name}_for_realsies?; do_things; end"
You can be...
Ruby 2.3 new features
Ruby 2.3.0 has been around since end of 2015. It brings some pretty nice new features! Make sure to read the linked post with its many examples!
Hash#fetch_values
Similar to Hash#fetch, but for multiple values. Raises KeyError
when a key is missing.
attrs = User.last.attributes
attrs.fetch_values :name, :email
Hash#to_proc
Turns a Hash into a Proc that returns the corresponding value when called with a key. May be useful with enumerators like #map
:
attrs.to_proc.call(:name)
attrs.keys.grep(/name/).map &attrs...
object-fit polyfill by lazysizes
All new browsers support the new object-fit
CSS property. It allows to specify how an element behaves within its parent element and is intended for images and videos. The most useful values are contain
(fit-in) and cover
(crop).
Unfortunately, IE does not support this yet. However, if you're already using lazysizes, you can use its object-fit polyfill!
Usage
In your Javascript manifest, require them like this:
#= require plugins/object-fit/ls.obj...
request_store: Per-request global storage for your Rails app
Ever needed to use a global variable in Rails? Ugh, that's the worst. If you need global state, you've probably reached for
Thread.current
.
When you're using Thread.current
, you must make sure you're cleaning up after yourself. Else, values stored in one request may be available to the next (depending on your server). request_store wipes all data when a request ends and makes per-request global storage a no-brainer. Internally, it's using Thread.current
with a Hash
in a simple middleware.
Example: Remembering all currently a...
Stubbing terminal user input in RSpec
Reading user input in console applications is usually done using Kernel#gets
. Stubbing that can be a bit hairy.
When your code expects user input, you can not say Kernel.stub(gets: 'user input')
. This will have no effect because of reasons.
Instead, you need to know which class will call gets
. For example:
described_class.any_instance.stub(gets: 'user input')
If you do not know where gets
is called, you can try something like this:
Object.any_instance.stub(gets: 'user input')
Any instance of an object should...
Testing terminal output with RSpec
When testing Ruby code that prints something to the terminal, you can test that output.
Since RSpec 3.0 there is a very convenient way to do that.
Anything that writes to stdout (like puts
or print
) can be captured like this:
expect { something }.to output("hello\n").to_stdout
Testing stderr works in a similar fashion:
expect { something }.to output("something went wrogn\n").to_stderr
Hint: Use heredoc to test multi-line output.
expect { something }.to output(<<-MESSAGE.strip_heredoc).to_stdout...
About IE's Compatibility mode
IE has a "Compatibility Mode" for old browsers. You can keep IE from offering it (and fix some other things, too) by adding this meta tag to your <head>
:
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
Or in Haml:
%meta(http-equiv="X-UA-Compatible" content="IE=Edge")
However, there are some things you need to bear in mind:
-
X-UA-Compatible is ignored unless it's present inside the first 4k of you page. If you put it somewhere in the bottom of your head section (or in the body) move it to top. The best place for ...
How to test whether your device has a true Retina display
The linked site hosts a simple test. It shows two images with narrow vertical/horizontal lines. The more they resemble each other, the more Retina your display is.
PostgreSQL and its way of sorting strings
PostgreSQL uses the C library's locale facilities for sorting strings:
- First, all the letters are compared, ignoring spaces and punctuation.
- It sorts upper and lower case letters together. So the order will be something like
a A b B c C
- Then, spaces and punctuation are compared to break ties.
Example:
Ruby | PostgreSQL |
---|---|
IMAGE3.jpg | image2.jpg |
image.jpg | image3.jpg |
image2.jpg | IMAGE3.jpg |
image3.jpg | image.jpg |
Further reading
- [PostgreSQL-FAQ: Why do my strings sort incorrectly?](h...