Standard Gems
Ruby's standard library is in the process of being gemified. It will soon - Ruby 2.5 - consist of RubyGems, which can be updated independently from Ruby.
This might mean smoother Ruby upgrades in the future. If breaking API changes happen in standard gems, we can update these before upgrading Ruby.
Middleman configuration for Rails Developers
Middleman is a static page generator that brings many of the goodies that Rails developers are used to.
Out of the box, Middleman brings Haml, Sass, helpers etc. However, it can be configured to do even better. This card is a list of improvement hints for a Rails developer.
Gemfile
Remove tzinfo-data
and wdm
unless you're on Windows. Add these gems:
gem 'middleman-livereload'
gem 'middleman-sprockets' # Asset pipeline!
gem 'bootstrap-sass' # If you want to use Bootstrap
gem 'byebug'
gem 'capistrano'
gem 'capistrano-mid...
Quickly printing data in columns on your Ruby console
Dump this method into your Ruby console to quickly print data in columns. This is helpful for e.g. comparing attributes of a set of Rails records.
def tp(objects, *method_names)
terminal_width = `tput cols`.to_i
cols = objects.count + 1 # Label column
col_width = (terminal_width / cols) - 1 # Column spacing
Array(method_names).map do |method_name|
cells = objects.map{ |o| o.send(method_name).inspect }
cells.unshift(method_name)
puts cells.map{ |cell| cell.to_s.ljust(col_width) }.join ' '
end
nil
end
Usag...
Howto: Require a gem that is not in Gemfile
In case you want to require a gem, that is not in the Gemfile of you bundle and therefore not in your loadpath, you need to add the path manually and require the gem afterwards.
Expected error
Requiring a gem, that is not in the Gemfile
or .gemspec
, will cause an LoadError
exception:
require 'example_gem' => LoadError: cannot load such file -- example_gem
Adding a gem to the loadpath temporary
- You need to install the
gem
gem install 'example_gem'
- Then you need to require the path where the gem was install...
Storing trees in databases
This card compares patterns to store trees in a relation database like MySQL or PostgreSQL. Implementation examples are for the ActiveRecord ORM used with Ruby on Rails, but the techniques can be implemented in any language or framework.
We will be using this example tree (from the acts_as_nested_set docs):
root
|
+-- Child 1
| |
| +-- Child 1.1
| |
| +-- Child 1.2
|
+-- ...
How to use Parallel to speed up building the same html partial multiple times (for different data)
The parallel-gem is quite easy to use and can speed up rendering time if you want to render the same partial multiple times (e.g. for rendering long lists of things).
Parallel supports execution using forked processes (the default), threads (mind the GVL) and Ractors (some limitations for data sharing).
If your parallelized code talks to the database, you should [ensure not to leak database connections](https://makandracards.com/makandra/45360-using-activerecord-with-threads-will-leak-database-connect...
ruby-sass: Do not use comments between selector definitions
Sass lets you easily specify multiple selectors at once like this:
.some-block
&.has-hover,
&:hover
outline: 1px solid red
This will add a red outline on either real hover or when the has-hover
class is present. However, adding a comment will void the definition of that line:
.some-block
&.has-hover, // From hoverable.js <-- DON'T
&:hover
outline: 1px solid red
... will simply drop the &.has-hover
part in ruby-sass(deprecated). [sassc](https://rubygems.org/g...
Beware: Nested Spreewald patiently blocks are not patient
Note: The behaviour of Spreewald's within
step is as described below for version < 1.9.0; For Spreewald >= 1.9.0 it is as described in Solution 1.
When doing integration testing with cucumber and selenium you will often encounter problems with timing - For example if your test runs faster than your application, html elements may not yet be visible when the test looks for them. That's why Spreewald (a collection of cucumber steps) has a concept of doing things patiently
, which means a given b...
Generating barcodes with the Barby gem
Barby is a great Ruby gem to generate barcodes of all different sorts.
It includes support for QR codes via rQRCode; if you need to render only QR codes, you may want to use that directly.
Example usage
Generating a barcode is simple:
>> Barby::Code128.new('Hello Universe').to_png
=> "\x89PNG\r\n\u001A..."
Configuration
Barby supports several barcode types and you must require all necessary files explicitly.
For the example a...
ActiveRuby
Looks like ActiveState is trying to market a new Ruby distribution for Enterprises:
ActiveRuby Enterprise Edition is designed for businesses with large Ruby deployments in essential, mission-critical applications that, when down, could cost your business in lost revenue and a damaged reputation. Deploy Ruby with confidence knowing you're using the most secure, enterprise-grade builds for the platforms that power your business. You'll get priority access to our Ruby experts for technical support and best prac...
Running external commands with Open3
There are various ways to run external commands from within Ruby, but the most powerful ones are Open3.capture3
and Open3.popen3
. Since those can do almost everything you would possibly need in a clean way, I prefer to simply always use them.
Behind the scenes, Open3
actually just uses Ruby's spawn
command, but gives you a much better API.
Open3.capture3
Basic usage is
require 'open3'
stdout_str, error_str, status = Open3.capture3('/some/binary', 'with', 'some', 'args')
if status.success?...
Ruby: Return boolean for regex comparison
A collection of code snippets which return a boolean value for a regex comparison.
regexp.match?(string) # Recommended for Ruby >= 2.4
!!(string =~ regexp) # Recommended for older Rubies
regexp === string
!(regexp !~ string)
The Ruby 2.4 method Regexp#match?
does not set globals like $~
or $1
, so it should be more performant.
Choosing the right gems for your project
Adding a gem means you take over the liability towards the external code.
Checklist
Based on "To gem, or not to gem":
- Gem is really needed (prefer writing your own code for simple requirements without many edge cases)
- Gem is tested well (coverage and quality)
- Gem has a good code quality
- Gem's licence fits to the project requirement
- Try to avoid gems that do much more than your requireme...
rbenv: A basic introduction
Why
We have projects that have been developed using many different versions of Ruby. Since we do not want to constantly update every old project, we need to have many Ruby versions installed on our development machines.
Rbenv does that for us.
How it works
Rbenv installs ruby version and ruby gems to ~/.rbenv/versions/VERSION_NUMBER/...
. This way many different Rubies can be installed at once.
When you run ruby
or gem
or bundler
or any other Ruby binary
- rbenv looks for a file...
When upgrading/downgrading RubyGems and Bundler on a server, you must clear bundled gems
On application servers, gems are usually bundled into the project directory, at a location shared across deployments.
This is usually shared/bundle
inside your project's root directory, e.g. /var/www/your-project/shared/bundle/
.
If you can't find that, take a look at current/.bundle/config
and look for BUNDLE_PATH
.
When you are changing the version of RubyGems or Bundler on a system where gems are installed this way, you must wipe that bundle directory in addition to the user and system gems or gems that are already ins...
Ruby 1.8.7: Bundler crashes with "deadlock" and core dump
Error
deadlock 0x7f8a4160a360: sleep:- (main) - /home/me/.rbenv/versions/1.8.7-p375/lib/ruby/gems/1.8/gems/bundler-1.14.3/lib/bundler/worker.rb:43
deadlock 0x7f8a38c03b08: sleep:- - /home/me/.rbenv/versions/1.8.7-p375/lib/ruby/gems/1.8/gems/bundler-1.14.3/lib/bundler/worker.rb:56
*** longjmp causes uninitialized stack frame ***: /home/me/.rbenv/versions/1.8.7-p375/bin/ruby terminated
... followed by a backtrace, memory map and more.
Fix
The culprit seems to be Bundler 1.14 when used with Ruby 1.8.7. [Downgrade to the maximu...
Error "undefined method last_comment"
This error message may occur when rspec gets loaded by rake, e.g. when you migrate the test database.
NoMethodError: undefined method 'last_comment' for #<Rake::Application:0x0055a617d37ad0>
Rake 11 removes a method that rspec-core
< 3.4.4 depends on. To fix, lock Rake to < 11 in your Gemfile:
gem 'rake', '< 11', # Removes a method that rspec-core < 3.4 depends on
How to install guard-livereload 2.5.2 on Ruby < 2.2.5
There are some inconvenient Gem dependencies. Resolve them by adding/modifying these lines in your Gemfile:
gem 'guard-livereload', '>= 2.5.2', require: false # Fixes a security issue
gem 'listen', '< 3.1' # 3.1 requires Ruby 2.2.5
It is not possible to install guard-livereload
2.5.2 on Ruby 1.8.7 because it depends on guard
2.8, which requires Ruby 1.9.
JSONP for Rails
The rack-contrib gem brings a JSONP middleware that just works™. Whenever a JSON request has a callback
parameter, it will wrap the application's JSON response appropriately.
The project is a bit dated, but the JSONP middleware is ok.
[jruby] TruffleRuby Status, start of 2017
TruffleRuby is an experimental Ruby implementation that tries to achieve ~10x performance over MRI.
This has been on our radar for a while. They seem to have made significant progress running Rails, reducing start-up time and becoming runtime-independent of the JVM.
Also see [Running Optcarrot, a Ruby NES emulator, at 150 fps with the GUI!](https://eregon.me/blog/2016/11/28/optcarrot.htm...
How to tackle complex refactorings in big projects
Sometimes huge refactorings or refactoring of core concepts of your application are necessary for being able to meet new requirements or to keep your application maintainable on the long run. Here are some thoughts about how to approach such challenges.
Break it down
Try to break your refactoring down in different parts. Try to make tests green for each part of your refactoring as soon as possible and only move to the next big part if your tests are fixed. It's not a good idea to work for weeks or months and wait for all puzzle pieces ...
Enabling ** in your bash
You may know the double asterisk operator from Ruby snippets like Dir['spec/**/*_spec.rb']
where it expands to an arbitrary number of directories.
However, it is disabled by default on most systems. Here is how to enable it.
If you check your globstar
shell option, it is probably disabled:
$ shopt globstar
globstar off
In that case, **
behaves just like *
and will match exactly 1 directory level.
$ ls spec/**/*_spec.rb
spec/models/user_spec.rb
To enable it, run
shopt -s globstar
The double ast...
Ruby: String representations of regular expressions
Ruby's regular expressions can be represented differently.
When serializing them, you probably want to use inspect
instead of to_s
.
For the examples below, consider the following Regexp
object.
regexp = /^f(o+)!/mi
to_s
Using to_s
will use a format that is correct but often hard to read.
>> regexp.to_s
=> "(?mi-x:^f(o+)!)"
inspect
As the Ruby docs say:
...