Protected and Private Methods in Ruby

In Ruby, the meaning of protected and private is different from other languages like Java. (They don't hide methods from inheriting classes.)

private

Private methods can only be called with implicit receiver. As soon as you specify a receiver, let it only be self, your call will be rejected.

class A
  def implicit
    private_method
  end
  
  def explicit
    self.private_method
  end
  
  private
  
  def private_method
    "Private called"
  end
end

A.new.implicit
# => "Private called"

A.new.explicit
# => NoMethod...

Ruby: Debugging a method's source location and code

Access the Method object

Dead simple: Get the method object and ask for its owner:

"foo".method(:upcase)
# =>  #<Method: String#upcase> 

"foo".method(:upcase).owner
# => String

Look up a method's source location

Ruby 1.9 adds a method Method#source_location that returns file and line number where that method is defined.

class Example; def method() end; end
# => nil

Example.new.method(:method).source_location
# => ["(irb)", 11] 
 
"foo".method(:upcase).source_location
# => nil # String#upcase is a native method...

Fix „rvm no such file to load -- openssl“ or "rvm no such file to load -- zlib"

For example if you use rvm and get this message:

ERROR:  Loading command: install (LoadError)
    no such file to load -- zlib
ERROR:  While executing gem ... (NameError)
    uninitialized constant Gem::Commands::InstallCommand

You've installed your ruby without having all required libraries.

I don't know why there isn't a Warning message if you install a ruby with rvm and didn't have libraries like openssl and zlib.

To fix this you can execute this:

#to show the requirements for your system
rvm requireme...

Ruby 1.9 or Ruby 2.0 do not allow using shortcut blocks for private methods

Consider this class:

class Foo

  private
  
  def test
    puts "Hello"
  end
  
end

While you can say create a block to call that method (using ampersand and colon) on Ruby 1.8, ...

1.8.7 > Foo.new.tap(&:test)
Hello
=> #<Foo:0x1e253c8> 

... you cannot do that on Ruby 1.9 or 2.0:

1.9.3 > Foo.new.tap(&:test)
NoMethodError: private method `test' called for #<Foo:0x00000001e8c258>

^
2.0.0 > Foo.new.tap(&:test)
NoMethodError: private method `test' called for #<Foo:0x000000027bc738...

Different behavior for BigDecimal#floor in Ruby 1.8 and Ruby 1.9

Ruby 1.8 (supplied by Rails' ActiveSupport)

>> BigDecimal.new("0.1").floor.class
=> BigDecimal

Ruby 1.9 (supplied by Ruby 1.9 itself)

>> BigDecimal.new("0.1").floor.class
=> Fixnum

In fact, Float#floor has changed from Ruby1.8 to Ruby 1.9 which is used by BigDecimal#floor internally.

Attached initializer backports Ruby 1.9 behavior to Ruby 1.8.

How to: Ruby heredoc without interpolation

When you use heredoc, string interpolation is enabled by default:

x = "Universe"
<<-MESSAGE
  Hello #{x}
MESSAGE
# => "Hello Universe"

This may be impractical sometimes. To avoid interpolation in heredoc strings, simply enclose your heredoc marker with single quotes:

x = "Universe"
<<-'MESSAGE'
  Hello #{x}
MESSAGE
# => "Hello #{x}"

That will make the string behave like a single-quoted string, so sequences like \n wil...

Capistrano: Bundler stalls and asks for "Username"

Given you use Capistrano together with bundler to automatically install your gems when deploying.

I recently had the problem that Capistrano stalled like this:

[err :: host.name.tld] Username:

It turned out that I this originated from GitHub. We had a gem in our Gemfile that explicitly pointed to a GitHub URL like that:

gem 'foogem', :git => 'https://github.com/blubb/foogem.git'

The URL was returning a 404 which caused the problems. You have to get another gem or point to a fork on GitHub.

instance_eval behaves different in Ruby 1.8 and Ruby 1.9, use instance_exec instead

In Ruby 1.9, instance_eval calls the block the with receiver as the first argument:

  • In Ruby 1.8, receiver.instance_eval(&block) calls block.call()
  • In Ruby 1.9, receiver.instance_eval(&block) calls block.call(receiver)

This will blow up in your face in Ruby 1.9, where a lambda crashes when it is called with a different number of arguments:

wrong number of arguments (1 for 0) (ArgumentError)

Forget that instance_eval ever existed. Use instance_exec instead, which behaves consistently across all Rubies.

MongoMapper for Rails 2 on Ruby 1.9

MongoMapper is a MongoDB adapter for Ruby. We've forked it so it works for Rails 2.3.x applications running on Ruby 1.9. [1]

makandra/mongomapper is based on the "official" rails2 branch [2] which contains commits that were added after 0.8.6 was released. Tests are fully passing on our fork for Ruby 1.8.7, REE, and Ruby 1.9.3.

To use it, add this to your Gemfile:

gem 'mongo_mapper', :git => 'git://github.com/makandra/mongomapper.git', :branch => 'rails2'

...

"Module.const_defined?" behaves differently in Ruby 1.9 and Ruby 1.8

Ruby 1.9 changed the default behavior of Module.const_defined? from what it was in Ruby 1.8 -- this can be especially painful when external code (read: gems) uses const_defined? to look something up and gets different results on different Rubies.

Consider this:

module Foo
  FOO = 42
end

class Bar
  include Foo
end

On Ruby 1.8, Bar won't have FOO defined as a constant since that's (even though it's accessible):

1.8.7 > Foo.const_defined? :F...

Fix error "invalid byte sequence in US-ASCII" in .js.erb files

This error can happen in Ruby 1.9.

To fix it, add the following line to the top of your .js.erb file:

<%# @encoding: UTF-8 %>

How to silence UTF-8 warnings on Rails 2.3 with Ruby 1.9

Rails 2.3.16+ on Ruby 1.9 causes warnings like this:

.../gems/activesupport-2.3.17/lib/active_support/core_ext/string/output_safety.rb:22: warning: regexp match /.../n against to UTF-8 string

Many thanks to grosser for supplying a monkey-patch for Rails 2.3 (Commit f93e3f0ec3 fixed it for Rails 3). Just put it into config/initializers/ to make those warnings go away.

Since we're using RSpec on mos...

A regular expression that will never match

So you have a method returning a regular expression but one case that should not yield a matching Regexp object but still keep the API stable? Just return one that never matches:

/(?!)/

Fix warning "already initialized constant Mocha" with Rails 3.2

You either have an old version of Mocha and an edge version of Rails 3.2, or you have a new version of Mocha and an old version of Rails. The best solution is to update Mocha to the latest version and switch to Rails edge.

If you are using shoulda-matchers or another gem that locks Mocha to an old version, you are out of luck.
More info with many other workarounds that you do not want to use can be found here. A hack to work around this case is to add the following file to lib/mocha/setup.rb:...

rsl/stringex · GitHub

Stringex is a gem that offers some extensions to Ruby's String class. Ruby 1.9 compatible, and knows its way around unicode and fancy characters.

Examples for stringex's String#to_url method:

# A simple prelude
"simple English".to_url => "simple-english"
"it's nothing at all".to_url => "its-nothing-at-all"
"rock & roll".to_url => "rock-and-roll"

# Let's show off
"$12 worth of Ruby power".to_url => "12-dollars-worth-of-ruby-power"
"10% off if you act now".to_url => "10-percent-off-if-you-act-now"

# You do...

lang/unicode_utils · GitHub

UnicodeUtils implements Unicode algorithms for case conversion, normalization, text segmentation and more in pure Ruby code.

If you don't need the ton of features that UnicodeUtils offers, try stringex.

How to fix: RVM does not offer recent Ruby versions

RVM needs to be updated regularly to know of Ruby versions released since installation (or last update).

So if you say rvm install 1.9.3, but get an old version (basically anything below 1.9.3-p385 when writing this card), your RVM is outdated. \
Fix that by saying:

rvm get stable

After that, rvm install 1.9.3 should install the latest 1.9.3 version.

How to fix: "Error Bundler::HTTPError during request to dependency API"

If bundle install shows the following message for you ...

Error Bundler::HTTPError during request to dependency API

... upgrade to Bundler ≥ 1.2.4:

gem install bundler

Apparently, it just hides the message.

Edge Rider: Power tools for ActiveRecord scopes

In our continued quest to extract proven code snippets from makandropedia into tested and upgradable gems, we have released Edge Rider.

Edge Rider was created with two intents:

  1. Provides a number of utility methods to facilitate hardcore work with scopes.
  2. Provide a stable API for working with scopes across multiple versions of Rails, since Rails has a tradition of breaking details of its scope API every other release.

The gem bundles multiple patches and initializers we've been using for hard...

Traverse an ActiveRecord relation along an association

The Edge Rider gem gives your relations a method #traverse_association which
returns a new relation by "pivoting" around a named association.

Say we have a Post model and each Post belongs to an author:

class Post < ActiveRecord::Base
  belongs_to :author
end

To turn a relation of posts into a relation of its authors:

posts = Post.where(:archived => false)
authors = posts.traverse_association(:author)

You can traverse multiple associations in a single call.
E....

The many gotchas of Ruby class variables

TLDR: Ruby class variables (@@foo) are dangerous in many ways. You should avoid them at all cost. See bottom of this card for alternatives.

Class variables are shared between a class hierarchy

When you declare a class variable, it is shared between this and all descending (inheriting) classes. This is rarely what you want.

Class variables are bound at compile-time

Like unqualified constants, class variables are bound to your current scope *whe...

Prevent double clicks on link_to_remote (simple case)

This works well in the simplified case, when your link disappears after it was clicked.

Let link_to_remote behave as „disabled“ after the first click. Use the :before hook to replace the orignal link with a link that does nothing but looks like the original link:

:ruby
  label = "do_something"
  dummy_link = link_to(label)
  other_attributes_hash = { :url => ..., :method => ..., ... }
  
  disable_link_option = { :before => "$('your_link_selector').html('#{escape_javascript(dummy_link)}'" } # jquery

= link_to_remote(label, other_att...

Regex: Be careful when trying to match the start and/or end of a text

Ruby has two different ways to match the start and the end of a text:

  • ^ (Start of line) and $ (End of line)
  • \A (Start of string) and \z (End of string)

Most often you want to use \A and \z.

Here is a short example in which we want to validate the content type of a file attachment. Normally we would not expect content_type_1 to be a valid content type with the used regular expression image\/(jpeg|png). But as ^ and $ will match lines, it matches both content_type_1 and content_type_2. Using \A and \z will wo...

What The Rails Security Issue Means For Your Startup

January has been a very bad month for Ruby on Rails developers, with two high-severity security bugs permitting remote code execution found in the framework and a separate-but-related compromise on rubygems.org, a community resource which virtually all Ruby on Rails developers sit downstream of. Many startups use Ruby on Rails. Other startups don’t but, like the Rails community, may one day find themselves asking What Do We Do When Apocalyptically Bad Things Happen On Our Framework of Choice? I thought I’d explain that for the general c...