layout | permalink | title |
---|---|---|
page |
/rails-tips |
Rails Tips |
Blog Posts and tips for Ruby on Rails web applications.
{% include tag-pages-loop.html tagName='Ruby on Rails' %}
Run which pg_config
.
Copy the path as the value for --with-pg-config
for bundler. Reference.
bundle config build.pg --with-pg-config=/Applications/Postgres.app/Contents/Versions/latest/bin/pg_config
ActiveRecord::Base.logger = Logger.new(STDOUT)
User.methods - ActiveRecord::Base.methods
https://stackoverflow.com/a/376521/126688
def do_division_by_zero; 5 / 0; end
begin
do_division_by_zero
rescue => exception
puts exception.backtrace
raise # always reraise
end
Boot app with $VERBOSE = true
in config/application.rb
or somewhere that executes
When vendoring/caching all gems, while developing on macOS but deploying with Alpine Linux, we need to download and cache gems for all platforms. This grabs the Linux version of the Nokogiri gem.
bundle package --all-platforms
If developing on Mac OS, deploying on Linux, and vendoring gems, the Darwin pre-built gem will be installed. Add the Linux platform:
bundle lock --add-platform x86_64-linux
And then bundle package --all-platforms
and confirm the Linux version has been added to vendor/cache
.
Sometimes there is a minimum version required that has a security fix, a team member recently introduced this:
gem 'addressable', '~> 2.8', '>= 2.8.0'
This makes bundle update addressable
easy in the future, grabbing any new patch version of the 2.8
minor version, while still calling out that 2.8.0
should be the minimum patch version that has a security fix.
In general I prefer to avoid specifying versions entirely in the Gemfile
and rely on the versions in Gemfile.lock
, which has specific versions for direct and indirect dependencies.
This is more of a Ruby tip but you can get a method reference and use source location. For example with an instance of foo:
Foo.new
the method
method can be called with a method name like bar
, e.g. Foo.new.method(:bar).source_location
and calling source_location will show the line number of the caller.
If there is the option to control the front-end HTTP request payload, take advantage of built-in nested attributes support to create objects via an association.
Because nested models can be created or updated this way, Active Record lifecycle events like before_save
can be triggered to create a loosely coupled series of actions.
- Identify unused code https://github.com/unused-code/unused
$ unused
- https://github.com/flyerhzm/rails-bestpractices.com
$ rails_best_practices .
- Run specific spec: use line number on end like
rspec spec/foo_spec.rb:123
to run line 123
expect(thing.time).to be_within(1.second).of Time.now
In a separate terminal window:
tail -f log/test.log
Sidekiq is a popular background processing framework.
Review my Sidekiq page: Sidekiq.
https://github.com/mperham/sidekiq/wiki/Testing We use the inline!
method to test jobs synchronously.
We use webmock for 3rd party APIs to capture authentic HTTP stubbed responses.
Set a statement_timeout
in config/database.yml to set an upper bound on how long a query can run. We use 5 seconds for our app servers. Hashrocket: Rails/PG Statement Timeout
For queries that are ok to run longer, or migrations, a higher value is appropriate. We use Strong Migrations which raises the statement timeout.
Set a checkout_timeout
to set how long to wait to check out a connection from the connection pool. The default is 5 seconds but we set it to 4 seconds. Rails Connection Pool Docs
ActiveRecord::Base.connection_pool.stat
# => {:size=>32, :connections=>0, :busy=>0, :dead=>0, :idle=>0, :waiting=>0, :checkout_timeout=>4.0}
In a Rails migration, check for the existence of the index like: index_exists?(:table_name, :column_name)
before writing it. Indexes may have different generated names in different environments.
Follow the tips in strong_migrations. Create your own custom checks. Explain your rationale when using safety_assured
.