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...
A non-weird replacement for grouped_collection_select
Rails comes with grouped_collection_select that appears to be useful, but isn't.
As an alternative, consider the flat_grouped_collection_select found below. It takes a third argument that extracts the group from each element in the collection:
= form.flat_grouped_collection_select :user_id, users, :department, :id, :full_name
Here is the monkey-patch:
class ActionView::Helpers::FormBuilder
def flat_grouped_collection_selec...
When sessions, cookies and Clearance tokens expire and how to change it
Expiration of Rails sessions
By default Rails sessions expire when the user closes her browser window.
To change this edit your config/initializers/session_store.rb like this:
ActionController::Base.session = {
:key => '...',
:secret => '...'
:expire_after => 10.years
}
In older Railses the initializer is not available. Set the option in the environment.rb instead:
config.action_controller.session = {
:key => '...',
:secret => '...'
...
Spec "content_for" calls in helpers
This only applies to RSpec below version 1.3.2. The issue has been fixed in RSpec 1.3.2, and most likely RSpec 2 and later versions.
When you have a helper that calls content_for and want to check its behavior you should probably write a feature instead. If you still want to do it, mind the following.
Consider this helper:
module LayoutHelper
def title(string)
content_for :title, string
string
end
end
Somewhere in the layout we'd then say something like this: `<%= yield :title %...</p>
A saner alternative to SimpleForm's :grouped_select input type
SimpleForm is a great approach to simplifying your forms, and it comes with lots of well-defined input types. However, the :grouped_select type seems to be overly complicated for most use cases.
Example
Consider this example, from the documentation:
form.input :country_id, collection: @continents,
as: :grouped_select, group_method: :countries
While that looks easy enough at a first glance, look closer. The example passes @continents for a country_id.\
SimpleForm actua...
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...
Force absolute URLs for parts of a view or controller
You know that you can force absolute URLs throughout a response. Now you want to modify URLs similarly, but only in parts of a view (or controller) logic. Here is how.
Note: this has only been tested on a Rails 2 application. It should work similarly for Rails 3.
Put this into your ApplicationController:
def rewrite_options(*args)
options = super
options.merge!(:only_path => false) if @with_full_urls
options
end...
How to set up SMTP email delivery with a Gmail account
If you want to make your Rails application be capable of sending SMTP emails, check out the action mailer configuration section in the Ruby on Rails guide.
TL;DR you will end up having an smtp_settings hash that looks something like this:
smtp_settings = {
address: ...,
domain: ...,
port: ...,
user_name: ...,
password: ...,
authentication: ...,
tls: ...,
enable_starttls_auto: ...,
}
This hash can be set as the `delivery_me...
How to disable cookies in cucumber tests
Unfortunately, Capybara does not offer a switch to disable cookies in your test browser. However, you can work around that by using a tiny Rack middleware -- it works for both Selenium and non-Selenium tests.
Wouldn't it be nice to say something like this?
Given cookies are disabled
When I try to sign in
Then I should see "Can't sign you in. Please enable cookies."
You can! Put the code below into some place like lib/rack/cookie_stripper.rb.
module Rack
class CookieStripper
ENABLED = false
...
Fix warning: No secret option provided to Rack::Session::Cookie
You will get this when you are using the latest version of Rails with a recent version of Rack:
SECURITY WARNING: No secret option provided to Rack::Session::Cookie.
This poses a security threat. It is strongly recommended that you
provide a secret to prevent exploits that may be possible from crafted
cookies. This will not be supported in future versions of Rack, and
future versions will even invalidate your existing user cookies.
The warning is caused by Rails calling Rack incorrectly. [It is unclear](https://github.c...
Threads and processes in a Capybara/Selenium session
TLDR: This card explains which threads and processes interact with each other when you run a Selenium test with Capybara. This will help you understand "impossible" behavior of your tests.
When you run a Rack::Test (non-Javascript) test with Capybara, there is a single process in play. It runs both your test script and the server responding to the user interactions scripted by your test.
A Selenium (Javascript) test has a lot more moving parts:
- One process runs your test script. This is the process you...
Always show all form errors during development
You've been there: A form cannot be submitted, but you don't see a validation error because the field at fault has no corresponding input field on the form. Because this is usually a bug, you insert debug information listing all errors into the form view. And once the bug is fixed, you forget to take out that debug information.
There is a better way. By copying one of the attached initializers into config/initializers, your forms will always render a small box listing all form errors in the bottom right corner of the screen. This box is n...
Carrierwave: Using a nested directory structure for file system performance
When storing files for lots of records in the server's file system, Carrierwave's default store_dir approach may cause issues, because some directories will hold too many entries.
The default storage directory from the Carrierwave templates looks like so:
class ExampleUploader < CarrierWave::Uploader::Base
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
end
If you store files for 500k records, that store_dir's parent directory will have 500k sub-directories which will cause some...
Safely chain scopes with hash conditions
There is a nasty bug in all version of Rails 2 and some versions of Rails 3.x where two chained scopes with hash conditions on the same attribute would overwrite each other.
This is a horrible security issue if you are using scopes to limit what a user may see or change.
Workaround
If you are using an affected Rails version and cannot switch to a fixed version, you can use this manual workaround....
Gem development: When your specs don't see dependencies from your Gemfile
When you develop a gem and you have a Gemfile in your project directory, you might be surprised that your gem dependencies aren't already required in your specs. Here is some info that should help you out:
- Bundler actually doesn't automatically require anything. You need to call
Bundler.require(:default, :your_custom_group1, ...)for that. The reason why you never had to write this line is that Rails does this for you when it boots the environment. - That also means that if you have an embedded Rails app in your
specfolder (like [h...
How to remove properties of ActiveRecord scopes
When dealing with AR scopes, you can remove conditions, order, etc by using the unscope method.
It is available on Rails 4+.
Examples
Consider an exemplary User class as follows. For the examples below, we will use a scope that applies all its constraints.
class User < ActiveRecord::Base
scope :active, -> { where(locked: false) }
scope :admins, -> { where(role: 'admin') }
scope :ordered, -> { order(:name) }
end
users = User.active.admins.ordered
^
SELECT "users".* FROM "users" WHERE "use...
PostgreSQL: How to show table sizes
When you have a large PG database, you may want to find out which tables are consuming the most disk space.
You can easily check this using the following SQL statement from the PostgreSQL wiki.
SELECT nspname || '.' || relname AS "relation",
pg_size_pretty(pg_total_relation_size(C.oid)) AS "total_size"
FROM pg_class C
LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
WHERE nspname NOT IN ('pg_catalog', 'information_schema')
AND C.relkind <> 'i'
AND nspname !~ '^pg_toast'
ORDER BY pg_tot...
Minidusen: Low-tech record filtering with LIKE queries
We have a new gem Minidusen which extracts Dusen's query parsing and LIKE query functionality.
Minidusen can no longer index text in MySQL FULLTEXT columns, which was hardly used and didn't always help performance due to the cost of reindexing.
Minidusen is currently compatible with MySQL, PostgreSQL, Rails 3.2, Rails 4.2 and Rails 5.0.
Basic Usage
Our example will be a simple address book:
class Contact < ActiveRecord::Base
validates_presence_of :name, :street, :city, :e...
Retrieving the class an ActiveRecord scope is based on
Edge Rider gives your relations a method #origin_class that returns the class the relation is based on.
This is useful e.g. to perform unscoped record look-up.
Post.recent.origin_class
# => Post
Note that #origin_class it roughly equivalent to the blockless form of #unscoped from Rails 3.2+, but it works consistently across all Rails versions. #unscoped does not exist for Rails 2 and is broken in Rails 3.0.
Using RSpec stubs and mocks in Cucumber
By default, Cucumber uses mocha. This note shows to use RSpec stubs and mocks instead.
Rspec 1 / Rails 2
Put the following into your env.rb:
require 'spec/stubs/cucumber'
Rspec 2 / Rails 3
Put the following into your env.rb:
require 'cucumber/rspec/doubles'
Note: Since Cucumber 4 it is important to require these lines in the env.rb and not any other file in support/* to register the hooks after any other After hook in support/*. Otherwise your doubles are removed, while other After steps requi...
Re-enable submit buttons disabled by the :disable_with option
Submit buttons in Rails come with a useful option :disable_with which will disable the button when clicked and change its label to something like "Please wait...".
An annoying side effect of that feature is that when you use the back button to return to the form, the submit button will be greyed out and disabled.
A solution is to re-enable the submit button before leaving the page. This works in Rails 3:
$(window).unload(function() {
$.rails.enableFormElements($($.rails.formSubmitSelector));
});
Bulk-change multiple table rows in a migration
Using rename_column, remove_column, etc. more than once in a migration makes that migration run slower than it should. Use change_table instead.
Consider this migration:
add_column :users, :name, :string
remove_column :users, :first_name
remove_column :users, :last_name
rename_column :users, :cool, :awesome
Migrating in this case means that all those commands are processed step by step, causing 4 SQL statements to change the table. In turn, your database needs to modify the table structure 4 times. When working on hu...
Upgrading Ruby from 1.8.7 to 2.3.5
Suggested Workflow
Set the ruby version in .ruby-version to 2.3.5, then perform these steps one by one, fixing errors as they occur:
- Update gems as listed below, and bundle
- Boot a Rails console - see below for a list of changes you will probably need
- Run Specs with
--backtraceoption - Run Cucumber features (with Geordi's
--debugoption) - When all tests are green, look through your Gemfile and remove as many version constraints as possible.
- Boot the application in different environements to spot further issues, e...
Fixing wall of net/protocol warnings
After upgrading to Rails 6.1.7.2 one of our apps printed a wall of warnings while booting:
/var/www/app/shared/bundle/ruby/2.6.0/gems/net-protocol-0.2.1/lib/net/protocol.rb:68: warning: already initialized constant Net::ProtocRetryError
/home/deploy-app/.rbenv/versions/2.6.10/lib/ruby/2.6.0/net/protocol.rb:66: warning: previous definition of ProtocRetryError was here
/var/www/app/shared/bundle/ruby/2.6.0/gems/net-protocol-0.2.1/lib/net/protocol.rb:214: warning: already initialized constant Net::BufferedIO::BUFSIZE
/home/deploy-app/.rben...