Nokogiri: CSS syntax for XML namespaces
<soapenv:Envelope>
<soapenv:Body>
<elem>
<nest>...</nest>
</elem>
</soapenv:Body>
</soapenv:Envelope>
CSS selectors are a very simple tool to select elements from a Nokogiri document. However, the colon in the XML namespace syntax does not work with CSS. When selecting namespaced elements, you need to replace their colon (soapenv:Envelope
) with a pipe (soapenv|Envelope
):
document = Nokogiri::XML(xml)
nest = document.at_css 'soapenv|Envelope soapenv|Body elem nest'
Cucumber may complain about cucumber.yml being invalid when it is valid
Running Cucumber tests while your cucumber.yml is 100% valid may still produce the following error.
cucumber.yml was found, but could not be parsed. Please refer to cucumber's documentation on correct profile usage.
This may in fact be due to your rerun file (e.g. tmp/rerun.txt
) being invalid. Delete it and try again.
Legacy CarrierWave: How to generate versions with different file extensions
We use CarrierWave in many of our projects to store and serve files of various formats - mostly images. A common use case of CarrierWave's DSL is to "process" the original file in order to create multiple "versions", for example different resolutions of the same image.
Now we could go one step further: What if we want to create versions that have a different file extension than the original file? For example, let's assume we'd like to create a ve...
How Rails and MySQL are handling time zones
When working with times and dates in Rails applications, you need to deal with the following problem:
- In Rails,
Time
objects have a time zone. You can get the zone name by doingtime_object.zone
. - This zone is considered when doing time calculations, e.g. 10 AM CEST minus 8 AM UTC is zero.
- A datetime in MySQL does not have a zone. It just stores the literal string "2010-05-01 12:00:00".
- That means that Rails must make assumptions about timestamps loaded from and written to MySQL.
Rails has two completely different modes ...
You don't need each, collect or select in Coffeescript
Working with lists in Javascript is painful because the native Array
class is so poorly designed.
One way to reduce the pain is to to use Underscore.js's functions like _.each
, _.map
or _.select
, which unfortunately clutters your code with awkward calls to the _
helper.
Fortunately when you use CoffeeScript you don't need any of that. CoffeeScript has a very versatile for
keyword that can do anything that each
, collect
or select
can do. Enjoy!
each
f...
Rspec: How to write better specs
betterspecs.org is a documentation on how to write better RSpec tests.
Note that there are also other approaches like The Self-Contained Test, which is complementary to the dry-approches in betterspecs. Like usual you need to weight the different recommendation and there is no rule of thumb for all specs.
How to reset a Mock
With Rspec you can mock objects or functions, for example like this:
expect(my_object).to receive(:my_function).and_return('hello world')
It's also easy to remove mocks for an object:
RSpec::Mocks.space.proxy_for(my_object).reset
whenever: Installing cron jobs only for a given Rails environment or Capistrano stage
We use the whenever gem to automatically update the crontab of the servers we deploy to. By default, whenever will update all servers with a matching role (we use the :cron
role ).
This card describes how to install some tasks only for a given Rails environment or for a given Capistrano stage ("deployment target").
Installing jobs only for a given Rails environment
-----------------------------------...
How Ruby method lookup works
When you call a method on an object, Ruby looks for the implementation of that method. It looks in the following places and uses the first implementation it finds:
- Methods from the object's singleton class (an unnamed class that only exists for that object)
- Methods from prepended modules (Ruby 2.0+ feature)
- Methods from the object's class
- Methods from included modules
- Methods from the class hierarchy (superclass and its an...
Rspec: Expecting a Rake task to be called
This seems to be obvious, but you can expect Rake tasks to be called in RSpec.
it 'deletes all Users' do
FactroyBot.create(:user)
expect(Rake::Task['notify:critical_operation']).to receive(:invoke)
expect { described_class.clean }.to change(User, :count).from(1).to(0)
end
Note: Try to avoid logic in rake tasks and prefer to just call classes in them.
Example:
desc 'Some task'
task :some_task do
SomeClass.new.run
end
How to use git fixup
Using git fixup helps you to speed up appending changes further back in the git history of your feature branch.
Example:
git commit --fixup aabbcc # Create a commit with the message "fixup! Commit message of aabbcc"
git rebase -i --autosquash master
It would be nice if you could use this feature without the -i
flag, but until now it seems not to be possible. Read more about our recommended git workflow for feature branches.
Also have a look at [git shortcut to use git fixup](https://makandracards.com/makand...
Installing multiple MySQL versions on the same Linux with mysql-sandbox
Ubuntu has a package mysql-sandbox
that lets you install multiple MySQL versions into your user home:
- Install
mysql-sandbox
sudo apt install mysql-sandbox
-
Download the version of MySQL you want to use from mysql.com:
https://dev.mysql.com/downloads/file/?id=480427
Make sure to choose "Generic Linux" instead of "Ubuntu" so you get a .tar.gz instead of .deb -
cd
into the directory the mysql binaries will be extracted to
mkdir -p ~/bin/sandbox_dist
cd ~/bin/sandbox_dist
- Build the sandbox
make_sandbo...
Rails: When defining scopes with class methods, don't use `self`
Sometimes it is useful to define a named scope by implementing a static method with the scope's name on the scoped class. For instance, when a method should decide which existing scope should be the next link in the scope chain. Take this class for example:
class Meal < ActiveRecord::Base
named_scope :for_date, lambda { |date| :conditions => { :date => date }}
named_scope :with_meat, :conditions => { :meat => true }
named_scope :without_meat, :conditions => { :meat => false }
def self.suitable_for(user)
if user.vegetar...
Rubygems: Installing the last version of rubygems that has no rubyforge_project deprecation warning
You can install rubygems 3.0.8
(released on February 18, 2020) to keep all the Gem::Specification#rubyforge_project
deprecation warnings away from your development log. With Rubygems >= 3.1
this deprecation warning was introduced. While maintaining older projects this could get quite annoying and the fix below might okey, for newer projects the right ways is to upgrade the gems.
gem update --system 3.0.8
Example message:
NOTE: Gem::Specification#rubyforge_project= is deprecated with no replacement. It will be removed o...
Git: How to add changes matching a regular expression
When you have many changes, and you want to spread them across different commits, here is a way to stage all changes matching a given regular expression for a single commit.
Example
Consider the following git diff
output.
diff --git a/file1.rb b/file1.rb
index 806ca88..36d536b 100644
--- a/file1.rb
+++ b/file1.rb
@@ -1,7 +1,5 @@
-# Here is a useless comment.
-# It will be removed.
class File1
- def foo
+ def bar
# ...
end
end
diff --git a/file2.rb b/file2.rb
index 550e1c6..600f4e3 100644
--- a/file2.rb
+++ b/file2...
Five years of "Today I Learned" from Josh Branchaud
The linked GitHub repository is a bit like our "dev" cards deck, but groomed from a single person (Josh Branchaud). It includes an extensive list of over 900 TILs on many topics that might be interesting for most of us. (e.g. Ruby, Rails, Git, Unix..)
Ruby
Here is an excerpt of all the Ruby TILs that were new to me. I encourage you to take your time to skim over the original list as well!
-
Assoc For Hashes
- `Hash#ass...
Rails: Concurrent requests in development and tests
With puma
you can have concurrent requests. There are two concepts on how Puma can handle two incoming requests: Workers and Threads.
Workers
Puma can have multiple workers. Each worker is a process fork from puma and therefore a very heavy instance and can have multiple threads, that handle the incoming requests.
Example: A Puma server with 2 workers
and 1 thread
each can handle 2 request in parallel
. A third request has to wait until the thread of one of the workers is free.
Threads
Rails is thread-safe since version 4 (n...
How to use Simplecov to find untested code in a Rails project with RSpec and Cucumber
Simplecov is a code coverage tool. This helps you to find out which parts of your application are not tested.
Integrating this in a rails project with rspec, cucumber and parallel_tests is easy.
-
Add it to your Gemfile and bundle
group :test do gem 'simplecov', require: false end
-
Add a
.simplecov
file in your project root:SimpleCov.start 'rails' do # any custom configs like groups and filters can be here at a central place enable_cov...
Using #deep_dup for copying whole hashes and array
"Everything in Ruby is an object". This is also true for nested hashes and arrays. If you copy a hash with #clone
or #dup
and you modify the copy, you will run into the following behavior:
original_hash = { foo: { bar: 'original value' } }
copied_hash = original_hash.dup
copied_hash[:foo][:bar] = 'changed value'
original_hash # => { foo: { bar: "changed value" }
This is, because { bar: 'baz' }
is an object, which is referenced in :foo
. The copy of original_hash
still holds the reference to the same object, so alterin...
How to: Throttle CPU in Google Chrome
Chrome allows you to throttle the Network and the CPU. Both settings are useful to measure the performance of you application and reproduce performance issues (Example Debugging frontend performance issues with Chrome DevTools).
You find the settings in: DevTools
> Performance
> Capture Settings (Gear icon in the right corner)
> `CPU: No...
Video transcoding: Web and native playback overview (April 2020)
Intro
Embedding videos on a website is very easy, add a <video>
tag to your source code and it just works. Most of the time.
The thing is: Both the operating system and Browser of your client must support the container and codecs of your video. To ensure playback on every device, you have to transcode your videos to one or more versions of which they are supported by every device out there.
In this card, I'll explore the available audio and video standards we have right now. The goal is to built a pipeline that...
Devise: How to allow only HTTP Basic Auth and disable the HTML sign-in form
By default, Devise redirects to a sign-in form when accessing a route that requires authentication. If for some reason you do not want this, but use Basic Authentication (and the corresponding browser username/password dialog) instead, this is a simple change.
Note that Devise's default configuration actually only redirects requests for HTML content (as requested by the HTTP Accept
header).
For all other formats (like JSON) it would use Basic Auth if the http_authenticatable
setting was enabled. So you can simply enable that flag and cl...
How to write good code comments
Code comments allow for adding human readable text right next to the code: notes for other developers, and for your future self. You can imagine comments as post-its (or sometimes multi-sheet letters ...) on real-world objects like cupboards, light switches etc.
As always, with power comes responsibility. Code comments can go wrong in many ways: they may become outdated, silently move away from the code they're referring to, restate the obvious, or just clutter files.
Good Comments
Here are some simple rules to keep your comments help...