kwrooijen / gungnir

A fully featured, data-driven database library for Clojure.
https://kwrooijen.github.io/gungnir/
MIT License
165 stars 9 forks source link

Model alias for tables #3

Closed kwrooijen closed 4 years ago

kwrooijen commented 4 years ago

Currently the model name will be mapped to the table name. The resulting model (before it is stored using gungnir.model/register!) has a property :table which contains the table name. This name is extracted from the key that you register it with.

It could be desirable to have a model name not be the same as a table name. Or possibly even have multiple models for a single table?

Ramblurr commented 4 years ago

It could be desirable to have a model name not be the same as a table name

Yes!

Here's a great example.

In postgres "user" is a reserved word, so you can't make a table like this: CREATE TABLE user (...); you have to do CREATE TABLE "user" (...); And in every query you must quote it SELECT * from "users" WHERE...;

In my first gungnir model, I tried to define this:

(model/register!
  {:users ;; <--- plural to workaround postgres reserved word
   [:map
    [:user/id {:primary-key true :auto true} uuid?] ;; <--- singular because its much more natural than users
    [:user/email [:re {:error/message "Invalid email"} #".+@.+\..+"]]
    ...]})

In general I've always followed the convention of plural table names and singular namespaces for the attributes, would love to be able to do this in gungnir.

jmayaalv commented 4 years ago

I agree this really needed, but i think it would be best if the table name doesn't need to be linked to the model name. It's very common, at least on the companies i have worked before, to have prefix for table names. I like the way honeysql handle tables aliases so maybe we could achieve something similar, for ex:

Table name same as model

(model/register!
  {:user 
   [:map
    [:user/id {:primary-key true :auto true} uuid?] ;; <--- singular because its much more natural than users
    [:user/email [:re {:error/message "Invalid email"} #".+@.+\..+"]]
    ...]})

Alternative table name

(model/register!
  {[:user :sec_user]
   [:map
    [:user/id {:primary-key true :auto true} uuid?] ;; <--- singular because its much more natural than users
    [:user/email [:re {:error/message "Invalid email"} #".+@.+\..+"]]
    ...]})
kwrooijen commented 4 years ago

I think a nice solution would be this format:

(gungnir.model/register!
 {:user
  [:map
   {:table "users"} ;; <<<<< Choose which table to use
   [:user/id {:primary-key true} uuid?]]})

Currently under the hood the :table property already gets set. https://github.com/kwrooijen/gungnir/blob/84feb362f6752cde3e7f78cd6e79a0aebbf5ff57/src/cljc/gungnir/model.cljc#L33-L36

However this is an incomplete feature (which is why it's not documented anywhere). I think in some parts of the code the model key is still used instead of the table name. ~Once I've implemented https://github.com/kwrooijen/gungnir/issues/5 I can complete this feature.~