Tagging in Rails 4 using Postgres Arrays

Usage:

class Document < ActiveRecord::Base
  scope :any_tags, -> (tags){ where('tags && ARRAY[?]', tags) }
  scope :all_tags, -> (tags){ where('tags @> ARRAY[?]', tags) }
end

Document.create(title: "PostgreSQL", tags: ["pg","rails"])

Document.any_tags('pg')
Document.all_tags(['pg', 'rails'])

Migration:

class CreateDocuments < ActiveRecord::Migration
  def change
    create_table :documents do |t|
      t.string :title
      t.string :tags, array: true, default: []
      t.timestamps
    end
    add_index  :documents, :ta...

Eager-loading polymorphic associations

To avoid n+1 queries, you want to eager-load associated records if you know you need to access them later on.

The Rails docs say:

Eager loading is supported with polymorphic associations.

This is true, but has some caveats.

Example

Consider the following models:

class Image < ActiveRecord::Base; end
class Video < ActiveRecord::Base; end
class PageVersion < ActiveRecord::Base
  belongs_to :primary_medium, polymorphic: true # may be Image or Video
end
class Page < ActiveRecord::Base
  belongs_to ...

How Exchange handles multipart/alternative emails

In Rails, you can very easily send emails with HTML and plaintext bodies.

However, if you're trying to debug those using your normal email account, you might be out of luck: For some reason, Exchange servers will simply throw away the plaintext part of your mail, and just save the html part.

Change the existing order of an ActiveRecord scope

Use reorder to replace an existing order clause with a new expression.

Ubuntu: Fix "An error occurred while installing pg"

If you get an error like this:

An error occurred while installing pg (0.17.1), and Bundler cannot continue.
Make sure that gem install pg -v '0.17.1' succeeds before bundling.

Then do this:

sudo apt-get install libpq-dev

... and run Bundler again.

Rspec: Complex argument expectations for should_receive

Sometimes you need complex expectations on method arguments like this

SomeApi.should_receive(:find).with(:query => '*foo*', :sort => 'timestamp ASC', :limit => 100).and_return(['some result'])

This is not very flexible, and failure messages will be hard to read.

Instead, consider doing this:

SomeApi.should_receive(:find) do |params|
  params[:query].should == '*foo*'
  params[:sort].should == 'timestamp ASC'
  params[:limit].should == 100
  
  ['some result']
end

What we know about PDFKit

What PDFKit is

  • PDFKit converts a web page to a PDF document. It uses a Webkit engine under the hood.
  • For you as a web developer this means you can keep using the technology you are familar with and don't need to learn LaTeX. All you need is a pretty print-stylesheet.

How to use it from your Rails application

  • You can have PDFKit render a website by simply calling PDFKit.new('http://google.com').to_file('google.pdf'). You can then send the...

Alternative for Ruby singletons

require 'net/http'

module Cheat
  extend self # the magic ingredient

  def host
    @host ||= 'http://cheat.errtheblog.com/'
  end

  def http
    @http ||= Net::HTTP.start(URI.parse(host).host)
  end

  def sheet(name)
    http.get("/s/#{name}").body
  end
end

# use it
Cheat.sheet 'migrations'
Cheat.sheet 'singletons'

What edge_rider offers you

edge_rider is Power tools for ActiveRecord relations (scopes). Please note that some of the functions edge_rider provides have native implementations in newer rails versions.

Useful in applications

Relation#traverse_association(*names)

Edge Rider gives your relations a method #traverse_association which returns a new relation by "pivoting" around a named association. You can traverse multiple associations in a single call. E.g. to turn a relation of posts into a relation of all posts o...

MySql lost connection trouble

Directly from the MySql docs:

There are three likely causes for this error message.

Usually it indicates network connectivity trouble and you should check the condition of your network if this error occurs frequently. If the error message includes during query, this is probably the case you are experiencing.

Sometimes the during query form happens when millions of rows are being sent as part of one or more queries. If you know that this is happening, you should try increasing net_read_timeout from its default of 30 seconds to 60 s...

terminator keyboard shortcuts

