
How to Run a Ruby on Rails Project Audit
Victor Motogna
Head of Web Development
Reading time: 6 min
Published: Nov 8, 2022
Key takeaways
- A Ruby on Rails project audit turns hard-to-define code quality into a clear, measurable, repeatable process.
- Wolfpack Digital runs a Basic Code Compliance Check every 6 to 12 months, producing a pass rate and prioritized to-do list.
- Vulnerability checks come first: scan with Brakeman and bundler-audit, set production logs to info, and hide sensitive data.
- Enforce at least 75% test coverage for controllers, models, and services, using RSpec and SimpleCov.
- Round out the audit with RuboCop code style, Git and CI rules, and N+1 query checks via the Bullet gem.
At Wolfpack Digital, delivering high-quality software is our mission. Quality is easy to spot in UI/UX design or a smooth client experience. But high-quality code is much harder to define, especially for non-technical people.
That does not stop us. Good software makes future development easier. It helps you squash bugs, or avoid them entirely. Cutting corners, on the other hand, quietly builds up. The next change then becomes far harder than it should be.
This is why we built a Ruby on Rails project audit. Here is how it works, and how you can build your own.
Defining the audit process
Our projects vary a lot. Some run under a year; others have run for six years and counting. Teams range from a single backend developer to five web developers. Each project has its own needs.
So we needed a process that could:
- Frame the common needs of as many active projects as possible;
- Fit each project's budget and timeline, since some allow less time for review and refactoring;
- Cover code style, security, testing, and system design;
- Be easy to use, adapt, and monitor, so it becomes a habit with a clear, measurable output.
We did not start from scratch. We already had strong guidelines, built on a Rails template. We keep it current with the latest Ruby and Rails versions. We also had rules for testing, documentation, and setup. To improve, though, we needed to measure our work more clearly.
The result: a Basic Code Compliance Check
The final framework has two parts:
- A detailed guideline with tools, code, and rules for architecture, naming, RuboCop config, git, and testing;
- A shorter process that fits in under two hours, run every 6 to 12 months. This is the focus of this article.
We call it the Basic Code Compliance Check. It is a set of common-sense rules for every project. We run it in a short meeting once or twice a year, per project.
The meeting includes a technical assist and one main developer. (Every project already has a technical assist, who supports complex decisions, code reviews, and pair programming.) The output is an email with the exact pass rate, plus a to-do list ordered by priority. Below, we walk through each rule and the reasoning behind it.
Vulnerability checks
This is the highest-priority rule by far. It sounds obvious, but it rarely gets enough attention. The goal is simple: make sure your gems have no known vulnerabilities, and your code has no issues like SQL injection.
The review runs four checks:
-
Static analysis with Brakeman. Add the gem to the development group, then run
bundle exec brakeman -q. -
Patch-level checks for each gem with bundler-audit. Run
bundle exec bundle-audit check --update -v. -
Production log level. This should be
info, notdebug. - Sensitive data check. Filter access tokens and other secrets from log files and VCR cassettes.
To pass, both Brakeman and bundler-audit must be in the project and run without warnings. Ideally, they also run in a CI job (more on that below) and stay up to date.
The action points are clear: add these gems, clear all warnings, hide sensitive data in exports, and set the production log level correctly.
Testing and coverage
We already had testing guidelines. We enforce unit tests on all backend projects and recommend RSpec. But we had no review process for coverage. So the check here is test coverage.
We aim for 100% coverage, but we know that is rarely realistic. Coverage also varies with a project's size and timeline. So we enforce two firm rules:
- Every project must have a test suite for controllers (requests), models, and services;
- Each of these must have at least 75% coverage.
Company-wide, we recommend RSpec for the suite and SimpleCov for coverage. If a project lacks SimpleCov, here is a quick setup:
- Add the SimpleCov gem to the Gemfile, ideally in the development and test groups;
- Update
spec/rails_helper.rbwith the snippet below.

- Run the tests with the environment variable set:
RUN_SIMPLE_COV=true rspec spec; - A
/coverage/index.htmlfile appears locally with the results; - For a clearer report, add
add_group('services', 'app/services')below the SimpleCov filters.
The action point is simple: write more tests. But raising a poorly tested project to 75% is hard, especially a large one. So take it step by step.
Write tests for every new feature. Write tests when you refactor. Otherwise, start with simpler controllers and models. Set a priority order: first the critical, most-used features, then validations, then everything else. Focus first on complex or frequently changed code, since that saves you the most pain later.
Code style with RuboCop
This is the most opinionated check, which makes it the trickiest. You need a base set of rules that fits most projects, while still letting people adapt. Your team may do this differently, and that is fine. The key is to agree on rules everyone follows.
There are four steps:
- Set up RuboCop with a config file for custom rules. Our template has an example. On bigger projects, keep the rule and mark exceptions rather than removing it.
- Set up Overcommit to run RuboCop before each commit, so unstyled code cannot be committed.
- Review the Rails credentials setup. Follow the official credentials guide, or use environment variables. The goal is that no secret can be read without the master key or server access.
- Check for deprecation comments and old, forgotten to-dos.
Most of these can be done in the meeting, like setting up RuboCop and Overcommit. The rest are small follow-up tasks.
Git and CI
This check depends on your tools. Most of our projects use GitHub for git and CircleCI for CI/CD. Still, the general process and checks apply to any tool.
Our main review points are:
- Branch and commit rules. Agree on a naming convention everyone follows, whether you use git flow or trunk-based development. We often prepend the Jira ticket ID to the branch name and PR title.
- CI setup. The pipeline should run at least three steps: RuboCop, the test suite, and the vulnerability checks above. Larger projects should also automate deployment.
- Repository settings. Block merges until a PR is open, has at least one approval, and passes CI.
The repo rules take only a few minutes to set. As long as your organization has a CI account, you can start the pipeline setup too. We keep a CircleCI config template for this.
Database optimizations and N+1 queries
This chapter is really about N+1 queries. Many database optimizations exist, but most are situational and take time to justify, especially on small projects. So the one check we run everywhere is this: no flow should have an N+1 query issue.
Here are the steps:
- Install Bullet (or another N+1 checker) and enable it in the test environment.

- Run all your tests, then fix the errors Bullet reports.
For more on this, see our guide on how to speed up your Rails backend server.
Conclusion: build your own Rails audit
We hope this article helps you define an audit for your own team. Treat it as a blueprint. We use it as a twice-yearly review that exports a completion percentage, so we can track quality over time. You might run yours more often, or change and add checks.
Want a partner for your next Rails project? See why we build with Ruby on Rails, or explore our web development services. Curious about Rails on mobile? Read our take on developing mobile apps with Ruby, then get in touch.



