Inspecting a live Ruby process

How to get a backtrace from a running Ruby process:

Ruby 2.6

# First, find out the PID of your Ruby process (e.g. passenger-status)
$ sudo gdb -p PID
(gdb) call rb_eval_string("$stderr.reopen('/tmp/ruby-debug.' + Process.pid.to_s); $stderr.sync = true") # redirects stderr
(gdb) call rb_backtrace() # prints current backtrace to /tmp/ruby-debug.xxx

Stop the process afterwards, since stderr is now borked.

It is possible you have to call rb_backtrace() multiple times to get the full stacktrace.

Previous method on Ruby 2....

Ruby blocks: Braces and do/end have different precedence

TL;DR {} binds stronger than do … end (as always in Ruby, special characters bind stronger than words)

Demo

✔️ Right way

names = ['bRUce', 'STaN', 'JOlIE']

# Blocks in braces are passed to the rightmost method
print names.map { |name| name.downcase }
print(names.map do |name| name.downcase end) # equivalent
=> ["bruce", "stan", "jolie"]

❌ Wrong way

Avoid the examples below, as you pass at least one block to print and not to the enumerator.

names = ['bRUce', 'STaN', 'JOlIE'] 

# Blocks in do…end ar...

Use the Ruby debugger on Rails 2 script/runner scripts

This card needs to be updated for Rails 3+.


Since there is no --debugger flag you need to run:

rdebug script/runner lib/scripts/something.rb

That will open an debugging IRB right away, like this:

require File.dirname(__FILE__) + '/../config/boot'
(rdb:1) _

Enter c to continue and reach your actual debugger call. Then, debug away.

If nothing happens for you: Make sure ruby-debug is available in the Gemfile and you require it.

Ruby: Making your regular expressions more readable with /x and alternative delimiters

The following two hints are taken from Github's Ruby style guide:

If your regular expression mentions a lot of forward slashes, you can use the alternative delimiters %r(...), %r[...] or %r{...} instead of /.../.

 %r(/blog/2011/(.*))
 %r{/blog/2011/(.*)}
 %r[/blog/2011/(.*)]

If your regular expression is growing complex, you can use the /x modifier to ignore whitespace and comments:

