Ruby on Rails (13)
- Rails World 2024 Conference Recap
- Solid Cache for Rails and PostgreSQL
- Trying out Solid Queue and Mission Control with PostgreSQL
- Madison+ Ruby 2024 Conference Recap
- ๐ Readers get their copies of "High Performance PostgreSQL for Rails"
- SaaS on Rails on PostgreSQL โ POSETTE 2024
- Mastering PostgreSQL for Rails: An Interview with Andy Atkinson
- Top Five PostgreSQL Surprises from Rails Devs
- RailsConf 2024 Conference โ The Long Goodbye
- ๐๏ธ Hacking Postgres ๐ Podcast โ Season 2, Ep. 1 Andrew Atkinson
- Sin City Ruby 2024
- Rails + Postgres Postgres.FM 086 โ Extended blog post edition! ๐๏ธ
- Maintainable Podcast โ MaintainableโฆDatabases? ๐๏ธ
- Remote Ruby โ Unleashing the Power of Postgres with Andrew Atkinson ๐๏ธ
- The Rails Changelog โ #014: PostgreSQL for Rails Developers with Andrew Atkinson ๐๏ธ
- Teach Kelvin Your Thing (TKYT) โ High Performance PostgreSQL for Rails ๐ฅ๏ธ
- SaaS for Developers with Gwen Shapira — Postgres, Performance and Rails with Andrew Atkinson ๐๏ธ
- Podcast: Code and the Coding Coders who Code it! Episode 27 Andrew Atkinson ๐๏ธ
- PGSQL Phriday #001 โ Query Stats, Log Tags, and N+1s
- PgHero 3 Released
- RailsConf 2022 Conference
- PostgreSQL pgbench Workload Simulation
App Code Tips
Native pg
gem dependencies
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
Log SQL queries to console
ActiveRecord::Base.logger = Logger.new(STDOUT)
List object methods
User.methods - ActiveRecord::Base.methods
Get a full backtrace
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
Warnings
Boot app with $VERBOSE = true
in config/application.rb
or somewhere that executes
Vendor everything
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
Bundler 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
.
Prefer simple dependency specifications
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.
Caller code source location
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.
Nested Attributes
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.
Unused
- Identify unused code https://github.com/unused-code/unused
$ unused
Rails Best Practices
- https://github.com/flyerhzm/rails-bestpractices.com
$ rails_best_practices .
Test Code Tips
Rspec Tips
- Run specific spec: use line number on end like
rspec spec/foo_spec.rb:123
to run line 123
Compare times at course granularity
expect(thing.time).to be_within(1.second).of Time.now
Tail test log file when running test
In a separate terminal window:
tail -f log/test.log
Sidekiq Content
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.
External web requests
We use webmock for 3rd party APIs to capture authentic HTTP stubbed responses.
Rails and Database Tips
Statement timeout
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.
Checkout 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
Connection Pool Stats
ActiveRecord::Base.connection_pool.stat
# => {:size=>32, :connections=>0, :busy=>0, :dead=>0, :idle=>0, :waiting=>0, :checkout_timeout=>4.0}
Remove unused indexes
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.
Use Strong Migrations
Follow the tips in strong_migrations. Create your own custom checks. Explain your rationale when using safety_assured
.