How to monitor Sidekiq: A working example
In order to have monitoring for Sidekiq (like queue sizes, last run of Sidekiq) your application should have a monitoring route which returns a json looking like this:
{
"sidekiq": {
"totals": {
"failed": 343938,
"processed": 117649167
},
"recent_history": {
"failed": {
"2016-11-06": 1,
"2016-11-07": 46,
"2016-11-08": 0,
"2016-11-09": 0,
"2016-11-10": 0
},
"processed": {
"2016-11-06": 230653,
"2016-11-07": 230701,
"2016-11-08"...
Detecting if a Ruby gem is loaded
Detect if a gem has been activated
A gem is activated if it is either in the current bundle (Gemfile.lock
), or if you have manually activated it using Kernel#gem
(old-school).
To detect if e.g. activerecord
has been activated:
if Gem.loaded_specs.has_key?('activerecord')
# ActiveRecord was activated
end
Detect if a particular gem version has been activated
To detect if e.g. activerecord
ma...
makandra/gemika: Helpers for testing Ruby gems
We have released a new library Gemika to help test a gem against multiple versions of Ruby, gem dependencies and database types.
Here's what Gemika can give your test's development setup (all features are opt-in):
- Test one codebase against multiple sets of gem dependency sets (e.g. Rails 4.2, Rails 5.0).
- Test one codebase against multiple Ruby versions (e.g. Ruby 2.1.8, Ruby 2.3.1).
- Test one codebase against multiple database types (currently MySQL or PostgreSQL).
- Compute a matrix of all possib...
Measuring sql query time of a piece of code using ActiveSupport::Notifications
ActiveSupport::Notifications provides an instrumentation API for Ruby. It is used throughout rails to publish instrumentation events that include information about each part of a request/response cycle.
Have a look at your application log file - yes, those are those events. The cool thing is that you can subscribe to those events.
There is also a convenience method that allows you to subscribe to those events only for the time of executing a block of code. Thus you can capture all sql queries that are triggered when executing your block....
Isolate Side Effects in Ruby
In this article, we’ll look at what side effects are, why they are problematic despite being necessary, and how to isolate them to minimise their drawbacks.
Capistrano: exclude custom bundle groups for production deploy
Capistrano is by default configured to exclude the gems of the groups development
and test
when deploying to the stages production
and staging
. Whenever you create custom groups in your Gemfile
, make sure to exclude these, if they should not be deployed to the servers. The gems of these groups might not be loaded by rails, however, the deployment process will take longer as the gems will be downloaded and installed to the server.
e.g. to exclude the groups cucumber
and deploy
, add the following to `config/deploy/production.rb...
Incredibly fast web apps // Speaker Deck
Presentation about optimizing Ruby on Rails apps.
From Nico Hagenburger (homify's lead frontend developer).
Ruby: __FILE__, __dir__ and symlinks
Ruby's __FILE__
keyword returns the path to the current file. On popular for this are Ruby binaries:
#!/usr/bin/env ruby
$LOAD_PATH << File.expand_path('../../lib', __FILE__)
require 'my_cli'
MyCli.run!
However, if you create a symlink to this file, this will no longer work. __FILE__
will resolve to the path of the symlink, not to its target.
One solution is to use File.realpath(__FILE__)
.
In Ruby 2+ you can also use this:
$LOAD_PATH << File.expand_path('../lib', __dir__)
__dir__
is simply a shortcut for `Fi...
Represent astral Unicode characters in Javascript, HTML or Ruby
Here is a symbol of an eight note: ♪
Its two-byte hex representation is 0x266A.
This card describes how to create a string with this symbol in various languages.
All languages
Since our tool chain (editors, languages, databases, browsers) is UTF-8 aware (or at least doesn't mangle bytes), you can usually get away with just pasting the symbol verbatim:
note = '♪'
This is great for shapes that are easily recognized by your fellow programmers.
It's not...
There is no real performance difference between "def" and "define_method"
You can define methods using def
or define_method
. In the real world, there is no performance difference.
define_method
is most often used in metaprogramming, like so:
define_method :"#{attribute_name}_for_realsies?" do
do_things
end
Methods defined via define_method
are usually believed to have worse performance than those defined via def
.
Hence, developers sometimes prefer using class_eval
to define methods using def
, like this:
class_eval "def #{attribute_name}_for_realsies?; do_things; end"
You can be...
has_one association may silently drop associated record when it is invalid
This is quite an edge case, and appears like a bug in Rails (4.2.6) to me.
Update: This is now documented on Edgeguides Ruby on Rails:
If you set the :validate option to true, then associated objects will be validated whenever you save this object. By default, this is false: associated objects will not be validated when this object is saved.
Setup
# post.rb
class Post < ActiveRecord::Base
has_one :attachment
end
# attachment....
Ruby's default encodings can be unexpected
Note: This applies to plain Ruby scripts, Rails does not have this issue.
When you work with Ruby strings, those strings will get some default encoding, depending on how they are created. Most strings get the encoding Encoding.default_internal
or UTF-8, if no encoding is set. This is the default and just fine.
However, some strings will instead get Encoding.default_external
, notably
- the string inside a
StringIO.new
- some strings created via
CSV
- files read from disk
- strings read from an IRB
Encoding.default_external
d...
Ruby 2.3 new features
Ruby 2.3.0 has been around since end of 2015. It brings some pretty nice new features! Make sure to read the linked post with its many examples!
Hash#fetch_values
Similar to Hash#fetch, but for multiple values. Raises KeyError
when a key is missing.
attrs = User.last.attributes
attrs.fetch_values :name, :email
Hash#to_proc
Turns a Hash into a Proc that returns the corresponding value when called with a key. May be useful with enumerators like #map
:
attrs.to_proc.call(:name)
attrs.keys.grep(/name/).map &attrs...
Download Ruby gems without installing
You can download .gem
files using gem fetch
:
gem fetch activesupport consul
This will produce files like active-support-5.0.0.gem
and consul-0.12.1.gem
in your working directory.
Dependencies will not be downloaded.
Ruby 2.3.0 has a safe navigation operator
As announced before, Ruby has introduced a safe navigation operator with version 2.3.0. receiver&.method
prevents NoMethodError
s by intercepting method invocations on nil
.
user = User.last
user&.name # => "Dominik"
# When there is no user, i.e. user is nil:
user&.name # => nil
This might remind you of andand
, and indeed it behaves very similar. The only difference is in handling of `fa...
Ruby 2.3 brings Array#dig and Hash#dig
#dig
lets you easily traverse nested hashes, arrays, or even a mix of them. It returns nil
if any intermediate value is missing.
x = {
foo: {
bar: [ 'a', { baz: 'x' } ]
}
}
x.dig(:foo, :bar) # => [ 'a', { baz: 'x' } ]
x.dig(:foo, :bar, 1, :baz) # => "x"
x.dig(:foo, :wronk, 1, :baz) # => nil
There is a tiny gem that backports this.
Testing terminal output with RSpec
When testing Ruby code that prints something to the terminal, you can test that output.
Since RSpec 3.0 there is a very convenient way to do that.
Anything that writes to stdout (like puts
or print
) can be captured like this:
expect { something }.to output("hello\n").to_stdout
Testing stderr works in a similar fashion:
expect { something }.to output("something went wrogn\n").to_stderr
Hint: Use heredoc to test multi-line output.
expect { something }.to output(<<-MESSAGE.strip_heredoc).to_stdout...
PostgreSQL and its way of sorting strings
PostgreSQL uses the C library's locale facilities for sorting strings:
- First, all the letters are compared, ignoring spaces and punctuation.
- It sorts upper and lower case letters together. So the order will be something like
a A b B c C
- Then, spaces and punctuation are compared to break ties.
Example:
Ruby | PostgreSQL |
---|---|
IMAGE3.jpg | image2.jpg |
image.jpg | image3.jpg |
image2.jpg | IMAGE3.jpg |
image3.jpg | image.jpg |
[PostgreSQL-FAQ: Why_do_my_strings_sort_incorrectly](https://wiki.postgresql.org/w...
Ruby: Converting UTF-8 codepoints to characters
Converting string characters to or from their integer value (7-bit ASCII value or UTF-8 codepoint) can be done in different ways in Ruby:
-
String#ord
orString#unpack
to get character values -
Integer#chr
orArray#pack
to convert character values into Strings
Character values to Strings
Integer#chr
To get the character for a 7-bit ASCII value or UTF-8 codepoint (0-127) you can use Integer#chr
:
116.chr
# => "t"
To get a character for values larger than 127, you need to pass the encoding. E.g. to get codepoint 25...
How to organize monkey patches in Ruby on Rails projects
As your Rails project grows, you will accumulate a number of small patches. These will usually fix a bug in a gem, or add a method to core classes.
Instead of putting many files into config/initializers
, I recommend to group them by gem in lib/ext
:
lib/
ext/
factory_girl/
mixin.rb
carrierwave/
change_storage.rb
fix_cache_ids.rb
sanitize_filename_characters.rb
ruby/
range/
covers_range.rb
array/
dump_to_excel.rb
xss_aware_join.rb
enumerable/
...
Introducing Helix: Rust + Ruby, Without The Glue
Helix allows you to implement performance-critical code of your Ruby app in Rust, without requiring glue code to bridge between both languages.
See attached article for a longer write-up about the why and how.
How to Work With Time Zones in Rails
With different time zones
When dealing with time zones in Rails, there is one key fact to keep in mind:
Rails has configurable time zones, while
Ruby is always in the server's time zone
Thus, using Ruby's time API will give you wrong results for different time zones.
For consistency, you should only use Rails' methods, but the hard thing is to know which method originates from Ruby and which from Rails. To simplify this, adhere to the following suggestion:
Use
Time.zone
for everything time-related
# E...
Install MySQL 5.6 in Ubuntu 16.04
Instead of using this hack you might want to use MariaDB 10.x which can work with both old and new apps.
An alternative could be to use the MySQL Docker image which is still updated for 5.6.
Ubuntu 16.04 only provides packages for MySQL 5.7 which has a range of backwards compatibility issues with code written against older MySQL versions.
Oracle maintains a list of official APT repositories for MySQL 5.6, but those repositories do...
Using Bumbler to Reduce Runtime Dependencies - The Lean Software Boutique
Tool to show you which gems are slow to load:
➜ git:(master) ✗ bundle exec bumbler
[################################################# ]
(49/65) travis-lint...
Slow requires:
110.21 render_anywhere
147.33 nokogiri
173.83 haml
179.62 sass-rails
205.04 delayed_job_active_record
286.76 rails
289.36 mail
291.98 capistrano
326.05 delayed_job
414.27 pry
852.13 salesforce_bulk_api