Fix Capistrano with RubyGems 1.6
After updating your RubyGems, you will probably not be able to run Capistrano any more, but receive an error similar to this:
can't activate net-ssh (= 2.0.22) for [], already activated net-ssh-2.1.0 for [] (Gem::LoadError)
If you have Bundler installed, you can use bundle exec
to avoid this problem as follows:
Create a gemfile at ~/.capistrano/Gemfile
(or at some other sensible place), that only contains these 2 lines:
source 'http://rubygems.org'
gem 'capistrano'
gem 'capistrano-ext' # You need this for multistag...
Closures in Ruby
If you want to get a deep understanding of how closures, blocks, procs & lambdas in Ruby work, check out the code at the attached link.
Here the summary:
^
---------------------------- Section 6: Summary ----------------------------
So, what's the final verdict on those 7 closure-like entities?
"return" returns from closure
True closure? or declaring context...? Arity check?
...
Maximum representable value for a Ruby Time object
On 32bit systems, the maximum representable Time is 2038-01-19 03:14:07
in UTC or 2038-01-19 04:14:07
in CET. If you try to instantiate a Time
with any later value, Ruby will raise an ArgumentError
.
If you need to represent later time values, use the DateTime class. This is also what Rails does when it loads a record from the database that has a DATETIME value which Time
cannot represent. Note that there are some [subtle differences](http://stackoverflow.com/quest...
Dump your database with dumple
This tool is used on our application servers (and called when deploying) but it also works locally.
Just call dumple development
from your project directory to dump your database.
This script is part of our geordi gem on github.
Validate an XML document against an XSD schema with Ruby and Nokogiri
The code below shows a method #validate
which uses Nokogiri to validate an XML document against an XSD schema. It returns an array of Nokogiri::XML::SyntaxError objects.
require 'rubygems'
gem 'nokogiri'
require 'nokogiri'
def validate(document_path, schema_path, root_element)
schema = Nokogiri::XML::Schema(File.read(schema_path))
document = Nokogiri::XML(File.read(document_path))
schema.validate(document.xpath("//#{root_element}").to_s)
end
v...
Testing if two date ranges overlap in Ruby or Rails
A check if two date or time ranges A and B overlap needs to cover a lot of cases:
- A partially overlaps B
- A surrounds B
- B surrounds A
- A occurs entirely after B
- B occurs entirely after A
This means you actually have to check that:
- neither does A occur entirely after B (meaning
A.start > B.end
) - nor does B occur entirely after A (meaning
B.start > A.end
)
Flipping this, A and B overlap iff A.start <= B.end && B.start <= A.end
The code below shows how to implement this in Ruby on Rails. The example is a class `Interv...
Dynamic conditions for belongs_to, has_many and has_one associations
Note: Consider not doing this. Use form models or vanilla methods instead.
The :conditions
option for Rails associations cannot take a lambda. This makes it hard to define conditions that must be evaluated at runtime, e.g. if the condition refers to the current date or other attributes.
A hack to fix this is to use faux string interpolation in a single-quoted :conditions
string:
class User < ActiveRecord::Base
has_many :contracts
has_one :current_contract, :class_name => 'Contract', :conditions => '...
Calling selected methods of a module from another module
Given those modules:
module A
def foo; end
def bar; end
end
module B
end
When you want to call methods from A
inside B
you would normally just include A
into B
:
module B
include A
end
Including exposes all of A
's methods into B
. If you do not want this to happen, use Ruby's module_function
: it makes a module's method accessible from the outside. You could put the module_function
calls into A
but it would remain unclear to peop...
Split an array into groups
Given group size
If you would like to split a Ruby array into pairs of two, you can use the Rails ActiveSupport method in_groups_of:
>> [1, 2, 3, 4].in_groups_of(2)
=> [[1, 2], [3, 4]]
>> [1, 2, 3, 4, 5].in_groups_of(2)
=> [[1, 2], [3, 4], [5, nil]]
>> [1, 2, 3, 4, 5].in_groups_of(2, 'abc')
=> [[1, 2], [3, 4], [5, 'abc']]
>> [1, 2, 3, 4, 5].in_groups_of(2, false)
=> [[1, 2], [3, 4], [5]]
Given group cou...
How to define constants with traits
When defining a trait using the Modularity gem, you must take extra steps to define constants to avoid caveats (like when defining subclasses through traits).
tl;dr
In traits, always define constants with explicit
self
.
If your trait defines a constant inside the as_trait
block, it will be bound to the trait module, not the class including the trait.
While this may seem unproblematic at first glance, it becomes a problem when including trai...
Access the documentation of all locally installed gems
In case https://www.rubydoc.info/ is to slow or offline, you can also read a gem documentation offline.
Start a server with gem server
and go to http://0.0.0.0:8808/
. Here you will find a list of all installed gems and it is possible to navigate to the documentation if installed e.g. http://0.0.0.0:8808/doc_root/rubocop-0.77.0/
In case you set the configured RubyGems to not install documentation by default, you need to add generate the documentation for the specific gem.
gem install rubocop --document
`...
ETags with memcached
I love ETags, but there’s something that annoys me: most implementations revolve around pulling a record out of a data store and only “rendering” the response if it hasn’t been modified.
The problem with this approach is that request has already gone through most of your application stack–parsing params, authentication, authorization, a few database lookups–so ETags are only saving you render time and some bandwidth.
While working on a Sinatra-based JSON web service that gets very heavy traffic, I wanted to find a way to short-circuit...
Always show the page if there is an error in Cucumber
Are you adding a "Then show me the page
" and re-run Cucumber whenever there is a failing scenario? Don't be that guy!
Save time with the shiny new version of our cucumber_spinner gem. It comes with a Cucumber formatter that not only displays an awesome progress bar, and shows failing scenarios immediately, it will also open the current page in your browser whenever a scenario step fails.
After you installed the gem, use the formatter like this:
cucumber --format CucumberSpinner::Curiou...
How to fix "extconf.rb:8:in `require': no such file to load -- mkmf (LoadError)"
If you're on Ubuntu:
sudo apt-get install ruby-dev
On other platforms: Look for a package containing ruby header files. On Red Hat that's "ruby-devel" likely.
Shell script to clean up a project directory
Call geordi clean
from a project root to remove unused and unnecessary files inside it.
This script is part of our geordi gem on github. In Geordi > 1.2 you can call geordi clean
.
Speed up RSpec by deferring garbage collection
Update: This trick probably isn't very useful anymore in Ruby 2.x. The Ruby GC has improved a lot over the years.
Joe Van Dyk discovered that running the Ruby garbage collector only every X seconds can speed up your tests. I found that deferring garbage collection would speed up my RSpec examples by about 15%, but it probably depends on the nature of your tests. I also tried applying it to Cucumber f...
Silencing Deprecation Warnings in Rspec
If you’re testing the behavior of deprecated code in your Ruby project, the warning messages littered throughout your spec output is incredibly noisy.
You could silence all warnings with ::ActiveSupport::Deprecation.silenced = true, but you might miss out on an important warning in one of your dependencies. It’s tempting to remove the tests altogether (the code will be burned soon too, right?), but I figured out something a little nicer a little while back in Formtastic’s test suite.
Iterate over every n-th element of a Range in Ruby
If you want to iterate over a Range, but only look at every n-th element, use the step
method:
(0..10).step(5).each do |i|
puts i
end
# Prints three lines:
# 0
# 5
# 10
This is useful e.g. to iterate over every Monday in a range of Dates
.
If you are using Rails or ActiveSupport, calling step
without a block will return an array of matching elements:
(0..10).step(5)
# => [0, 5, 10]
Default block arguments for Ruby 1.8.7
When your block takes an argument that should have an default, only in Ruby 1.9 you can say:
block = lambda do |message, options = {}|
# ...
end
If you are on Ruby 1.8.6 or 1.8.7 you must resort to the following workaround:
block = lambda do |*args|
message = args[0]
options = args[1] || {}
end
Overriding unary operators in Ruby
This must be one of the coolest, yet quite unknown, technique in Ruby. For certain types of problems (e.g. when you have a set of rules) this gives you such an elegant way of describing the solution. There’s no meta programming or monkey patching involved, it’s short and sweet and best of all: it’s very intuitive.
Word boundaries in MySQL regular expressions
In regular expressions you can use the zero-width pattern \b
to match the beginning or end of a word:
note.title =~ /\bfoo\b/
Unfortunately \b
is not available in MySQL. You can use [[:<:]]
and [[:>:]]
to match the beginning and end of a word instead:
SELECT * FROM notes WHERE title REGEXP "[[:<:]]foo[[:>:]]"
These markers are unique to MySQL and not available in Ruby regular expressions.
RSpec matcher to check if two numbers are the same
You can usually just use the eq
matched to compare two numbers:
expect(deal.total).to eq(120)
If the actual value is a BigDecimal
, you might have issues when you match it against a Float
:
expect(deal.total_price).to eq(1200.99)
In these cases, try matching it against another BigDecimal
:
expect(deal.total_price).to eq BigDecimal(1200.99)
If you don't like the syntax, our rspec_candy gem has a matcher that will compare Fixnums
(integers), Floats
and `BigDecima...
The Ruby Infinite Hash
How to create an infinitely nestable hash that always defaults to a new hash if a key does not map to a value.
Force net/http to verify SSL certificates
Ruby's net/http is setup to never verify SSL certificates by default. Most ruby libraries do the same. That means that you're not verifying the identity of the server you're communicating with and are therefore exposed to man in the middle attacks. This gem monkey-patches net/http to force certificate verification and make turning it off impossible.