Convenience namespace exposing the most common parts of the library's public API for day-to-day usage (i.e., not implementing anything advanced)
Convenience namespace exposing the most common parts of the library's public API for day-to-day usage (i.e., not implementing anything advanced)
(batched-hydrate model k rows)
(changes instance)
Get a map with any changes made to instance
since it came out of the DB. Only includes keys that have been
added or given different values; keys that were removed are not counted. Returns nil
if there are no changes.
Get a map with any changes made to `instance` since it came out of the DB. Only includes keys that have been added or given different values; keys that were removed are not counted. Returns `nil` if there are no changes.
(compile & body)
Return the compiled query that would be executed by a form, rather than executing that form itself.
(delete/delete :table :id 1) => ["DELETE FROM table WHERE ID = ?" 1]
Return the compiled query that would be executed by a form, rather than executing that form itself. (delete/delete :table :id 1) => ["DELETE FROM table WHERE ID = ?" 1]
(count modelable & kv-args? query?)
(current instance)
Return the underlying map representing the current state of an instance
.
Return the underlying map representing the current state of an `instance`.
(default-connectable model)
The default connectable that should be used when executing queries for model
if
no toucan2.connection/*current-connectable*
is currently bound. By default, this just returns the global default
connectable, :default
, but you can tell Toucan to use a different default connectable for a model by implementing
this method.
The default connectable that should be used when executing queries for `model` if no [[toucan2.connection/*current-connectable*]] is currently bound. By default, this just returns the global default connectable, `:default`, but you can tell Toucan to use a different default connectable for a model by implementing this method.
(define-after-insert model [instance-binding] & body)
(define-after-select model [instance-binding] & body)
(define-after-update model [instance-binding] & body)
(define-before-delete model [instance-binding] & body)
(define-before-insert model [instance-binding] & body)
(define-before-select model [args-binding] & body)
(define-before-select [model query-class] [args-binding] & body)
(define-before-update model [row-binding] & body)
(define-default-fields model & body)
(deftransforms model transforms)
Define type transforms to use for a specific model. transforms
should be a map of
{:column-name {:in <fn>, :out <fn>}}
:in
transforms are applied to values going over the wire to the database; these generally only applied to values
passed at or near the top level to various functions; don't expect Toucan 2 to parse your SQL to find out which
parameter corresponds to what in order to apply transforms or to apply transforms inside JOINS in hand-written
HoneySQL. That said, unless you're doing something weird your transforms should generally get applied.
:out
transforms are applied to values coming out of the database; since nothing weird really happens there this is
done consistently.
Transform functions for either case are skipped for nil
values.
Example:
(deftransforms :models/user {:type {:in name, :out keyword}})
You can also define transforms independently, and derive a model from them:
(deftransforms ::type-keyword {:type {:in name, :out keyword}})
(derive :models/user ::type-keyword) (derive :models/user ::some-other-transform)
Don't derive a model from multiple deftransforms
for the same key in the same direction.
When multiple transforms match a given model they are combined into a single map of transforms with merge-with merge
. If multiple transforms match a given column in a given direction, only one of them will be used; you should
assume which one is used is indeterminate. (This may be made an error, or at least a warning, in the future.)
Until upstream issue https://github.com/camsaul/methodical/issues/97 is resolved, you will have to specify which method should be applied first in cases of ambiguity using [[methodical.core/prefer-method!]]:
(m/prefer-method! transformed/transforms ::user-with-location ::user-with-password)
If you want to override transforms completely for a model, and ignore transforms from ancestors of a model, you can
create an :around
method:
(defmethod toucan2.tools.transformed/transforms :around ::my-model [_model] {:field {:in name, :out keyword}})
Define type transforms to use for a specific model. `transforms` should be a map of {:column-name {:in <fn>, :out <fn>}} `:in` transforms are applied to values going over the wire to the database; these generally only applied to values passed at or near the top level to various functions; don't expect Toucan 2 to parse your SQL to find out which parameter corresponds to what in order to apply transforms or to apply transforms inside JOINS in hand-written HoneySQL. That said, unless you're doing something weird your transforms should generally get applied. `:out` transforms are applied to values coming out of the database; since nothing weird really happens there this is done consistently. Transform functions for either case are skipped for `nil` values. Example: (deftransforms :models/user {:type {:in name, :out keyword}}) You can also define transforms independently, and derive a model from them: (deftransforms ::type-keyword {:type {:in name, :out keyword}}) (derive :models/user ::type-keyword) (derive :models/user ::some-other-transform) Don't derive a model from multiple `deftransforms` for the same key in the same direction. When multiple transforms match a given model they are combined into a single map of transforms with `merge-with merge`. If multiple transforms match a given column in a given direction, only one of them will be used; you should assume which one is used is indeterminate. (This may be made an error, or at least a warning, in the future.) Until upstream issue https://github.com/camsaul/methodical/issues/97 is resolved, you will have to specify which method should be applied first in cases of ambiguity using [[methodical.core/prefer-method!]]: (m/prefer-method! transformed/transforms ::user-with-location ::user-with-password) If you want to override transforms completely for a model, and ignore transforms from ancestors of a model, you can create an `:around` method: (defmethod toucan2.tools.transformed/transforms :around ::my-model [_model] {:field {:in name, :out keyword}})
(delete! modelable & conditions? query?)
Returns number of rows deleted.
Returns number of rows deleted.
(do-with-connection connectable f)
(exists? modelable & kv-args? query?)
(hydrate results k & ks)
Hydrate a single object or sequence of objects.
[[toucan2.hydrate/hydrate]] attempts to do a batched hydration where possible. If the key being hydrated is
defined as one of some table's [[toucan2.hydrate/model-for-automagic-hydration]], hydrate
will do a batched
toucan2.select/select
if a corresponding key (by default, the same key suffixed by -id
) is found in the
objects being batch hydrated. The corresponding key can be customized by
implementing [[toucan2.hydrate/fk-keys-for-automagic-hydration]].
(hydrate [{:user_id 100}, {:user_id 101}] :user)
Since :user
is a hydration key for :models/User
, a single toucan2.select/select
will used to fetch Users:
(db/select :models/User :id [:in #{100 101}])
The corresponding Users are then added under the key :user
.
If the key can't be hydrated auto-magically with the appropriate [[toucan2.hydrate/model-for-automagic-hydration]], [[toucan2.hydrate/hydrate]] will attempt to do batched hydration if it can find a matching method for [[toucan2.hydrate/batched-hydrate]]. If a matching function is found, it is called with a collection of objects, e.g.
(m/defmethod hydrate/batched-hydrate [:default :fields] [_model _k rows] (let [id->fields (get-some-fields rows)] (for [row rows] (assoc row :fields (get id->fields (:id row))))))
If the key is not eligible for batched hydration, [[toucan2.hydrate/hydrate]] will look for a matching
[[toucan2.hydrate/simple-hydrate]] method. simple-hydrate
is called with a single row.
(m/defmethod simple-hydrate [:default :dashboard] [_model _k {:keys [dashboard-id], :as row}] (assoc row :dashboard (select/select-one :models/Dashboard :toucan/pk dashboard-id)))
You can hydrate several keys at one time:
(hydrate {...} :a :b) -> {:a 1, :b 2}
You can do recursive hydration by listing keys inside a vector:
(hydrate {...} [:a :b]) -> {:a {:b 1}}
The first key in a vector will be hydrated normally, and any subsequent keys will be hydrated inside the corresponding values for that key.
(hydrate {...} [:a [:b :c] :e]) -> {:a {:b {:c 1} :e 2}}
Hydrate a single object or sequence of objects. #### Automagic Batched Hydration (via [[toucan2.hydrate/model-for-automagic-hydration]]) [[toucan2.hydrate/hydrate]] attempts to do a *batched hydration* where possible. If the key being hydrated is defined as one of some table's [[toucan2.hydrate/model-for-automagic-hydration]], `hydrate` will do a batched [[toucan2.select/select]] if a corresponding key (by default, the same key suffixed by `-id`) is found in the objects being batch hydrated. The corresponding key can be customized by implementing [[toucan2.hydrate/fk-keys-for-automagic-hydration]]. (hydrate [{:user_id 100}, {:user_id 101}] :user) Since `:user` is a hydration key for `:models/User`, a single [[toucan2.select/select]] will used to fetch Users: (db/select :models/User :id [:in #{100 101}]) The corresponding Users are then added under the key `:user`. #### Function-Based Batched Hydration (via [[toucan2.hydrate/batched-hydrate]] methods) If the key can't be hydrated auto-magically with the appropriate [[toucan2.hydrate/model-for-automagic-hydration]], [[toucan2.hydrate/hydrate]] will attempt to do batched hydration if it can find a matching method for [[toucan2.hydrate/batched-hydrate]]. If a matching function is found, it is called with a collection of objects, e.g. (m/defmethod hydrate/batched-hydrate [:default :fields] [_model _k rows] (let [id->fields (get-some-fields rows)] (for [row rows] (assoc row :fields (get id->fields (:id row)))))) #### Simple Hydration (via [[toucan2.hydrate/simple-hydrate]] methods) If the key is *not* eligible for batched hydration, [[toucan2.hydrate/hydrate]] will look for a matching [[toucan2.hydrate/simple-hydrate]] method. `simple-hydrate` is called with a single row. (m/defmethod simple-hydrate [:default :dashboard] [_model _k {:keys [dashboard-id], :as row}] (assoc row :dashboard (select/select-one :models/Dashboard :toucan/pk dashboard-id))) #### Hydrating Multiple Keys You can hydrate several keys at one time: (hydrate {...} :a :b) -> {:a 1, :b 2} #### Nested Hydration You can do recursive hydration by listing keys inside a vector: (hydrate {...} [:a :b]) -> {:a {:b 1}} The first key in a vector will be hydrated normally, and any subsequent keys will be hydrated *inside* the corresponding values for that key. (hydrate {...} [:a [:b :c] :e]) -> {:a {:b {:c 1} :e 2}}
(insert! modelable row-or-rows)
(insert! modelable columns row-vectors)
(insert! modelable k v & more)
Returns number of rows inserted.
Returns number of rows inserted.
(insert-returning-instances! modelable row-or-rows)
(insert-returning-instances! [modelable & columns-to-return] row-or-rows)
(insert-returning-instances! modelable columns row-vectors)
(insert-returning-instances! [modelable & columns-to-return]
columns
row-vectors)
(insert-returning-instances! modelable k v & more)
(insert-returning-instances! [modelable & columns-to-return] k v & more)
Like insert!
, but returns a vector of the primary keys of the newly inserted rows rather than the number of rows
inserted. The primary keys are determined by model/primary-keys
. For models with a single primary key, this
returns a vector of single values, e.g. [1 2]
if the primary key is :id
and you've inserted rows 1 and 2; for
composite primary keys this returns a vector of tuples where each tuple has the value of corresponding primary key as
returned by model/primary-keys
, e.g. for composite PK [:id :name]
you might get [[1 "Cam"] [2 "Sam"]]
.
Like [[insert!]], but returns a vector of the primary keys of the newly inserted rows rather than the number of rows inserted. The primary keys are determined by [[model/primary-keys]]. For models with a single primary key, this returns a vector of single values, e.g. `[1 2]` if the primary key is `:id` and you've inserted rows 1 and 2; for composite primary keys this returns a vector of tuples where each tuple has the value of corresponding primary key as returned by [[model/primary-keys]], e.g. for composite PK `[:id :name]` you might get `[[1 "Cam"] [2 "Sam"]]`.
(insert-returning-pks! modelable row-or-rows)
(insert-returning-pks! modelable columns row-vectors)
(insert-returning-pks! modelable k v & more)
Like insert!
, but returns a vector of the primary keys of the newly inserted rows rather than the number of rows
inserted. The primary keys are determined by model/primary-keys
. For models with a single primary key, this
returns a vector of single values, e.g. [1 2]
if the primary key is :id
and you've inserted rows 1 and 2; for
composite primary keys this returns a vector of tuples where each tuple has the value of corresponding primary key as
returned by model/primary-keys
, e.g. for composite PK [:id :name]
you might get [[1 "Cam"] [2 "Sam"]]
.
Like [[insert!]], but returns a vector of the primary keys of the newly inserted rows rather than the number of rows inserted. The primary keys are determined by [[model/primary-keys]]. For models with a single primary key, this returns a vector of single values, e.g. `[1 2]` if the primary key is `:id` and you've inserted rows 1 and 2; for composite primary keys this returns a vector of tuples where each tuple has the value of corresponding primary key as returned by [[model/primary-keys]], e.g. for composite PK `[:id :name]` you might get `[[1 "Cam"] [2 "Sam"]]`.
(instance model)
(instance model m)
(instance model k v & more)
(instance-of? model x)
True if x
is a Toucan2 instance, and its [[protocols/model]] isa?
model
.
(instance-of? ::bird (instance ::toucan {})) ; -> true (instance-of? ::toucan (instance ::bird {})) ; -> false
True if `x` is a Toucan2 instance, and its [[protocols/model]] `isa?` `model`. (instance-of? ::bird (instance ::toucan {})) ; -> true (instance-of? ::toucan (instance ::bird {})) ; -> false
(instance? x)
True if x
is a Toucan2 instance, i.e. a toucan2.instance.Instance
or some other class that satisfies the correct
interfaces.
Toucan instances need to implement [[IModel]], [[IWithModel]], and [[IRecordChanges]].
True if `x` is a Toucan2 instance, i.e. a `toucan2.instance.Instance` or some other class that satisfies the correct interfaces. Toucan instances need to implement [[IModel]], [[IWithModel]], and [[IRecordChanges]].
(model this)
Get the Toucan model associated with this
.
Get the Toucan model associated with `this`.
(model-for-automagic-hydration original-model k)
The model that should be used to automagically hydrate the key k
in instances of original-model
.
(model-for-automagic-hydration :some-table :user) :-> :myapp.models/user
The model that should be used to automagically hydrate the key `k` in instances of `original-model`. (model-for-automagic-hydration :some-table :user) :-> :myapp.models/user
(original instance)
Get the original version of instance
as it appeared when it first came out of the DB.
Get the original version of `instance` as it appeared when it first came out of the DB.
(primary-key-values instance)
(primary-key-values model m)
Return a map of primary key values for a Toucan 2 instance
.
Return a map of primary key values for a Toucan 2 `instance`.
(primary-keys model)
Return a sequence of the primary key columns names, as keywords, for a model.
Return a sequence of the primary key columns names, as keywords, for a model.
(primary-keys-vec model)
Get the primary keys for a model
as a vector.
Get the primary keys for a `model` as a vector.
(query queryable)
(query connectable queryable)
(query connectable modelable queryable)
(query-one queryable)
(query-one connectable queryable)
(query-one connectable modelable queryable)
(reducible-insert modelable row-or-rows)
(reducible-insert modelable columns row-vectors)
(reducible-insert modelable k v & more)
(reducible-insert-returning-instances modelable row-or-rows)
(reducible-insert-returning-instances [modelable & columns-to-return]
row-or-rows)
(reducible-insert-returning-instances modelable columns row-vectors)
(reducible-insert-returning-instances [modelable & columns-to-return]
columns
row-vectors)
(reducible-insert-returning-instances modelable k v & more)
(reducible-insert-returning-instances [modelable & columns-to-return]
k
v
&
more)
(reducible-insert-returning-pks modelable row-or-rows)
(reducible-insert-returning-pks modelable columns row-vectors)
(reducible-insert-returning-pks modelable k v & more)
(reducible-query queryable)
(reducible-query connectable queryable)
(reducible-query connectable modelable queryable)
(reducible-select modelable & kv-args? query?)
(reducible-select [modelable & columns] & kv-args? query?)
(reducible-update modelable
pk?
conditions-map-or-query?
&
conditions-kv-args
changes-map)
(reducible-update-returning-pks modelable
pk?
conditions-map-or-query?
&
conditions-kv-args
changes-map)
(save! object)
(select modelable & kv-args? query?)
(select [modelable & columns] & kv-args? query?)
(select-fn->fn f1 f2 modelable & kv-args? query?)
(select-fn->pk f modelable & kv-args? query?)
(select-fn-reducible f modelable & kv-args? query?)
(select-fn-set f modelable & kv-args? query?)
Like select
, but returns a set of values of (f instance)
for the results. Returns nil
if the set is empty.
Like `select`, but returns a set of values of `(f instance)` for the results. Returns `nil` if the set is empty.
(select-fn-vec f modelable & kv-args? query?)
Like select
, but returns a vector of values of (f instance)
for the results. Returns nil
if the vector is
empty.
Like `select`, but returns a vector of values of `(f instance)` for the results. Returns `nil` if the vector is empty.
(select-one modelable & kv-args? query?)
(select-one [modelable & columns] & kv-args? query?)
(select-one-fn f modelable & kv-args? query?)
(select-one-pk modelable & kv-args? query?)
(select-pk->fn f modelable & kv-args? query?)
(select-pks-fn modelable)
Return a function to get the value(s) of the primary key(s) from a row. Used by toucan2.select/select-pks-reducible
and thus by toucan2.select/select-pks-set
, toucan2.select/select-pks-vec
, etc.
The primary keys are determined by toucan2.model/primary-keys
. By default this is simply the keyword :id
.
Return a function to get the value(s) of the primary key(s) from a row. Used by [[toucan2.select/select-pks-reducible]] and thus by [[toucan2.select/select-pks-set]], [[toucan2.select/select-pks-vec]], etc. The primary keys are determined by [[toucan2.model/primary-keys]]. By default this is simply the keyword `:id`.
(select-pks-set modelable & kv-args? query?)
(select-pks-vec modelable & kv-args? query?)
(simple-hydrate model k row)
Implementations should return a version of map row
with the key k
added.
Implementations should return a version of map `row` with the key `k` added.
(table-name model)
(transforms model)
Return a map of
{column-name {:in <fn>, :out <fn>}}
For a given model
, all matching transforms are combined with merge-with merge
in an indeterminate order, so don't
try to specify multiple transforms for the same column in the same direction for a given model -- compose your
transform functions instead if you want to do that. See toucan2.tools.helpers/deftransforms
for more info.
Return a map of {column-name {:in <fn>, :out <fn>}} For a given `model`, all matching transforms are combined with `merge-with merge` in an indeterminate order, so don't try to specify multiple transforms for the same column in the same direction for a given model -- compose your transform functions instead if you want to do that. See [[toucan2.tools.helpers/deftransforms]] for more info.
(update! modelable
pk?
conditions-map-or-query?
&
conditions-kv-args
changes-map)
(update-returning-pks! modelable
pk?
conditions-map-or-query?
&
conditions-kv-args
changes-map)
(with-call-count [call-count-fn-binding] & body)
Execute body
, trackingthe number of database queries and statements executed. This number can be fetched at any
time withing body
by calling function bound to call-count-fn-binding
:
(with-call-count [call-count] (select ...) (println "CALLS:" (call-count)) (insert! ...) (println "CALLS:" (call-count))) ;; -> CALLS: 1 ;; -> CALLS: 2
Execute `body`, trackingthe number of database queries and statements executed. This number can be fetched at any time withing `body` by calling function bound to `call-count-fn-binding`: (with-call-count [call-count] (select ...) (println "CALLS:" (call-count)) (insert! ...) (println "CALLS:" (call-count))) ;; -> CALLS: 1 ;; -> CALLS: 2
(with-compiled-query [query-binding [model query]] & body)
(with-connection [connection-binding connectable] & body)
(with-connection [connection-binding connectable] & body)
(with-model [model-binding modelable] & body)
(with-transaction [conn-binding connectable] & body)
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close