regexp = %r{
  start         # some text
  \s            # white space char
  (group)    ...

Ruby: Find the most common string from an array

This will give you the string that appears most often in an array:

names = %w[ foo foo bar bar bar baz ]
names.group_by(&:to_s).values.max_by(&:size).try(:first)
=> "bar"

This is very similar to the linked StackOverflow thread, but does not break on empty arrays.

Note that try is provided by ActiveSupport (Rails). You could explicitly load activesupport or use andand on plain Ruby.

Change how Capybara sees or ignores hidden elements

Short version

  • Capybara has a global option (Capybara.ignore_hidden_elements) that determines whether Capybara sees or ignores hidden elements.
  • Prefer not to change this global option, and use the :visible option when calling page.find(...). This way the behavior is only changed for this one find and your step doesn't have confusing side effects.
  • Every Capybara driver has its own notion of "visibility".

Long version

Capybara has an option (Capybara.ignore_hidden_elements) to configure the default...

Fix [RubyODBC]Cannot allocate SQLHENV when connecting to MSSQL 2005 with Ruby 1.8.7. on Ubuntu 10.10

I followed this nice guide Connecting to MSSQL with Ruby on Ubuntu - lambie.org until I ran in the following errors:

irb(main):001:0> require "dbi"; dbh = DBI.connect('dbi:ODBC:MyLegacyServer', 'my_name', 'my_password')

DBI::DatabaseError: INTERN (0) [RubyODBC]Cannot allocate SQLHENV
  from /usr/lib/ruby/1.8/dbd/odbc/driver.rb:36:in `connect'
  from /usr/lib/ruby/1.8/dbi/handles/driver.rb:33:in `connect'
  from /usr/lib/ruby...

Ruby, Ruby on Rails, and _why: The disappearance of one of the world’s most beloved computer programmers

Nice article to educate your non-geek girlfriend/boyfriend about the joys of programming.

Make your Rails console (and irb) output better readable

Pour color on your Rails console with awesome_print. Turn confusing long strings into formatted output. Have objects and classes laid out clearly whenever you need it.

Put gem 'awesome_print', :group => :development into your Gemfile. Now on the Rails console you have the command ap that will give you a colored, formatted output of whatever you pass it. See the example output of the User class below.

For customization visit the repository on Github.

![awesome_print.png](https://makan...

Fix error: rails console - no such file to load -- readline

Install libreadline:

sudo apt-get install libreadline-dev

Reinstall the ruby and tell rvm where to find readline

rvm reinstall 1.8.7 --with-readline-dir=/usr/include/readline

Make sure you get a huge cup of tea before running the command above! It will take some time.

References

Bundler 1.1 has been released, is very fast

Bundler 1.1 has been released. With this version you no longer need to wait for this:

Fetching source index…

The new Bundler is smarter and can fetch required metadata in a few seconds.

You can install the new version by saying:

sudo gem install bundler

Install the typhoeus gem with native extensions

If you get this:

Installing typhoeus (0.3.3) with native extensions
/usr/local/lib/site_ruby/1.8/rubygems/installer.rb:483:in `build_extensions': ERROR: Failed to build gem native extension. (Gem::Installer::ExtensionBuildError)

/usr/bin/ruby1.8 extconf.rb 
checking for curl/curl.h in /opt/local/include,/opt/local/include/curl,/usr/include/curl,/usr/include,/usr/include/curl,/usr/local/include/curl... no
need libcurl

You can fix it by installing the libcurl3-dev package:

sudo apt-get install libcurl3-dev

Now you should...

Setup or update Passenger to use Ruby Enterprise

  1. Your current ruby must be Ruby Enterprise.
  2. gem install passenger
  3. passenger-install-apache2-module
  4. Edit your httpd.conf according to the instructions provided at the end of the setup script.
  5. Restart Apache: sudo service apache2 restart

This also works when you previously ran your Passenger using MRI. Just run the setup as described.

Gherkin: Error during installation

When trying to install the gherkin gem, you might encounter an error with the following lines:

ERROR:  Error installing gherkin:
	ERROR: Failed to build gem native extension.
...
checking for main() in -lc... yes
creating Makefile
...
cc1: all warnings being treated as errors
Makefile:150: recipe for target 'gherkin_lexer_ar.o' failed
make: *** [gherkin_lexer_ar.o] Error 1
...

If upgrading is not an option, configure build options for gherkin:

bundle config --local build.gherkin --with-cflags=-w

Your .bundle/config fi...

Compare two XML strings as hashes

Let's say you have two XML strings that are ordered differently but you don't care about the order of attributes inside containers:

a = '<?xml version="1.0" encoding="UTF-8"?><Authenticate><User>batman</User><Password>secret</Password></Authenticate>'
b = '<?xml version="1.0" encoding="UTF-8"?><Authenticate><Password>secret</Password><User>batman</User></Authenticate>'

Working with plain string comparison is not helpful, of course:

a == b
=> false

Instead, you can use the Nori gem ...

Do not rescue inline in Ruby

When you are calling a method that may raise an exception that you don't care about, you might think of doing something like this:

@user = User.power_find(something) rescue User.new

Do not do that! You will be rescuing away StandardError and all its subclasses, like NameError -- meaning that even a typo in your code won't raise an error.

Instead, rescue the exception type that you are expecting:

@user = begin
  User.power_find(something)...

WebMock 1.8.0 does not play nice with Curb < 0.7.16

When updating WebMock, be prepared that your specs may send real requests into the depths of the internet unless you update Curb as well.\
WebMock will not complain about those requests not being stubbed.

One of the commits that made it into 1.8.0 actually breaks Curb versions below 0.7.16 while fixing it for that version (and above, hopefully).\
WebMock's hooks for Curl::Easy are sti...

Issues with has_select?

The handy method has_select?(field, :selected => text) does not behave as expected with Cucumber 0.10.2, Capybara 0.4.1.2 and Selenium 0.2.2. It may not recognize a select field if the selected option with the text has no value. If you don't have the possibility to upgrade these Gems, probably the best way to go is to distinguish the current Capybara driver:

Then /^"([^"]*)" should be selected for "([^"]*)"(?: within "([^\"]*)")?$/ do |value, field, selector|
  with_scope(selector) do

    # currently needed due to different behav...

Fix YAML::Syck::DefaultKey:0x1083b59f8

When your gems complain about invalid gemspecs and illformed requirements, it is most probably an error resulting from the transition from Syck to psych. To fix this:

  1. go to your gemspec directory (e.g. /Library/Ruby/Gems/1.8/specifications/)
  2. change #<Syck::DefaultKey:0x00000100e779e8> to = (equals sign) in each file that's complaining

RestClient sends XML Accept header by default

REST Client is a nice, simple HTTP client library for Ruby.

When you do a simple GET request like that:

RestClient.get 'http://example.com/'

it will result in this request beeing sent to www.example.com:

GET / HTTP/1.1
Accept: */*; q=0.5, application/xml
Accept-Encoding: gzip, deflate
Host: www.example.com

The application/xml accept header might lead to unexpected results on your server. You can force REST Client to ask the server for default text/html that way:

RestC...

Ruby: Indent a string

Copy the attached file to config/initializers/indent_string.rb and you can say

"foo".indent(4) # "    foo"

Note you will find many simpler implementations of this method on the Interweb. They probably won't do what you want in edge cases, fuck up trailing whitespace, etc. The implementation in this card has the following behavior:

describe '#indent' do

  it 'should indent the string by the given number of spaces' do
    "foo".indent(2).should == "  foo"
  end

  it 'should indent multiple lines line by line' do

...

Use the "retry" keyword to process a piece of Ruby code again.

Imagine you have a piece of code that tries to send a request to a remote server. Now the server is temporarily not available and raises an exception. In order to re-send the request you could use the following snippet:

def remote_request
  begin
    response = RestClient.get my_request_url
  rescue RestClient::ResourceNotFound => error
    @retries ||= 0
    if @retries < @max_retries
      @retries += 1
      retry
    else
      raise error
    end
  end
  response
end

This sni...

Cucumber step to test that a tooltip text exists in the HTML

Tooltips that are delivered through HTML attributes are encoded. Decode entities before checking for their presence.

Capybara:

Then /^there should( not)? be a(n encoded)? tooltip "([^"]*)"$/ do |negate, encoded, tooltip|
  tooltip = HTMLEntities.new.encode(tooltip) if encoded
  Then "I should#{negate} see \"#{tooltip}\" in the HTML"
end

Note

This step uses the htmlentities gem described in another card.

Ma...