Ruby on Rails Case Studies & Practical Application 3 — Questions and Answers
Question 1: A Rails app's homepage makes 12 database queries on every load. After profiling, navigation categories are queried every request. Best fix?
- Add a database index on categories.name
- Cache the navigation fragment with Rails.cache or fragment caching (Correct answer)
- Preload categories in ApplicationController with a before_action
- Store categories in a YAML config file
Correct answer: Cache the navigation fragment with Rails.cache or fragment caching
Fragment or low-level caching stores the rendered or queried result, eliminating repeated DB hits for static-ish data.
Question 2: You are deploying a Rails app and must run database migrations without downtime. Which strategy is safest for a high-traffic production app?
- Run migrations during a maintenance window with the site down
- Use additive migrations and deploy code before removing old columns in a follow-up migration (Correct answer)
- Run rake db:migrate in the Procfile so it runs on every dyno boot
- Wrap all migrations in a transaction and run them after deployment
Correct answer: Use additive migrations and deploy code before removing old columns in a follow-up migration
Additive migrations paired with a two-phase deploy avoid locking tables during traffic.
Question 3: Your Rails API returns sensitive user data in JSON responses because serializers are not filtering attributes. Which approach best solves this?
- Rescue all controller actions and strip keys before rendering
- Use a serializer library to explicitly whitelist attributes returned per resource (Correct answer)
- Override as_json in each model to exclude sensitive fields
- Add Rack middleware that parses and filters every JSON response body
Correct answer: Use a serializer library to explicitly whitelist attributes returned per resource
Serializer libraries enforce an explicit allowlist of returned attributes, making accidental data exposure much harder.
Question 4: A legacy Rails 4 app uses attr_accessible for mass-assignment protection. In Rails 5+, this is removed. What replaces it?
- Strong Parameters via require and permit in the controller (Correct answer)
- Declaring protected attributes in the model with attr_protected
- Using before_action to sanitize params manually
- Enabling config.force_ssl to block unauthorized writes
Correct answer: Strong Parameters via require and permit in the controller
Strong Parameters (params.require(:model).permit(:field)) moved mass-assignment protection to the controller layer starting in Rails 4+.
Question 5: A Rails app processes large CSV imports synchronously, causing 30-second HTTP timeouts. What is the correct pattern?
- Increase the server timeout to 120 seconds
- Stream the CSV directly into the database using COPY
- Accept the upload, enqueue a background job to process it, and return a job ID immediately (Correct answer)
- Use a separate Rails process dedicated to CSV imports
Correct answer: Accept the upload, enqueue a background job to process it, and return a job ID immediately
Returning a job ID immediately and processing asynchronously prevents HTTP timeouts and gives users a way to check progress.
Question 6: A team needs to A/B test a new checkout flow without deploying separate code branches. Which approach fits best?
- Deploy both versions and use Nginx to split traffic
- Use a feature flag library like Flipper to enable the new flow for a percentage of users (Correct answer)
- Create two separate controllers and route users randomly
- Use browser cookies to serve cached versions of different HTML
Correct answer: Use a feature flag library like Flipper to enable the new flow for a percentage of users
Feature flag libraries enable runtime control over feature rollout without code deploys, allowing clean A/B experiments.
Question 7: Users report that deleting a Company record leaves orphaned Employee records. How should this be fixed in the model?
- Add a database trigger to delete employees on company delete
- Add dependent: :destroy to the has_many :employees association (Correct answer)
- Manually call employees.delete_all in a before_destroy callback
- Use a scheduled job to find and remove orphaned records
Correct answer: Add dependent: :destroy to the has_many :employees association
dependent: :destroy tells ActiveRecord to destroy all associated Employee records when the parent Company is destroyed.
A Rails app's homepage makes 12 database queries on every load.
After profiling, navigation categories are queried every request.
Best fix?