Working with or without time zones in Rails applications
Rails supports time zones, but there are several pitfalls. Most importantly because Time.now and Time.current are completely different things and code from gems might use one or the other.
Especially configuring an application that cares only about one time zone is a bit tricky.
The following was tested on Rails 5.1 but should apply to Rails 4.2 as well.
Using only local time
Your life will be easier if your application does not need to support time zones. Disable them like this:
config.time_zone = 'Berlin' # Your local ...
Listing all gems on a private gem server
You can use gem list to list all gems available from a remote gem server:
gem list -r --clear-sources -s 'https://user:password@gemserver.tld/'
This is useful to debug cases where Bundler complains of a gem existing in more than one gem source.
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 ...