Bundler error: Downloading gem revealed dependencies not in the API
Recent Bundler (1.16.1) started complaining about missing dependencies in the Gemfile. This is due to a stricter handling of specifications (see attached link).
The error message looks like this:
Downloading example-gem-1.2.3 revealed dependencies not in the API or the lockfile (other-gem (< 3)).
Either installing with `--full-index` or running `bundle update example-gem` should fix the problem.
However, bundle install --full-index did not any better for me, and bundle update is not always a viable solution.
Easiest solut...
Generating test images on the fly via JavaScript or Ruby
When you need test images, instead of using services like lorempixel or placehold.it you may generate test images yourself.
Here we build a simple SVG image and wrap it into a data: URI. All browsers support SVG, and you can easily adjust it yourself.
Simply set it as an image's src attribute.
JavaScript
Simple solution in modern JavaScript, e.g. for use in the client's browser:
function svgUri(text) {
let svg = `
<svg wid...
RSpec: Expecting multiple calls of the same method
If the argument list is the same every time:
expect(object).to receive(:foo).with('argument').and_return('response 1', 'response 2')
If the argument list differs between invocations:
expect(object).to receive(:foo).with('argument 1').ordered.and_return('response 1')
expect(object).to receive(:foo).with('argument 2').ordered.and_return('response 2')
Running Rails 2 apps with modern MariaDB SQL server
You might have some trouble running a Rails LTS 2 app with MySQL 5.7.
If you don't want to hack Mysql 5.6 into your modern Ubuntu or use the MySQL sandbox, you might want to try MariaDB 10.x.
MariaDB 10.x should work with both old and new Rails applications.
[Switch to MariaDB](https://makandracards.com/makandra/468343-how-...
Understanding SQL compatibility modes in MySQL and MariaDB
MySQL and MariaDB have an SQL mode setting which changes how MySQL behaves.
The SQL mode value is comprised of multiple flags like "STRICT_TRANS_TABLES, NO_ZERO_IN_DATE". Each flag activates or disables a particular behavior.
The default SQL mode varies widly between versions of MySQL and MariaDB. In general, more recent versions of MySQL and MariaDB have stricter settings than older versions, and MySQL has stricter settings than the more liberal MariaDB.
If your app explodes ...
Rails: Overriding view templates under certain conditions only
Rails offers a way to prepend (or append) view paths for the current request. This way, you can make the application use different view templates for just that request.
Example
A use case of this is a different set of view templates that should be used under certain circumstances:
class UsersController < ApplicationController
before_action :prepare_views
def index
# ...
end
private
def prepare_views
if <condition>
prepend_view_path Rails.root.join('app', 'views', 'special')
end
end
...
VNC browser disappears while typing
We often use the Then console step from spreewald in combination with geordi vnc from geordi to debug tests within a real browser. Sometimes when you type in the browser it suddenly disappears. You will only see a grey screen then.
This will always happen if you press the d key. Press the d key again and the browser will appear again.
Nested Spreewald patiently blocks are now patient
In Spreewald 1.10.4+, nested patiently blocks are now patient.
Here is an example:
patiently do
outer_code
patiently do
inner_code
end
end
On spreewald 1.11.2+ the inner block will wait for the full configured wait time (by default 5 seconds). The outer patiently block would now be out of time, but it will always be retried at least a second time. This behavior allows with_scope to be patient, and it must be patient, as explained below.
In versions 1.10.4 - 1.11.1, inner blocks would keep giving the ou...
How to: Solve gem loaded specs mutex
Use bundler > 1.15 to fix Gem::LOADED_SPECS_MUTEX (NameError).
Given the following project:
ruby -v
ruby 1.8.7
bundler -v
Bundler version 1.13.7
gem -v
1.8.30
rails -v
Rails 3.2.22.1
Running specs or features resulted in:
uninitialized constant Gem::LOADED_SPECS_MUTEX (NameError)
The previous settings described in Maximum version of Rubygems and Bundler for Ruby 1.8.7 and Rails 2.3 (even the rails version was rails 3.2 and not 2.3) seems not to work here, so I used (also described in the ca...
How to control Chromedriver using curl
Here is how to use Chromedriver without libraries like selenium-webdriver. This can be useful for debugging.
The following example visits a web page and reads the a headline's text contents.
-
Create a session. You will get a JSON response containing lots of information about your Chrome session, including a
sessionId. Use that to send any future commands to your chromedriver session.$ curl -XPOST http://localhost:9515/session -d '{"desiredCapabilities":{"browserName":"chrome"}}' {"sessionId":"your-session-id-here","sta...
RSpec expects pending tests to fail
When flagging a spec that will be implemented later as pending, include a failing spec body or RSpec 3 will consider the pending test as failing.
The reasoning is: If the spec is flagged as pending but passes, it should not be pending. So these will fail:
it 'does something' do
pending
end
it 'does something else' do
pending
expect(1).to eq(1)
end
The first case may be unexpected, if you just wanted to write down that something should eventually happen that will be implemented later.
Instead, ...
XHR is not JSON
When a Rails controller action should handle both HTML and JSON responses, do not use request.xhr? to decide that. Use respond_to.
I've too often seen code like this:
def show
# ...
if request.xhr?
render json: @user.as_json
else
# renders default HTML view
end
end
This is just plain wrong. Web browsers often fetch JSON via XHR, but they (should) also send the correct Accept HTTP header to tell the server the data they expect to receive.
If you say request.xhr? as a means for "wants JSON" you are ...
Think twice before using application names in your variables and methods
I recently had fun with replacing a custom video plattform ("mycustomtv") in one of our applications. I learned a lot about naming stuff.
youtube_mycustomtv_chooser is a bad name for a directive.
Why?
- if you add, for example, other video systems like vimeo, the name of the method either lies or will get longer.
- if you replace one system, you will have to change the method and all of its occurrences (and you're very lucky if it is only one poorly named thing in your application)
What would be a better solution?
Abstract fro...
Katapult 0.4.0 released
Features
- Generating a project README
- Finally: Support for modelling associations between models in your application model! Example:
# lib/katapult/application_model.rb
model 'Cart' do |cart|
cart.belongs_to 'User'
end
crud 'User' do |user|
user.attr :fullname
end
Decide whether cronjobs should run on one or all servers
Understanding your type of cronjob
Some cronjobs must only run on a single server. E.g. when you run nightly batch operations on the database, it should probably run on a single server. Running it on multiple servers would likely result in deadlocks or corrupt data.
Some cronjobs must always run on all servers. E.g. starting a sidekiq process on reboot.
Configuring whenever
If not configured otherwise, cronjobs defined in whenever's `s...
Cucumber: How to avoid VCR errors for unused requests in pending tests
When you have a pending Cucumber step (or feature) that also uses an existing VCR cassette, your pending test may fail at the very end with an error like this:
There are unused HTTP interactions left in the cassette:
- [get ...] => [200 ...]
- [get ...] => [200 ...] (VCR::Errors::UnusedHTTPInteractionError)
The error happens because your VCR is configured to complain about cassettes that contain extra requests which your test did not use. This is often a good configuration.
If you do not want to change your whole test suite...
Katapult 0.3.0 released
Katapult 0.3.0 brings Rails 5 and Ruby 2.5 support with a new design, plus a ton of smaller features, fixes and improvements.
Features
- Generating a Rails 5.1.4 app on Ruby 2.5.0
- Dropped asset pipeline in favor of Webpacker
- The generated application now has a sleek, simple design based on Bootstrap
- Employing Unpoly
- New application model DSL shortcut
crudfor "create a model and a web UI with crud actions" - The generated application model is now a transformable e...
Ruby: Using all? with empty collection
Enumerable#all? returns true for an empty collection. This totally makes sense but you have to think about it when making assumptions on relations which might be empty.
[].all?(&:will_never_be_called_here) => true
Example with empty collection
class Researcher < ActiveRecord::Base
has_many :papers
end
class Paper
validates :topic, inclusion: { in: ['computer_science', 'mathematics', 'economy'] }
end
Easy goal: Delete all researches who write onl...
Capybara: A step for finding images with filename and extension
This cucumber step is useful for testing an image (looking at the src of the image).
Then(/^I should see the image "([^"]*)"$/) do |filename_with_extension|
expect(page).to have_css("img[src*='#{filename_with_extension}']")
end
Then I should see the image "placeholder.png"
Outline: Read more about how to test a uploaded file here, e.g. file downloads.
How to debug Rails autoloading
ActiveSupport::Dependencies takes care of auto-loading any classes in development. This is usually useful, but when you run into issues with the Rails autoloader, you should take a look at what it's doing.
For me this was useful in an "exciting" case of auto-loading classes inside a thread which caused the application to stop responding.
Rails 4.x
ActiveSupport::Dependencies includes logging support. It is easy to use:
ActiveSupport::Dependencies.logger = Rails.logger
Rails 5+
[Logging support was removed](https://github...
Carrierwave: Deleting files outside of forms
TL;DR Use user.update!(remove_avatar: true) to delete attachments outside of forms. This will have the same behavior as if you were in a form.
As you know, Carrierwave file attachments work by mounting an Uploader class to an attribute of the model. Though the database field holds the file name as string, calling the attribute will always return the uploader, no matter if a file is attached or not. (Side note: use #present? on the uploader to check if the file exists.)
class User < ApplicationRecord
mount :avatar, ...
RSpec: How to check that an ActiveRecord relation contains exactly these elements
To check which elements an ActiveRecord relation contains use the contain_exactly matcher.
describe User do
let!(:admin) { create(:user, role: 'admin') }
let!(:customer) { create(:user, role: 'customer') }
subject(:users) { User.where(role: 'admin') }
# Recommended (The error output is most helpful)
it { expect(users).to contain_exactly(admin) }
# Other options
it { expect(users).to eq([admin]) }
it { expect(users.pluck(:id).to eq([admin.id]) }
end
In case you have an `ActiveRecord::AssociationRelati...
Rails and Postgres: How to test if your index is used as expected
This is a small example on how you can check if your Postgres index can be used by a specific query in you Rails application. For more complex execution plans it might still be a good idea to use the same path of proof.
1. Identify the query your application produces
query = User.order(:last_name, :created_at).to_sql
puts query
# => SELECT "users".* FROM "users" ORDER BY "users"."last_name" ASC, "users"."created_at" ASC
2. Add an index in your migration and migrate
add_index :users, [:last_name, :created_at]...
Heads up: RSpec-Mocks' #stub_const will define intermediate modules that have not been loaded yet
The issue: You are using stub_const to change a constant value for your test.
stub_const "SomeClass::CONST", 'test'
All of a sudden, tests fail with undefined method 'some_method' for #<SomeClass:0x00000000101433a8>.
The reason
When using stub_const before the Class containing the constant has been loaded, a module is automatically created with the name.
Since RSpec does no autoloading, it will create a SomeClass module by itself. This is arguably a good idea.
As a workaround, use stub_const in your Rails specs li...