Subclassing module
Yesterday I stumbled across a talk in which the guy mentioned module sub-classing. I was curious what you can do with it and found his blog post with a cool example. It allows you to inject some state into the module you are including elsewhere. Check it out!
class AttributeAccessor < Module
def initialize(name)
@name = name
end
def included(model)
super
define_accessors
end
private
def define_accessors
ivar = "@#{@name}"
define_writer(ivar)
define_reader(ivar)
end
def define_writer(ivar)
...
Angular with haml: Dynamic html classes
A haml angular 1 template with
.thing(class="is-{{:: item.type }}")
will be compiled (by haml) to
<div class="is-{{:: item.type thing }}"></div>
which is not what you want! It will also crash in angular (unless thing is a valid variable in your angular directive) with Error: [$parse:syntax] Syntax Error: Token 'thing' is an unexpected token at column 11 of the expression [item.type thing]
Solution 1: Use ng-class instead of class
.thing(ng-class='"is-{{ item.type }}"')
**Solution 2: Don't let haml b...
Developer Soft Skills
Knowing when to refactor
Just feeling like refactoring is not a good reason to do it. Make an educated decision: Is the code change worth the effort? Stay straight on track, don't go astray.
Note: Usually, you'd refactor after finishing your story. At times, it might be necessary to refactor up front. But try to keep refactoring out of your current task.
Knowing where to optimize
Things should only be optimized a) when they have settled, i.e. haven't changed for a longer time, and b) when there is a measurable gain from th...
How to "git diff" with a graphical diff tool
If you are fine with the default console diff most of the time but only sometimes want to use an external tool for viewing a diff, you can use git difftool.
E.g. viewing git diff with meld:
git difftool --tool=meld
For each file in the diff you will be asked if you want to view it using meld.
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...
Running awstats on a single logfile
AWstats is build to regularly run on webservers. If you want it to build a report once, here is the minimal configuration you need:
Put the following into the awstats config file (look into /etc/awstats/awstats.conf.local or look into /etc/awstats/awstats.conf how to do it on your system):
SiteDomain="yourdomain.de"
DirData="."
DNSLookup=0
Run the following to build a simple HTML page:
awstats -staticlinks -config="yourdomain.de" -LogFile=your-logfile.log -output > report.html
This might take a second (it will take ...
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...
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...
How to use Haml in your helpers
You know those helper methods that just render some HTML but look weird because of content_tags 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...
How to tidy up your Git mess
Git is hard: screwing up is easy, and figuring out how to fix your mistakes is fucking impossible. Git documentation has this chicken and egg problem where you can't search for how to get yourself out of a mess, unless you already know the name of the thing you need to know about in order to fix your problem.
Maybe this flowchart may be of help...
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.0to make it accessible from other machines in the local network, e.g. ...
An intro to Javascript promises
Promises are the new way™ to express "Do this, and once you're done, do that". In contrast to callbacks, promises are easily chainable. From the readme of Q, an early implementer of the pattern:
The callback approach is called an “inversion of control”. A function that accepts a callback instead of a return value is saying, “Don’t call me, I’ll call you.”. Promises un-invert the inversion, cleanly separating the input arguments from control flow arguments. This simplifies the use and creation of APIs, p...
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')...
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...
Middleman does not fingerprint asset paths by default
We're using Middleman for some static sites like our blog.
Despite being very similar to Rails, Middleman does not add a fingerprint hash to its asset paths by default. This means that when you write this:
<%= javascript_include_tag 'all.js' %>
... you always get the same path, regardless of the contents of all.js:
<script src='/javascripts/all.js'>
Because browsers tend to cache assets for a while, this means that users might not get your changes until their cac...
Represent astral Unicode characters in Javascript, HTML or Ruby
Here is a symbol of an eight note: ♪
Its two-byte hex representation is 0x266A.
This card describes how to create a string with this symbol in various languages.
All languages
Since our tool chain (editors, languages, databases, browsers) is UTF-8 aware (or at least doesn't mangle bytes), you can usually get away with just pasting the symbol verbatim:
note = '♪'
This is great for shapes that are easily recognized by your fellow programmers.
It's not...
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...
Google Chrome: How to find out your currently installed theme
So you downloaded a theme for Chrome a while ago and don't remember which one it is?
You can go to chrome://settings/appearance (on Chrome 61+) to see the theme's name, and click a link to open it in the Chrome Web Store.
If you are on an older version, or if the above no longer works, you have to check Chrome's Preferences file.
Linux
/home/YOUR_USER_NAME/.config/chromium/Default/Preferences
OSX
/Users/YOUR_USER_NAME/Library/Application Support/Google/Chrome/Default/Preferences
Windows
C:\Users\YOUR_US...
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
htmltag to define your page's default background color (because on short pages or large screens, yourbodymay not be as tall as the browser window). - Use the
htmltag to define a basefont-sizeso you can use [remunits](https://www.sitepoint.com/underst...
Using Google Analytics with Unpoly
The default Google Analytics might not work as expected with your Unpoly app. This is because your app only has a single page load when the user begins her session. After that only fragments are updated and the <script> tag that sends the page view to Google Analytics is probably never evaluated again.
Luckily you can fix this.
Simple mode: You just want to track all the page views
Embed your Google Analytics code as always.
Now add the following code snippet:...
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...
HAML 4+ expands nested element attributes
As you may know, HAML expands data attributes that are given as a hash:
%div{ data: { count: 3 } }
# results in:
<div data-count="3"></div>
However, this also works for any other hash attribute. Consider an Angular directive or an Unpoly compiler that is configured by several attributes. Usually you'd prefix them with the directive/compiler name so it gets clear where the attribute belongs. With HAML, this is easy to build:
%...