Pitfall: has_defaults on virtual attributes are nil when loaded from database, of course …

It smells. Rethink your code design.

Code example with makandra/has_defaults:

class Post < ActiveRecord::Base

  has_defaults tags: []          # field in db
  has_defaults virtual_tags: []  # no db field
  
  def all_tags
    virtual_tags + tags
  end
  
end

> Post.new.virtual_tags
=> []   # ✔

> Post.find(1).virtual_tags
=> nil   # ☹

> Post.find(1).all_tags
=> Error: undefined method '+' for nil:NilClass

Continuous Security Testing with Devops - OWASP EU 2014

Interesting talk about a team that integrated automated security testing into their BDD workflow.

There is also a video of the talk.

An auto-mapper for ARIA labels and BEM classes in Cucumber selectors

Spreewald comes with a selector_for helper that matches an English term like the user's profile into a CSS selector. This is useful for steps that refer to a particular section of the page, like the following:

Then I should see "Bruce" within the user's profile
                                 ^^^^^^^^^^^^^^^^^^

If you're too lazy to manually translate English to a CSS selector by adding a line to features/env/selectors.rb, we already have an [auto-mapper to translate English into ...

passenger problems with upgraded rails-app

You may encounter problems with passenger starting an application with an updated rails.
If you find an error like this in the apache error log:

[ 2015-08-21 10:53:04.1266 17680/7f4909bf7700 Pool2/Implementation.cpp:883 ]: Could not spawn process for group /var/www/example.com/current#default: An error occured while starting up the preloader.
     in 'void Passenger::ApplicationPool2::SmartSpawner::handleErrorResponse(Passenger::ApplicationPool2::SmartSpawner::StartupDetails&)' (SmartSpawner.h:455)
     in 'std::string Passenger::Appli...

postgresql create extension without giving the application superuser rights

If you need a postgresql extension for your database it isn't a good idea to give your applications database user superuser rights (like many people on stackoverflow think)

Just login to the database with a superuser account (e.g. postgres) and create the extension with it.

Example:

# with the default configuration of postgresql you normally can login as `postgres` user
# without a password if you use the systems `postgres` user
$ sudo su -l postgres
$ pgsql
postgres=# \c your_database;
psql (9.3.9, server 9.3.5)
You are now connected...

How to deal with 'parent id missing' error in nested forms

tl;dr

  • Use form models to handle this problem
  • Or soften the validation to validates_presence_of :parent

Usually you would validate presence of parent object id, like in this example:

class Parent < ActiveRecord::Base
  has_many :nested, :inverse_of => :parent
  accepts_nested_attributes_for :nested
end

class Nested < ActiveRecord::Base
  belongs_to :parent
  validates_presence_of :parent_id # <- 
end

With the parent already persisted creating nesteds still works fine.

But one will encounter a *'parent id missing' er...

How to silence thin boot messages

Each time thin boots, it prints a boot message :

Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on localhost:36309, CTRL+C to stop

If you are running parallel tests with thin, this will clutter you output. Disable thin logging with these lines:

# e.g. in features/support/thin.rb

require 'thin'
Thin::Logging.silent = true

