#  status       :integer          default("draft")
#
class Post < ApplicationRecord
 enum status: [:draft, :published, :archived]

 validates :name, presence: true

 has_one_attached :cover_photo
 has_one_attached :audio
 has_many_attached :attachments

 belongs_to :user, optional: true
 has_many :comments, as: :commentable
 has_many :reviews, as: :reviewable

 acts_as_taggable_on :tags
end
```

```ruby [app/avo/resources/post.rb]
class Avo::Resources::Post < Avo::BaseResource
  self.includes = []
  # self.search = {
  #   query: -> { query.ransack(id_eq: q, m: "or").result(distinct: false) }
  # }

  def fields
    field :id, as: :id
    field :name, as: :text
    field :body, as: :textarea
    field :is_featured, as: :boolean
    field :published_at, as: :datetime
    field :user_id, as: :number
    field :status, as: :select, enum: ::Post.statuses
    field :cover_photo, as: :file
    field :audio, as: :file
    field :attachments, as: :files
    field :user, as: :belongs_to
    field :comments, as: :has_many
    field :reviews, as: :has_many
    field :tags, as: :tags
  end
end
```

:::

It's also possible to specify the resource model class. For example, if we want to create a new resource named `MiniPost` resource using the `Post` model we can do that using the following command:

```bash
bin/rails generate avo:resource mini-post --model-class post
```

That command will create a new resource with the same attributes as the post resource above with specifying the `model_class`:

```ruby
class Avo::Resources::MiniPost < Avo::BaseResource
  self.model_class = "Post"
end
```

:::info
You can see the result in the admin panel using this URL `/avo`. The `Post` resource will be visible on the left sidebar.
:::

## Generating resources for all models

To generate Avo resources for all models in your application, run:

```bash
rails generate avo:all_resources
```

### What it does

1. Scans your `app/models` directory for all model files
2. Excludes `ApplicationRecord` from the generation process
3. For each model found, it:
   - Generates a corresponding Avo resource using the `avo:resource` generator
   - Handles errors gracefully, printing error messages if generation fails for any model

This is particularly useful when:
- Setting up Avo in an existing Rails application
- Ensuring all your models have corresponding Avo resources

## Fields

`Resource` files tell Avo what records should be displayed in the UI, but not what kinds of data they hold. You do that using the `fields` method.

Read more about the fields here.

```ruby{5-17}
class Avo::Resources::Post < Avo::BaseResource
  self.title = :id
  self.includes = []

  def fields
    field :id, as: :id
    field :name, as: :text, required: true
    field :body, as: :trix, placeholder: "Add the post body here", always_show: false
    field :cover_photo, as: :file, is_image: true, link_to_record: true
    field :is_featured, as: :boolean

    field :is_published, as: :boolean do
      record.published_at.present?
    end

    field :user, as: :belongs_to, placeholder: "—"
  end
end
```

## Routing

Avo will automatically generate routes based on the resource name when generating a resource.

```
Avo::Resources::Post         -> /avo/resources/posts
Avo::Resources::PhotoComment -> /avo/resources/photo_comments
```

If you change the resource name, you should change the generated controller name too.

## Use multiple resources for the same model

Usually, an Avo Resource maps to one Rails model. So there will be a one-to-one relationship between them. But there will be scenarios where you'd like to create another resource for the same model.

Let's take as an example the `User` model. You'll have an `User` resource associated with it.

```ruby