-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Adding a new model
You added new functionality to Metabase which requires state to be persisted. To do so you will need to write a Toucan model, and make sure all the migrations are set up.
Note, this guide deals only with Metabase-specifics. For Toucan models basics, refer to Defining models chapter of Toucan documentation.
Models go into metabase.models.____ namespace
. The convention we use is to use singular in model names, so DomainEntity
, rather than DomainEntities.
To lessen boilerplate, we have metabase.models.interface/IModelDefaults
, and metabase.models.interface/IObjectPermissions
into which you merge
customizations you might need.
(defn- perms-objects-set [{:keys [source-table]} _]
(let [table (Table source-table)]
#{(perms/object-path (:db_id table) (:schema table) (:id table))}))
(u/strict-extend (class DomainEntity)
models/IModel
(merge models/IModelDefaults
{:hydration-keys (constantly [:domain-entity])
:types (constantly {:metrics :json
:segments :json
:breakout_dimensions :json
:dimensions :json
:type :keyword})
:properties (constantly {:timestamped? true}) ; don't forget to add created_at and updated_at fields when defining the migration (see bellow)
:pre-update serialize-dimensions
:pre-insert serialize-dimensions
:post-select deserialize-dimensions})
i/IObjectPermissions
(merge i/IObjectPermissionsDefaults
{:can-read? (partial i/current-user-has-full-permissions? :read)
:can-write? i/superuser?
;; here we'll just use the same permission set as the table to which this refers to,
;; but you might need something more fine-grained.
;; Look into `metabase.models.permissions` for what access controls you have at your disposal.
:perms-objects-set perms-objects-set}))
Access control, pre-/post- hooks, and :types
(de)serializations should be covered by tests.
Add the model to entities
in metabase.cmd.load-from-h2
, minding where in the list you insert it.
Update the test fixture DB. To do so, set
export MB_DB_FILE=frontend/frontend/test/__runner__/test_db_fixture.db
(remember: MB_DB_FILE
doesn't take the trailing .mv.db
in the file name)
and start Metabase so that migrations get run. Include test_db_fixture.db
in the PR.
Add a new changeset to resources/migrations/000_migrations.yaml
.
Use comments to explain what is being added both in terms of the whole changeset as well as documenting non-trivial fields (eg. anything that has a :types
serialization).
Use delete cascades by specifying deleteCascade: true
on foreign keys where possible instead of relying on manual cleanup via post-delete
hook.
Don't forget to add indices that cover the common access patterns.
Avoid migrations which touch existing data (adding new fields to existing tables is fine). It's better to have a constraint less (which can always be enforced by Schema).
- Backend
- Metabase Developer Reference
- Product Management
- QA and Testing
- Writing A Driver
- Driver Notices
- REST API Notices
- Writing style guide for documentation and blog posts (WIP)