# Translation strategy

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

### Steps

Creating a custom data source will require you to work on the 3 following steps:

1. Declare the structure of the data
2. Declare the API capabilities
3. Code a translation layer

### Minimal example

```ruby
require 'net/http'
require 'json'
require 'uri'

module App
  module Collections
    # Minimal implementation of a readonly data source
    class MyCollection < ForestAdminDatasourceToolkit::Collection
      include ForestAdminDatasourceToolkit::Schema
      # The real work is in writing this module
      # Expect a full featured query translation module to be over 1000 LOCs
      include QueryGenerator

      def initialize(datasource)
        # Set name of the collection once imported
        super(datasource, 'MyCollection')

        add_field('id', ColumnSchema.new(
          column_type: 'Number',
          filter_operators: [], # As we are using the query translation strategy => define capabilities
          is_primary_key: true,
          is_read_only: true, # field is readonly
          is_sortable: false # field is not sortable
        ))

        add_field('title', ColumnSchema.new(
          column_type: 'String',
          filter_operators: [],
          is_primary_key: false,
          is_read_only: true,
          is_sortable: false
        ))
      end

      def list(caller, filter, projection)
        params = QueryGenerator.generate_list_query_string(filter, projection)
        uri = URI.parse('http://my-api/my-collection')
        uri.query = URI.encode_www_form(params)

        response = Net::HTTP.get_response(uri)
        body = JSON.parse(response.body)

        body['items']
      end

      def aggregate(caller, filter, aggregation, limit = nil)
        params = QueryGenerator.generate_aggregate_query_string(filter, aggregation, limit)
        uri = URI.parse('http://my-api/my-collection')
        uri.query = URI.encode_www_form(params)

        response = Net::HTTP.get_response(uri)
        body = JSON.parse(response.body)

        body
      end
    end
  end
end
```

```ruby
module App
  class MyDatasource < ForestAdminDatasourceToolkit::Datasource
    def initialize
      super
      add_collection(Collections::MyCollection.new(self)) # List of your collections
    end
  end
end
```

```ruby
lambda do
    datasource = new MyDatasource;
    agent = new ForestAdminAgent::Builder::AgentFactory([]);
    agent.add_datasource(datasource);
end
```

### Read more

Implementing a data source using the "query translation" strategy is an advanced concept: you will need to have a deep understanding of Forest Admin internals.

This strategy is a good match when writing data sources for full-featured databases.

Before starting, it is highly advised to read and understand the following sections:

* [Data Model Typing](/developer-guide-agents-ruby/under-the-hood/data-model/typing.md)
* [Data Model Relationships](/developer-guide-agents-ruby/under-the-hood/data-model/relationships.md)
* [Query interface](/developer-guide-agents-ruby/data-sources/getting-started/queries.md)
* [Fields and projections](/developer-guide-agents-ruby/data-sources/getting-started/queries/fields-projections.md)
* [Filters](/developer-guide-agents-ruby/data-sources/getting-started/queries/filters.md)
* [Aggregations](/developer-guide-agents-ruby/data-sources/getting-started/queries/aggregations.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.forestadmin.com/developer-guide-agents-ruby/data-sources/custom/translation.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
