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 callingpage.find(...)
. This way the behavior is only changed for this onefind
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...
Connecting the "sequel" gem to MSSQL via ODBC
After you configured your ODBC describe in
- Fix [RubyODBC]Cannot allocate SQLHENV when connecting to MSSQL 2005 with Ruby 1.8.7. on Ubuntu 10.10
- and Connecting to MSSQL with Ruby on Ubuntu - lambie.org
you can connect with sequel
:
require "rubygems"
require "se...
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.
 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
- Your current
ruby
must be Ruby Enterprise. gem install passenger
passenger-install-apache2-module
- Edit your
httpd.conf
according to the instructions provided at the end of the setup script. - 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:
- go to your gemspec directory (e.g.
/Library/Ruby/Gems/1.8/specifications/
) - 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...