assignable_values 0.11.0 can return *intended* assignable values

As you know, assignable_values does not invalidate a record even when an attribute value becomes unassignable. See this example about songs:

class Song < ActiveRecord::Base
  belongs_to :artist
  belongs_to :record_label

  assignable_values_for :artist do
    record_label.artists
  end
end

We'll create two record labels with one artist each and create a song for one artist. When we change the song's record label, its artist is still valid.

makandra = RecordLabel.create! name: 'makandra records'
dominik...

assignable_values 0.10.0 released

assignable_values now supports Rails 4.1 and Ruby 2.1.0.

Things to consider when using Travis CI

Travis CI is a free continuous integration testing service. However, it is really fragile and will break more than it will work.

If you choose to use it anyway, learn the lessons we already learnt:

Use a compatible Rubygems for Rails 2.3 on Ruby 1.8.7

Ruby 1.8.7 is not compatible with current Rubygems versions (> 2.0). Runnig rvm rubygems latest-1.8 --force will fix this and install Rubygems version 1.8.29.

To make Travis CI do this, add `before_script: rvm rubygems latest-1....

rbenv: How to update list of available Ruby versions on Linux

When you tell rbenv to install a Ruby it does not know about, you will get an error message.

$ rbenv install 2.1.2
ruby-build: definition not found: 2.1.2

You can list all available versions with `rbenv install --list'.

If the version you're looking for is not present, first try upgrading
ruby-build. If it's still missing, open a request on the ruby-build
issue tracker: https://github.com/sstephenson/ruby-build/issues