Note that this disables all logging in tests. Instead, you also might set a different logger with `Thin::Loggi...

How to split config/routes.rb in Rails 4

A word of caution

There should rarely be a reason for you to split up config/routes.rb. If you need to, probably your whole application should be split up.

Split it anyway

Rails::Engine looks at config.paths['config/routes.rb'] and registers its value with app.routes_reloader. This means you could put routing files anywhere and then require them. However, I recommend to put any routing files into config/routes/:

# config/routes/example.rb

Rails.application.routes.draw do
 resources :example
end

After creating y...

marco-polo improves your Rails console prompt

MarcoPolo shows your app name and environment in your console prompt so you don't accidentally break production
Officially supporting IRB (standard rails console) and pry (via pry-rails gem).

Example:

$ rails console
Loading development environment (Rails 4.2.1)
agencyapp(dev)> 

List of Helpful RubyMine Shortcuts

Navigation

CTRL + SHIFT + ALT + N

Search for any symbol in your application, like CSS classes, Ruby classes, methods, helpers etc.

CTRL + SHIFT + N

Search for filename in your application (also dependencies)

CTRL + E

Open a list of recently opened files

ALT + POS1

Open a the navigation bar as a context menu. Allows you to quickly navigate between files.

CTRL + G

Go to line

Actions

CTRL + SHIFT + A

:...

PostgreSQL: Be careful when creating records with specific ids

In tests, it is sometimes useful to create records with specific ids. On PostgreSQL this can cause problems:

Usually, PostgreSQL uses an "autoincrement" sequences to provide sequential ids for new database rows. However, these sequences will not increment if you insert a record "by hand". This will cause an error:

record = Record.create!
record.id                             # => 100, next automatic id will be 101
Record.create!(id: record.id + 1)     # okay, but next automatic id will still be 101
Record.create!                       ...

Jasmine: Testing complex types for equality

Jasmine comes with two matchers that test for equality. The first is toBe:

expect(first).toBe(second)

toBe passes when first === second. Unfortunately this is useless for non-primitive values because JavaScript is a horrible language.

However, Jasmine comes with another matcher toEqual:

expect(first).toEqual(second)

This matcher behaves as a human would expect for types like the following:

  • Arrays
  • Objects
  • Nested array/object constructs
  • Regular expressions...

Mocking time in Jasmine specs

The easiest way to freeze or travel through time in a Jasmine spec is to use the built-in jasmine.clock().

  • After jasmine.clock().install() you can use it to control setTimeout and setInterval.
  • Using jasmine.clock().mockDate() you can mock new Date() (which returns the current time in Javascript)

While you can use SinonJS Fake timers, using the built-in Jasmine clock will save you an extra dependency.

Pierce through Javascript closures and access private symbols

If you are writing any amount of Javascript, you are probably using closures to hide local state, e.g. to have private methods.

In tests you may find it necessary to inspect a variable that is hidden behind a closure, or to mock a private method using Jasmine spies.

You can use the attached Knife helper to punch a hole into your closure, through which you can read, write or mock local symbols:

klass = (->

 privateVariable = 0

 privateMethod = ->
   ...

JavaScript events: target vs currentTarget

tl;dr: Use event.currentTarget unless you are absolutely certain that you need event.target.


Since it hasn't been written down in this deck before, here it goes:

When working with JavaScript Event objects, the DOM element that triggered the event is attached to them. [1]
However, there are 2 "opinions" on which element that would be:

  • The element that the user interacted with (event.target),
  • or the element that the event listener is bound to (event.currentTarget).

Note that both can be, but not...

How to fix: iPad does not trigger click event on some elements

iPads will not trigger click events for all elements. You can fix that, but you don't want to know why.

Example: Capturing clicks on table rows (use case would be clicking the 1st link inside it for better UI). Consider this setup:

<table>
  <tr>
    <td>hello</td>
  </tr>
</table>

^

$(document).on('click', 'tr', function () {
  alert('row clicked')
});

While this works on a desktop browser, clicking the row/cell on an iPad will just do nothing.

Turns out, the iPad will only trigger such events for ...

Parallel Rspec with RTeX

Running projects parallel makes some trouble with PDF generation. Use geordi rspec spec to force sequential tests for the whole application or failed specs only.


geordi rspec
RTeX::Document::GenerationError in '...'
Could not find result PDF document.pdf after generation.
Check .../document.log

The document will show you, that RTeX tries to generate a PDF document out of a HTML file, which won't work.

Protip: Clone large projects multiple times

Large projects usually have large test suites that can run for a long time.
This can be annoying as running tests blocks you from picking up the next story -- but it doesn't have to be that way!

Simply clone your project's repo twice (or even more often).

When your work on a feature branch is done, simply push that branch and check it out on your 2nd copy to run tests there.
You can pick up a new story and work on that on your "main" project directory.

If you do it right, you will even be able to run tests in both your 2nd copy and your m...

Material Design Lite

CSS (+ some Javascript) framework, implementing Google's material design for static web pages.

Can be used for plain websites without requiring a full blown Javascript framework, unlike the (also excellent) Polymer paper elements, or Angular material.

Prelimiary impression:

I would recommend against using it at this stage, for a couple of reasons:

  • It is much less complete than you might expect from a CSS framewor...

A non-weird replacement for grouped_collection_select

Rails comes with grouped_collection_select that appears to be useful, but isn't.

As an alternative, consider the flat_grouped_collection_select found below. It takes a third argument that extracts the group from each element in the collection:

= form.flat_grouped_collection_select :user_id, users, :department, :id, :full_name

Here is the monkey-patch:

class ActionView::Helpers::FormBuilder

  def flat_grouped_collection_selec...

Rails 3 ActiveRecord::Persistence#becomes does not copy changed attributes

Note: ActiveRecord::Base#becomes has a lot of quirks and inconsistent behavior. You probably want to use ActiveType.cast instead.


This issue will be encountered when relying on attribute_was methods of ActiveModel::Dirty after casting a model which has defaults to a form model, for example.

In my case a record with an assignable_values legacy value beca...

Querying model errors in Rails 4

ActiveModel supplies an errors object that behaves similar to a Hash. It can be used to add errors to a record, as well as to query the record for registered errors. This object is returned when calling <object>.errors:

errors = @user.errors # => #<ActiveModel::Errors ...>

Here are some helpful messages of its API:


[<attribute name>]

Returns an array of error messages on that attribute. Example: errors[:name] => ['is missing']


add_on_blank(<attribute list>) (similarly add_on_empty)

Registers an error ...

Reverse-proxying web applications with Apache 2.4+

Note: Making a reverse proxy with nginx is much more straightforward.


A reverse proxy is a "man in the middle" server that tunnels requests to another server. You can use for things like:

  • Expose a local service that you cannot directly reach over the internet
  • "Change" the domain or path of a web application by rewriting them on the fly
  • Instantly change servers that respond to a name or ...

sessionStorage: Per-window browser storage

All major browsers (IE8+, FF3.5+, Safari 4+, any Chrome) support sessionStorage, a JavaScript storage object that

  • survives page reloads and browser restores,
  • but is different per new tab/window (in contrast to localStorage which is shared across all tabs).

MDN says:

The sessionStorage object is most useful for hanging on to temporary data that should be saved and restored if the browser is accidentally refreshed

Demo

Example usage: