# Charts

{% hint style="success" %}
This is the official documentation of the `agent_ruby` Ruby agent.
{% endhint %}

A well-known adage says, "a picture is worth a thousand words": charts help people better understand and remember information.

Forest Admin Dashboards and Analytics are meant to answer that need.

![Dashboard example](https://561307319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn23xpsrpC8uJXljJ3an2%2Fuploads%2Fgit-blob-5ae091dcef45c5f92710b5196b358da04ce67887%2Fchart-dashboard-on-live-demo.png?alt=media)

## From your admin panel

Charts can be configured from the interface, without the need to write any code.

This is documented in the [User Guide](https://docs.forestadmin.com/user-guide/dashboards/charts)

## From your agent

Sometimes, chart data are closely tied to your business. Forest Admin allows you to code how the data fueling any given chart is computed.

This is done in 3 steps:

* Implement the chart data retrieval using the Agent API,
* Either:
  * create a new Chart on a Dashboard, and choose "API" as the data source,
  * or create a new Chart in the "Analytics" tab of a Collection,
* Enter the URL of the Chart you just implemented (`/forest/_charts/<chartName>` or `/forest/_charts/<collectionName>/<chartName>`).

![](https://561307319-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fn23xpsrpC8uJXljJ3an2%2Fuploads%2Fgit-blob-a8cc720c87548edcbae1f237a9f7c271f575a081%2Fchart-api.png?alt=media)

Note that, when defining a chart from your agent:

* The type of chart defined in your agent must match your selection when adding it to a dashboard or record.
* The name of the chart must be URL-safe.

### Chart context

When defining a chart handler, the callback receives a `context` object and a `result_builder`.

The `context` object provides access to:

| Property                      | Availability           | Description                                                           |
| ----------------------------- | ---------------------- | --------------------------------------------------------------------- |
| `context.datasource`          | All charts             | Access to your collections for querying data                          |
| `context.caller`              | All charts             | Information about the current user (email, team, role, timezone, ...) |
| `context.parameters`          | All charts             | Custom query string / body parameters sent to the chart endpoint      |
| `context.record_id`           | Collection charts only | The id of the record the chart is displayed on                        |
| `context.composite_record_id` | Collection charts only | The composite primary key as an array                                 |
| `context.get_record(fields)`  | Collection charts only | Helper to fetch the current record                                    |

#### Traditional Syntax

```ruby
include ForestAdmin::Types

@create_agent.add_chart('example') do |context, result_builder|
  # Access the current user
  email = context.caller.email
  timezone = context.caller.timezone

  # Access custom parameters from the request
  start_date = context.parameters['startDate']

  # Query your data
  aggregation = Aggregation.new(operation: 'Count')
  result = context.datasource.get_collection('orders').aggregate(Filter.new, aggregation)

  result_builder.value(result[0]['value'] || 0)
end
```

#### DSL Syntax

```ruby
@create_agent.chart :example do
  # Access custom parameters from the request
  start_date = context.parameters['startDate']

  # Query your data
  aggregation = Aggregation.new(operation: 'Count')
  result = context.datasource.get_collection('orders').aggregate(context.caller, Filter.new, aggregation)

  value(result[0]['value'] || 0)
end
```

### Relation to Smart Charts

[Smart Charts](https://docs.forestadmin.com/developer-guide-agents-ruby/frontend-customization/smart-charts) allow the implementation of any charts types that are not supported natively (density maps, cohorts, ...).

Coding a Chart handler from your agent, on the other hand, gives you the full freedom in how the data powering a native chart is computed.
