Ruby on Rails » Keeping Up With The Joneses: Keeping Rails and its extensions up to date » Pathfinder Development
There are many wonderful things about Rails and the Rails ecosystem. A clean, well-lighted path for keeping all your extensions up to date is not one of them.
Rails: Default generators
This is a visualization of the files that will be generated by some useful rails generators. Invoke a generator from command line via rails generate GENERATOR [args] [options]. List all generators (including rails generators) with rails g -h.
| generator | model | migration | controller | entry in routes.rb
|
views | tests |
|---|---|---|---|---|---|---|
| scaffold | ✔ | ✔ | ✔ | ✔ | ✔ | ✔ |
| resource | ✔ | ✔ | ✔ ... |
How to fix "undefined method `name' for Array" error when running bundled commands on Ruby 1.8.7 + Rails 2.3
On recent/fresh installations of Ruby 1.8.7 you may encounter this error why calling any bundled binary (or just bundle exec):
/home/arne/.rvm/gems/ruby-1.8.7-p374@global/gems/rubygems-bundler-1.4.2/lib/rubygems-bundler/noexec.rb:75:in `setup': undefined method `name' for #<Array:0x7fe04783ef30> (NoMethodError)
from /home/arne/.rvm/rubies/ruby-1.8.7-p374/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:29:in `map'
...
Apparently, this is due to bundler (or maybe the rubygems-bundler that RVM supplies by default) no lon...
Rails 3 routing: Be careful with matching routes *including their format*
Today, this line made me trouble. Can you spot the mistake?
match 'sitemap.xml' => 'feeds#sitemap', :constraints => { :format => 'xml' }, :as => 'sitemap'
The mistake is to match sitemap.xml. Rails will by default strip any dot-anything, remember it as desired format and forward the rest of the request to the routing engine. Since we're making .xml part of the match, it is not available for format determination and Rails will set the format to html.
Unfortunately, the constraint won't complain in this case and Rails even ren...
Installing Rails on a fresh system
- Install Ruby from the Ubuntu repository:
sudo apt-get install ruby ruby-dev\
rubyis the meta package. If you want to explicitly install 1.8 or 1.9, installruby1.8orruby1.9instead (the same applies forruby-dev). - Do not install RubyGems from the repository but install the version from the webpage instead.
- Get Bundler:
sudo gem install bundler
Rails and other gems for a project should now be installed via bundle install from the...
Rails: How to list all validations on a model or an attribute
If a model inherits from others or uses many concerns / traits, it might be hard to see in the code which validators it has.
But fortunately there's a method for that:
irb(main):002:0> pp UserGroup.validators
[#<ActiveModel::Validations::InclusionValidator:0x00007f55efff97a8
@attributes=[:deleted],
@delimiter=[true, false],
@options={:in=>[true, false], :allow_nil=>false}>,
#<ActiveModel::Validations::InclusionValidator:0x00007f55f15748d0
@attributes=[:cancelled],
@delimiter=[true, false],
@options={:in=>[true, false], ...
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 ...
3 ways to run Spring (the Rails app preloader) and how to disable it
spring ...
The most obvious way to use spring is to call it explicitly:
spring rails console
spring rake db:migrate
Binstubs
Binstubs are wrapper scripts around executables. In Rails they live inside bin/. If you run spring binstub --all, your binstubs will be using Spring.
bin/rails console
bin/rake db:migrate
bundle exec rails ...
Bundle exec is inconsistent when it comes to spring. Some commands will use it, some won't.
bundle exec rails console # starts Spring...
Fix error: rails console No such file to load -- irb/encoding_aliases.rb (LoadError)
I got this error after upgrading Ruby from 2.4.5 to 2.6.4 when I opened the Rails console - rails server still worked.
Running via Spring preloader in process 14679
Loading development environment (Rails 5.2.2.1)
Traceback (most recent call last):
.../lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application.rb:175:in 'fork': No such file to load -- irb/encoding_aliases.rb (LoadError)
.../lib/ruby/gems/2.6.0/gems/spring-2.1.0/lib/spring/application.rb:175:in 'fork': undefined method 'reject!' for nil:NilClass (NoMethodError)
.../li...
ExceptionNotification gem will only show application backtrace starting on Rails 4
Starting with Rails 4.0, when you get an exception reported via the ExceptionNotification gem, you will only see a very short backtrace with all backtrace lines from gems or ruby libraries missing.
This happens, because the ExceptionNotification gem uses Rails' default backtrace cleaner. To get a full backtrace in exception emails, you can remove the comment from this line in config/initializers/backtrace_silencers.rb:
Rails.backtrace_cleaner.remove_silencers!
Note that this will break the "Application Trace" functionality o...
Rails 3.1 gives you free down migrations
In Rails 3.1+, instead of defining a separate up and down method you can define a single method change:
class AddComparisonFieldsToReport < ActiveRecord::Migration
def change
add_column :reports, :compare, :boolean
update "UPDATE reports SET compare = #{quoted_false}"
add_column :reports, :compare_start_date, :date
add_column :reports, :compare_end_date, :date
end
end
Migrating up works as expected:
b rake db:migrate
== AddComparisonFieldsToReport: migrating ====================================
-- ad...
Rails + Sidekiq::Web: Configuration for wildcard session cookies
When you're using Sidekiq::Web to monitor the Sidekiq status AND have your session cookie configured to a wildcard domain like .example.com, you need to take an additional step to keep your cookies valid.
Issue
Sidekiq::Web is mounted into your Rails application and will use the Rails session cookie for protection from CSRF attacs. While it somehow figures out the cookie name, it does NOT respect cookie configuration like a custo...
See which Rails applications are being served by your Passenger
To obtain a list of Passenger processes with their application directories and memory usages, you can say
sudo passenger-memory-stats
This will output a list like this:
----- Passenger processes -----
PID VMSize Private Name
-------------------------------
671 112.9 MB 95.5 MB Rails: /opt/www/project1/current
707 79.4 MB 60.5 MB Rails: /opt/www/project2/current
1094 88.1 MB 69.3 MB Rails: /opt/www/project3/current
1260 81.6 MB 62.6 MB Rails: /opt/www/project4/current
1269 7...
Zeus promises to make rails development faster
I am talking about development speed. When your application starts growing and you start adding gems, it starts to take really long to start up, be it the server, console or just running a single spec.
Zeus is smart, you don’t have to put it in your Gemfile or run it with Bundler, all you need to do is create a JSON config file via
zeus initand then start the serverzeus start.
After that, you’re ready to go, all you need to do is prefix every command with zeus. That means
rails serverbecomeszeus server, `rails console...
How to get the hostname of the current machine in Rails or a Ruby script
Use Socket.gethostname. So for a machine whose hostname is "happycat", it will look like this:
>> Socket.gethostname
=> "happycat"
That should work right away for your Rails application. For plain Ruby, you first need to do:
require 'socket'
If you don't want to use Socket for some reason, you can still just use the hostname command, at least on non-Windows machines. Keep in mind that you need to remove trailing white space from the result of the system call.
>> `hostname`
=> "happycat\n"
>> `hostname`.stri...
Ruby and Rails deprecation warnings and how to fix them
Add deprecation warnings and their solution or link to available solutions.
Global access to Rake DSL methods is deprecated. Please include Rake::DSL into classes and modules which use the Rake DSL methods.
Open your Rakefile and add the following line above YourApp::Application.load_tasks:
YourApp::Application.class_eval do
include Rake::DSL
end
Use of ole/file_system is deprecated. Use ole/storage (the file_system api is recommended and enabled by default)...
Upgrading a Rails 3.2 application to Ruby 2.1 is really easy
Upgrading from Ruby 1.8.7 to 2.1.2 took me an hour for a medium-sized application. It involved hardly any changes except
- removing the occasional monkey patch where I had backported functionality from modern Rubies
- Migrating from
requiretorequire_relativewhere I loaded RSpec factories in Cucumber'senv.rb(the Rails application root is no longer in the load path by default) - replacing the old debugger with
byebug - removing
sytem_timerfrom Gemfile (see [this SO thread](http://stackoverflow.com/questions/7850216/how-to-inst...
Use Sass without Rails
You don't need a Rails application to use Sass. Even when you're working on a static site you can generate your CSS through Sass.
- Install Sass with
sudo gem install haml - Create a folder
sassin the folder, that stores your stylesheets, e.g.mkdir css/sass - In a separate terminal window, run
sass --watch css/sass:css. This will watch your sass files for changes and rewrite stylesheets as required.
This even works on Windows.
Note about your .gitignore
You might want to change our [typical .gitignor...
How to upgrade Cucumber on Rails 3+
-
Run
bundle update cucumber capybara cucumber-railsto update to the newest versions. -
Backup your
features/support/path.rbto be able to add your own paths again after the cucumber installation script in step 4. -
Backup your
features/support/env.rbfile to be able to reintegrate parts like your blueprints setup:ENV["RAILS_ENV"] ||= "cucumber" require File.expand_path(File.dirname(__FILE__) + '/../../config/environment') require 'spec/support/blueprints' -
Run `$ rails generate cucumber:install --capyba...
Rendering 404s for missing images via Rails routes
When you load a dump for development, records may reference images that are not available on your machine.
Requests to those images may end up on your application, e.g. if a catch-all route is defined that leads to a controller doing some heavy lifting. On pages with lots of missing images, this slows down development response times.
You can fix that by defining a Rails route like this:
if Rails.env.development?
scope format: true, constraints: { format: /jpg|png|gif/ } do
get '/*anything', to: proc { [404, {}, ['']] }
...
Caveat when using Rails' new "strict locals" feature
In Rails 7.1 it has become possible to annotate partials with the locals they expect:
# partial _user_name.erb
<%# locals: (user:) %>
<%= user.name %>
# view
<%= render 'user_name' %> <%# this raises an ArgumentError %>
Unfortunately, when some other code in that template raises an ArgumentError (for example an error in the User#name method) you will end up with a confusing stacktrace that looks like you have an error in your render call.
If th...
Rendering a custom 404 page in Rails 2
Simple: Tell the application controller how to handle exceptions, here a RecordNotFound error.
Do this with the following line:
# application_controller.rb
rescue_from ActiveRecord::RecordNotFound, :with => :render_404
This will call the method render_404 whenever a RecordNotFound error occurs (you could pass a lambda instead of a symbol, too).
Now write this method:
def render_404
render 'errors/404', :status => '404'
end
Finally create a 404 document views/errors/errors.html.haml.
%h1 Record...
Custom loggers in Ruby and Rails
File logger
If you need to log to a file you can use Ruby's Logger class:
require 'logger'
log = Logger.new('log/mylog.log')
log.info 'Some information'
log.debug 'Debugging hints'
log.error StandardError.new('Something went wrong')
Logger does a number of things well:
- Message type (info / debug / error) is logged
- Log entries are timestamped
- Writing log output is synchronized between threads
- Logged errors are printed with full backtraces
If you don't like the output format, you can define a custom formatter.
I ha...
Security fixes for Rails 2.3
Last week saw a security issue with rails 2.3 that required a fix. While an official patch was provided, the 2.3 branch is no longer maintained. So we forked it.
(I'm sure there are already 100 other forks doing absolutely the same, but they are not very easily discoverable.)
To use our fork, change the gem "rails"... line in your Gemfile to this:
gem 'rails', :git => 'https://github.com/makandra/rails.git', :branch => '2-3-fixes'
The intent is to make as few changes to the f...