---
title: "Ruby on Rails: Convention Over Configuration"
description: "Test your knowledge of Ruby on Rails: MVC, Active Record and associations, migrations, routing, controllers and callbacks, ERB views, and the conventions that make Rails productive."
author: "Mohammad Abu Mattar"
canonical: https://mkabumattar.com/quizzes/post/ruby-on-rails-fundamentals-quiz
---

# Ruby on Rails: Convention Over Configuration

Rails is productive because it decided things for you. The router derives a controller and action from a verb and a path, the controller infers its template from its own name, and Active Record infers table names, column types and primary keys from the schema. You get a lot for very little typing, and the same trade means debugging Rails often requires knowing which convention is quietly in play.

This quiz targets the places where those conventions have sharp edges: the difference between `save` and `save!` inside a transaction, why editing a migration that already ran is a bad idea, and how `includes` turns 101 queries into 2.

_A request through Rails, end to end_

Several questions here are really about production behaviour rather than syntax, so it is worth seeing where each Rails piece lands when you deploy it. The web and worker processes come from the same image and scale separately, migrations run as a one-off task rather than in an entrypoint, and Puma's thread count multiplied by your replica count has to stay under the database connection limit.

_The same Rails app deployed on AWS_

Read the explanations even on the questions you get right. Most of them name a specific failure mode rather than restating the correct answer, and those failure modes are the reason the distinction exists.

## Questions

### 1. In Rails MVC, where does business logic belong?

- In the model, or in service objects the model layer owns
- In the controller, since that is where the request arrives
- In the view, close to where the result is displayed
- In an initializer, so it loads once at boot

**Hint:** Think about which layer survives when you swap the interface from HTML to a JSON API.

### 2. What does `resources :articles` generate in `config/routes.rb`?

- Seven routes: index, new, create, show, edit, update, destroy
- Four routes, one per HTTP verb
- Two routes: index and show
- Nothing until you also define the controller actions

**Hint:** Count the actions, not the URL patterns.

### 3. What is the difference between `has_many :through` and `has_and_belongs_to_many`?

- `:through` uses a real model for the join, so the relationship can carry its own attributes
- `:through` is faster because it generates fewer queries
- `has_and_belongs_to_many` supports validations on the join, `:through` does not
- They are aliases for the same thing

**Hint:** One gives you a model for the relationship itself.

### 4. What does `Article.includes(:author)` do that `Article.all` does not?

- It loads authors up front, replacing N+1 queries with a fixed small number
- It adds a WHERE clause restricting results to articles that have an author
- It caches the query result across requests
- It validates that the association is present

**Hint:** Count the queries when you then loop over the results and touch the association.

### 5. A migration has been run in production. What is the correct way to change it?

- Write a new migration that makes the additional change
- Edit the existing migration file and redeploy
- Edit the file and manually delete its row from `schema_migrations`
- Edit `db/schema.rb` directly

**Hint:** Think about what `schema_migrations` records, and what other machines have already applied.

### 6. What happens when a `before_action` callback calls `redirect_to`?

- The chain halts and the controller action is never executed
- The action runs first, then the redirect is applied
- Rails raises a DoubleRenderError
- Remaining callbacks run, but the action does not

**Hint:** Think about what a partially-rendered response would even mean.

### 7. What is the difference between `save` and `save!` on an Active Record model?

- `save` returns false on validation failure, `save!` raises an exception
- `save!` skips validations, `save` runs them
- `save!` writes immediately while `save` defers to the end of the request
- `save!` bypasses callbacks

**Hint:** One returns a value you must check, the other interrupts control flow.

### 8. Which of these Active Record calls skips validations and callbacks?

- `update_column`
- `update`
- `save`
- `create`

**Hint:** One of these writes straight to the database.

### 9. What does `strong parameters` protect against?

- Mass assignment of parameters the developer never intended to expose
- SQL injection in `where` clauses
- Cross-site request forgery
- Cross-site scripting in rendered views

**Hint:** Think about a form POST that includes a field your form never rendered.

### 10. In a Rails app, what is the practical difference between `Rails.cache` and a Sidekiq queue backed by the same Redis?

- Cache entries may be evicted; queued jobs must not be, so they need different eviction policies
- They are interchangeable as long as Redis has enough memory
- Sidekiq stores jobs in PostgreSQL, not Redis
- Rails.cache always uses memory and never Redis

**Hint:** One is allowed to lose data, the other is not.

### 11. What does `rails db:migrate` do that `rails db:schema:load` does not?

- It runs each pending migration in sequence, including any data changes inside them
- It is faster because it skips intermediate states
- It preserves existing data while `db:migrate` drops tables
- They are equivalent on an empty database

**Hint:** One replays history, the other stamps a final state.

### 12. Why does `Article.where(published: true).count` differ from `Article.where(published: true).size` in some cases?

- `count` always queries the database, while `size` uses the loaded records if they are already in memory
- `size` is deprecated in favour of `count`
- `count` ignores the where clause
- `size` counts associations while `count` counts records

**Hint:** Think about whether the records have already been loaded into memory.