(Fun fact: Recent versions of ruby-build will give you a more helpful error message which...

How to remove RSpec "old syntax" deprecation warnings

RSpec 3.0 deprecates the :should way of writing specs for expecting things to happen.

However, if you have tests you cannot change (e.g. because they are inside a gem, spanning multiple versions of Rails and RSpec), you can explicitly allow the deprecated syntax.

Fix

Inside spec/spec_helpber.rb, set rspec-expectations’ and/or rspec-mocks’ syntax as following:

RSpec.configure do |config|
  # ...
  config.mock_with :rspec do |c|
    c.syntax = [:should, :expect]
 ...

Silence specific deprecation warnings in Rails 3+

Sometimes you're getting an ActiveSupport deprecation warning that you cannot or don't want to fix. In these cases, it might be okay to silence some specific warnings. Add this to your initializers, or require it in your tests:

silenced = [
  /Not considered a useful test/,
  /use: should(_not)? have_sent_email/,
] # list of warnings you want to silence

silenced_expr = Regexp.new(silenced.join('|'))

ActiveSupport::Deprecation.behavior = lambda do |msg, stack|
  unless msg =~ silenced_expr
    ActiveSupport::Deprecation::DEFAULT_BEHAVI...

Removing MiniTest warnings from Rails 4 projects

Warnings like those below may originate from rspec or shoulda-matchers or other gems that have not updated yet to the new MiniTest API.

One

Warning: you should require 'minitest/autorun' instead.
Warning: or add 'gem "minitest"' before 'require "minitest/autorun"'
# (backtrace)

Solution: Add gem 'minitest' to your Gemfile, before any rspec gem.

Another

MiniTest::Unit::TestCase is now Minitest::Test. From /Users/makandra/.rvm/rubies/ruby-1.9.3-p484/lib/ruby/1.9.1/tes...

Discarding cached SQL query results in ActiveRecord

ActiveRecord caches results of SQL queries. If you want to discard the cached results for one model, you can call MyModel.connection.clear_query_cache.

A saner alternative to SimpleForm's :grouped_select input type

SimpleForm is a great approach to simplifying your forms, and it comes with lots of well-defined input types. However, the :grouped_select type seems to be overly complicated for most use cases.

Example

Consider this example, from the documentation:

form.input :country_id, collection: @continents,
  as: :grouped_select, group_method: :countries

While that looks easy enough at a first glance, look closer. The example passes @continents for a country_id.\
SimpleForm actua...

A Ruby script that installs all gems it is missing

So you want your Ruby script to install missing gems instead of dying? Take this method:

def installing_missing_gems(&block)
  yield
rescue LoadError => e
  gem_name = e.message.split('--').last.strip
  install_command = 'gem install ' + gem_name
  
  # install missing gem
  puts 'Probably missing gem: ' + gem_name
  print 'Auto-install it? [yN] '
  gets.strip =~ /y/i or exit(1)
  system(install_command) or exit(1)
  
  # retry
  Gem.clear_paths
  puts 'Trying again ...'
  require gem_name
  retry
end

Use it like this:

insta...

Caching in Rails

The information in this card is only relevant for Rails 2.3-era apps.


This note gives a quick introduction into caching methods (page caching, action caching and fragment caching) in rails and describes some specific problems and solutions.

The descriptions below are valid for Rails 2 and 3. Recently, caching with timestamp- or content-based keys has become more popular which saves you the pain of invalidating stale caches.

How to enable/disable caching

To enable or disable caching in rails you ca...

When using "render :text", set a content type

When your Rails controller action responds with only a simple text, render text: 'Hello' may not be what you want. You should not even use it on Rails 4.1+ any more.

By default, a "text" response from a Rails controller will still be a sent as text/html:

render text: 'Hello'
response.body # => "Hello"
response.content_type # => "text/html"

While this may not be too relevant for a Browser client, the response's content type is simply wrong if you want to send a plain-text response, and can cause trouble. \
For example, con...

Get the last leaf of a DOM tree (while considering text nodes)

I use this to simulate the (non-existing) :last-letter CSS pseudoclass, e. g. to insert a tombstone at the end of an article:

findLastLeaf = ($container) ->
  $children = $container.children()
  if $children.length == 0
    $container
  else
    $lastChild = $children.last()
    $lastContent = $container.contents().filter(->
      # Only return nodes that are either elements or non-empty text nodes
      @nodeType == 1 || (@nodeType == 3 && _.strip(@nodeValue) != '')
    ).last()
...

Chrome 34+, Firefox 38+, IE11+ ignore autocomplete=off

Since version 34, Chromium/Chrome ignores the autocomplete="off" attribute on forms or input fields. Recent versions of other browser do the same, although implementation details vary.

This is especially problematic for admin areas because Chrome might automatically fill in a password on a "add new user" forms.

Chrome developers say this is by design as they believe it encourages users to store more complex passwords.

Recommended fix for Chrome and F...

About "unexpected '#' after 'DESCENDANT_SELECTOR' (Nokogiri::CSS::SyntaxError)"

The error unexpected 'x' after 'DESCENDANT_SELECTOR' (Nokogiri::CSS::SyntaxError) (where x may be basically any character) occurs when the Nokogiri parser receives an invalid selector like .field_with_errors # or td <strong>.

In Cucumber, the culprit will be an invalid step definition that builds an invalid selector:

# inside some step definition:
field = find_field(label)
page.send(expectation, have_css(".field_with_errors ##{field[:id]}"))

The above raises the mentioned error if field[:id] is nil, i.e. the foun...

YAML: Keys like "yes" or "no" evaluate to true and false

If you parse this Yaml ...

yes: 'Totally'
no: 'Nope'

... you get this Ruby hash:

{ true: 'Totally',
  false: 'Nope' }

In order to use the strings 'yes' and 'no' as keys, you need to wrap them with quotes:

'yes': 'Totally'
'no': 'Nope'

There's actually a long list of reserved words with this behavior:

y|Y|yes|Yes|YES|n|N|no|No|NO
|true|True|TRUE|false|False|FALSE
|on|On|ON|off|Off|OFF

I'm sorry.

OpenStack nova resize "ERROR: Resize requires a change in size"

If you get this error when you try to resize an OpenStack instance:

# nova resize example 23 --poll
ERROR: Resize requires a change in size. (HTTP 400)

You need to change your flavor to have a different memory size. It's a bug in an older OpenStack version:

        # /nova/compute/api.py
        if (current_memory_mb == new_memory_mb) and flavor_id:		
            raise exception.CannotResizeToSameSize()

which got fixed 2012-09-12 ([https://git.openstack.org/cgit/openstack/nova/commit/nova/compute/api.p...