Mailcatcher: An alternative to inaction_mailer
Looks simpler than inaction_mailer:
gem install mailcatcher
mailcatcher
Setup Rails to send mails to 127.0.0.1:1025. Usually you want the following config in config/environments/development.rb and maybe in test.rb or cucumber.rb.
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => 'localhost',
:port => 1025
}
Now you can see sent mails in your browser when opening http://127.0.0.1:1080
Note: In order to s...
Using before(:context) / before(:all) in RSpec will cause you lots of trouble unless you know what you are doing
TL;DR Avoid before(:context) (formerly before(:all)), use before(:example) (formerly before(:each)) instead.
If you do use before(:context), you need to know what you are doing and take care of any cleanup yourself.
Why?
Understand this:
-
before(:context)is run when thecontext/describeblock begins, -
before(:context)is run outside of transactions, so data created here will bleed into other specs -
before(:example)is run before each spec inside it,
Generally, you'll want a clean setup for each s...
Spreewald: Content-Disposition not set when testing a download's filename
Precondition
- You are not using javascript tests
- The file is served from a public folder (not via controller)
Problem description
If you deliver files from a public folder it might be that the Content-Disposition header is not set. That's why the following spreewald step might raise an error:
Then I should get a download with filename "..."
expected: /filename="some.pdf"$/
got: nil (using =~) (RSpec::Expectations::ExpectationNotMetError)
Solution
One solution...
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...
When does Webpacker compile?
Webpack builds can take a long time, so we only want to compile when needed.
This card shows what will cause Webpacker (the Rails/Webpack integration) to compile your assets.
When you run a dev server
While development it is recommended to boot a webpack dev server using bin/webpack-dev-server.
The dev server compiles once when booted. When you access your page on localhost before the initial compilation, the page may load without assets.
The ...
Geordi 1.3 released
Changes:
- Geordi is now (partially) tested with Cucumber. Yay!
- geordi cucumber supports a new @solo tag. Scenarios tagged with
@solowill be excluded from parallel runs, and run sequentially in a second run - Support for Capistrano 2 AND 3 (will deploy without
:migrationson Capistrano 3) - Now requires a
.firefox-versionfile to set up a test firefox. By default now uses the system Firefox/a test Chrome/whatever and doesn't print warnings any more. -
geordi deploy --no-migrations(aliased-M): Deploy with `cap ...
Jasmine: Testing AJAX calls that manipulate the DOM
Here is a Javascript function reloadUsers() that fetches a HTML snippet from the server using AJAX and replaces the current .users container in the DOM:
window.reloadUsers = ->
$.get('/users').then (html) ->
$('.users').html(html)
Testing this simple function poses a number of challenges:
- It only works if there is a
<div class="users">...</div>container in the current DOM. Obviously the Jasmine spec runner has no such container. - The code requests
/usersand we want to prevent network interaction in our uni...
Debug Ruby code
This is an awesome gadget in your toolbox, even if your test coverage is great.
-
gem install ruby-debug(Ruby 1.8) orgem install debugger(Ruby 1.9) - Start your server with
script/server --debugger - Set a breakpoint by invoking
debuggeranywhere in your code - Open your application in the browser and run the code path that crosses the breakpoint
- Once you reach the breakpoint, the page loading will seem to "hang".
- Switch to the shell you started the server with. That shell will be running an irb session where you can step thr...
Interacting with a Microsoft Exchange server from Ruby
Microsoft Exchange service administrators can enable Exchange Web Services (EWS) which is a rather accessible XML API for interacting with Exchange. This allows you to read and send e-mails, create appointments, invite meeting attendees, track responses, manage to-do tasks, check user availability and all other sorts of things that are usually only accessible from Outlook.
You can implement an EWS by hand-rolling your XML (the [docs](http://msdn.microsoft.com/en-us/...
Protip: Clone large projects multiple times
Large projects usually have large test suites that can run for a long time.
This can be annoying as running tests blocks you from picking up the next story -- but it doesn't have to be that way!
Simply clone your project's repo twice (or even more often).
When your work on a feature branch is done, simply push that branch and check it out on your 2nd copy to run tests there.
You can pick up a new story and work on that on your "main" project directory.
If you do it right, you will even be able to run tests in both your 2nd copy and your m...
Ruby: Comparing a string or regex with another string
In Rubocop you might notice the cop Style/CaseEquality for e.g. this example:
def foo(expected, actual)
expected === actual
end
In case expected is a Regex, it suggests to change it to the following pattern:
def foo(expected, actual)
expected.match?(actual)
end
In case expected is a Regex or a String, you need to keep ===. Otherwise the actual expression is always converted to a regular expression.
# For expected === actual
foo('Test(s)', 'Test(s)') #=> true
# For expected.match?(actual)
foo('Test(...
Mysql::Error: SAVEPOINT active_record_1 does not exist: ROLLBACK TO SAVEPOINT active_record_1 (ActiveRecord::StatementInvalid)
Possible Reason 1: parallel_tests - running more processes than features
If you run old versions of parallel_tests with more processes than you have Cucumber features, you will get errors like this in unexpected places:
This is a bug caused by multiple processes running the same features on the same database.
The bug is fixed in versions 0.6.18+.
Possib...
Case Study: Analyzing Web Font Performance
Table of contents of the linked article:
What are Web Fonts?
- Advantages of Web Fonts
- Disadvantages of Web Fonts
- Fallback Fonts
- CSS3 @font Declaration Example
- Fallback Font Example
- Render Blocking and Critical Rendering Path
- FOIT
Optimizing Web Font Delivery Further
- Prioritize Based On Browser Support
- Choose Only Styles You Need
- Character Sets
- Host Fonts Locally or Prefetch
- Store in LocalStorage with Base64 Encoding
- Another Method
Web Font Pe...
Geordi 1.0 released
Geordi 1.0 features a command line application geordi, that holds most of Geordi's previous commands.
New features
-
command help and usage examples right within
geordi(geordi helpandgeordi help <command>) -
quick command access: type just the first few letters of a command, e.g.
geordi rsorgeordi dev[server] -
command dependencies, e.g.
geordi rspecinvokesgeordi bundle-install(which bundles only if needed) -
no cluttered
/usr/bin, but all commands in one handy tool -
template for easily adding new...
Good real world example for form models / presenters in Rails
We have often felt the pain where our models need to serve too many masters. E.g. we are adding a lot of logic and callbacks for a particular form screen, but then the model becomes a pain in tests, where all those callbacks just get in the way. Or we have different forms for the same model but they need to behave very differently (e.g. admin user form vs. public sign up form).
There are many approaches that promise help. They have many names: DCI, presenters, exhibits, form models, view models, etc.
Unfortunately most of these approaches ...
esbuild: Make your Rails application show build errors
Building application assets with esbuild is the new way to do it, and it's great, especially in combination with Sprockets (or Propshaft on Rails 7).
You might be missing some convenience features, though.
Here we cover one specific issue:
Once you have started your development Rails server and esbuild with the --watch option (if you used jsbundling-rails to set up, you probably use bin/dev), esbuild will recompile your assets upon change, but build errors will only be printed to the terminal. Your application won't complain about them ...
Rspec 3: what to do when `describe` is undefined
When tests might not run with skipping RSpec in the RSpec.describe failing with the error undefined method 'describe' for main:Object this card will help you out!
In RSpec 3 the DSL like describe is exposed globally by default. Therefore it is not necessary to write Rspec.describe.
However, there is a config option to disable this beavior, which also disables the old should-syntax:
RSpec.configure do |config|
config.disable_monkey_patching!...
Always store your Paperclip attachments in a separate folder per environment
tl;dr: Always have your attachment path start with :rails_root/storage/#{Rails.env}#{ENV['RAILS_TEST_NUMBER']}/.
The directory where you save your Paperclip attachments should not look like this:
storage/photos/1/...
storage/photos/2/...
storage/photos/3/...
storage/attachments/1/...
storage/attachments/2/...
The problem with this is that multiple environments (at least development and test) will share the same directory structure. This will cause you pain eventually. Files will get overwritten and...
Postgres in Alpine docker container: sorting order might differ
In CI test runs I noticed that string sorting order changed after switching from a debian-based PostgreSQL docker image to one that is based on Alpine Linux.
Debian image sorting: bar Bar foo Foo
Alpine image sorting: Bar Foo bar foo
Explanation
Alpine Linux is a very slim linux distribution that results in small docker image sizes (roughly 100MB instead of 150MB), so it's a popular choice. However, it does not have all comman locales installed and does not use all locales that a user installs by default.
Postgres orders string co...
Using Spring and parallel_tests in your Rails application
You want Spring for super-fast binstubs like bin/rails or bin/rspec which avoid Rails boot time.
You want parallel_tests to speed up full test runs of large test suites.
Unfortunately, you do not want parallel_tests to use your Spring binstubs as those parallelized tests will share data and/or loose some information. There are some issues about this on GitHub and there is a suggested [workaround](https:...
git: find the version of a gem that releases a certain commit
Sometimes I ran across a GitHub merge request of a gem where it was not completely obvious in which version the change was released. This might be the case for a bugfix PR that you want to add to your project.
Git can help you to find the next git tag that was set in the branch. This usually has the name of the version in it (as the rake release task automatically creates a git tag during release).
git name-rev --tags <commit ref>
Note
The more commonly used
git describecommand will return the last tag before a c...
Ruby 1.9 or Ruby 2.0 do not allow using shortcut blocks for private methods
Consider this class:
class Foo
private
def test
puts "Hello"
end
end
While you can say create a block to call that method (using ampersand and colon) on Ruby 1.8, ...
1.8.7 > Foo.new.tap(&:test)
Hello
=> #<Foo:0x1e253c8>
... you cannot do that on Ruby 1.9 or 2.0:
1.9.3 > Foo.new.tap(&:test)
NoMethodError: private method `test' called for #<Foo:0x00000001e8c258>
^
2.0.0 > Foo.new.tap(&:test)
NoMethodError: private method `test' called for #<Foo:0x000000027bc738...
How to fix gsub on SafeBuffer objects
If you have an html_safe string, you won't be able to call gsub with a block and match reference variables like $1. They will be nil inside the block where you define replacements (as you already know).
This issue applies to both Rails 2 (with rails_xss) as well as Rails 3 applications.
Here is a fix to SafeBuffer#gsub. Note that it will only fix the $1 behavior, not give you a safe string in the end (see below).
Example
def test(input)...
How to migrate CoffeeScript files from Sprockets to Webpack(er)
If you migrate a Rails application from Sprockets to Webpack(er), you can either transpile your CoffeeScript files to JavaScript or integrate a CoffeeScript compiler to your new process. This checklist can be used to achieve the latter.
- If you need to continue exposing your CoffeeScript classes to the global namespace, define them on
windowdirectly:
-class @User
+class window.User
- Replace Sprocket's
requirestatement with Webpacker's...