When connecting to multiple (i.e. > 4) servers to dive into logfiles or do security updates, terminator is what you want.
There are several keyboard shortcuts available:

  • Ctrl-Shift-E: Split the view vertically.
  • Ctrl-Shift-O: Split the view horizontally.
  • Ctrl-Shift-P: Focus be active on the previous view.
  • Ctrl-Shift-N: Focus be active on the next view.
  • Ctrl-Shift-W: Close the view where the focus is on.
  • Ctrl-Shift-Q: Exit terminator.
  • Ctrl-Shift-X: Enlarge active window...

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...

PSA: Umlauts are not always what they seem to be

When you have a string containing umlauts which don't behave as expected (are not matched with a regexp, can't be found with an SQL query, do not print correctly on LaTeX documents, etc), you may be encountering umlauts which are not actually umlaut characters.

They look, depending on the font, like their "real" umlaut counterpart:

  • ä ↔ ä
  • ö ↔ ö
  • ü ↔ ü

However, they are not the same:

'ä' == 'ä' # false
'ä'.size # 1
'ä'.size # 2

Looking at how those strings are constructed reveals what is going on:

'ä'.unpack('U*...

patbenatar/jquery-nested_attributes

jQuery plugin that makes it easy to dynamically add and remove records when using ActiveRecord's nested attributes.

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.

Retrieving the class an ActiveRecord scope is based on

Edge Rider gives your relations a method #origin_class that returns the class the relation is based on.
This is useful e.g. to perform unscoped record look-up.

Post.recent.origin_class
# => Post

Note that #origin_class it roughly equivalent to the blockless form of #unscoped from Rails 3.2+, but it works consistently across all Rails versions. #unscoped does not exist for Rails 2 and is broken in Rails 3.0.

What's new in edge Rails: Active Record enums

Declare an enum attribute where the values map to integers in the database, but can be queried by name.

Why Ruby Class Methods Resist Refactoring

In a nutshell:

  • Splitting a long method into sub methods is easier in instances since it is in classes. Since you must not save state in a class, you need to pass around context as a long chain of parameters again and again.
  • If your public API has a single entry point, you can still have a class-level method that takes care of constructing the instance etc. So it's all win.

Why your previous developer was terrible

When you, as a developer, look at the choices used to build a particular application, you’re blown away at the poor decisions made at every turn. “Why, oh why, is this built with Rails when Node.js would be so much better?” or “how could the previous developer not have forseen that the database would need referential integrity when they chose MongoDB?” But what you may not realize is that you are seeing the application as it exists today. When the previous developer (or team) had to develop it, they had to deal with a LOT of unknowns. They...

BrowserStack has browser plugins for local testing

Local testing allows you to test your private and internal servers using the BrowserStack cloud, which has support for firewalls, proxies and Active Directory.

ActiveRecord: validate_uniqueness_of is case sensitive by default

By default, Rails' validates_uniqueness_of does not consider "username" and "USERNAME" to be a collision. If you use MySQL this will lead to issues, since string comparisons are case-insensitive in MySQL.

(If you use PostgreSQL, read this instead.)

Say you have a user model

class User < ActiveRecord::Base
  validates_uniqueness_of :name
end

with a unique index in the database.

If you try to create the users "user" and "USER", this will not trigger a validation error, but may fail with an SQL error due ...

all_blank_except for accepts_nested_attributes_for

Put the attached file to config/initalizers to ignore some fields for rejecting nested records (e.g. hidden input fields).

class Post < ActiveRecord::Base
  
  has_many :comments
  accepts_nested_attributes_for :comments, :reject_if => all_blank_except(:position, :other_nested_attrs)

end

Your Rails sandbox console

Just found out about a great feature in Rails that seems to be around since Rails 2. Start a console with the --sandbox (or -s) parameter:

rails console --sandbox

All changes you make to the database will be rolled back on exit.

Warning

Changes beyond the database (deleting files, sending emails, etc) cannot be rolled back!

Don't ever use the float type for database columns

Like in any language, a FLOAT will eventually corrupt data due to rounding errors.

Please use DECIMAL, which has well-defined behavior for rounding and range overflows.