---
url: /reference/generators/scaffold.md
---
# Scaffold

```sh
bin/rails g trek:scaffold Book title intro:text
bin/rails db:migrate
```

Akin to Rails', Trek's scaffold generates, with a single command:

* the `Book` model and migration (calling the Rails `model` generator behind the scenes)
* the `Admin::BooksController`, inheriting from [`Trek::ResourceController`](/reference/controllers)
* the Slim views: `index`, `show`, `new`, `edit` and the `_form` partial
* the `Admin::BookPolicy`, inheriting from [`Trek::ResourcePolicy`](/reference/policies)
* the `resources :books, except: :show` route in the `admin` namespace, with a commented-out `reorder` route (the `show` view is generated all the same, for when you add the route)
* the locale files for the model and its admin panel, in every configured locale
* the entry in the admin dashboard menu

## Field types

Standard Rails attribute types are supported (`string`, `text`, `integer`, `float`, `decimal`, `boolean`, `date`, `datetime`, `references`…). Each field gets the form helper Rails' own scaffold picks: `text_field` for a `string`, `textarea` for a `text`, `checkbox` for a `boolean`, a `text_field` of the id for a `references`, and so on. Swap them in the generated `_form` for Trek's [form helpers](/reference/forms) where they fit: `content_editor` for rich text, `switch_box`, a `collection_select`…

## Namespaced models

```sh
bin/rails g trek:scaffold Shop::Product name price:decimal
```

The controller and policy are nested accordingly (`Admin::Shop::ProductsController`, `Admin::Shop::ProductPolicy`), the routes go under `namespace :shop`, and everything else follows the namespace.

The generated code references the model as `::Shop::Product`, top-level qualified, and the dashboard menu entry is `::Shop::Product` too. This is deliberate: once `Admin::Shop` exists, a bare `Shop` written anywhere under `module Admin` resolves to that namespace instead of the `Shop` model. Existing admin code that references such a model — an `Admin::ShopsController#model` returning `Shop`, or a `Shop` entry in `Admin::Dashboard::MODELS_IN_MENU` — must be updated to `::Shop` once a scaffold introduces a namespace with the same name (the menu would otherwise silently list the module).

Also note that `bin/rails g model Shop::Product` (which the scaffold runs) writes `app/models/shop.rb` as a `module Shop` namespace file; if a `Shop` model already lives there, the generator warns and Rails asks before overwriting it — move the model or answer `n`.

## The model

The admin shows a record by its `to_s`, in lists and titles: the scaffold returns the first `string` attribute given (here `title`), or Ruby's default (`#<Book:0x…>`) when it's blank. Without a `string` attribute, `to_s` is left to write.

The generated model ships with commented-out hooks for Trek's most useful [concerns](/reference/), ready to be enabled when needed, each under a `TODO`:

```ruby
class Book < ApplicationRecord
  # TODO: uncomment to format some attributes, or remove if not needed
  # include Trek::Formattable
  # format_attributes Trek::TypographyFormatter, :title

  # TODO: uncomment to translate some attributes, or remove if not needed
  # include Trek::Translatable
  # translate_attributes :title

  # TODO: choose how the model should be ordered in the admin panel
  # scope :ordered, -> { order(:id) }

  strip_attributes

  # TODO: uncomment to attach files to the model, or remove if not needed
  # include RecordImageUploader::Attachment(:image)

  # The title in the admin panel
  def to_s
    title.presence || super
  end

  # TODO: choose which attribute to use as image in the admin panel, or remove if not needed
  # def image
  #   image_url || super
  # end
end
```
