Skip to content
Snippets Groups Projects
Commit 62a7becf authored by Cam Saul's avatar Cam Saul
Browse files

mongo test data stuff (WIP)

parent bf9794e6
No related branches found
No related tags found
No related merge requests found
......@@ -277,7 +277,7 @@
(sel :one User :id 1) -> returns the User (or nil) whose id is 1
(sel :many OrgPerm :user_id 1) -> returns sequence of OrgPerms whose user_id is 1
OPTION, if specified, is one of `:field`, `:fields`, `:id`, `:id->field`, `:field->id`, or `:id->fields`.
OPTION, if specified, is one of `:field`, `:fields`, `:id`, `:id->field`, `:field->id`, `:field->obj`, or `:id->fields`.
;; Only return IDs of objects.
(sel :one :id User :email \"cam@metabase.com\") -> 120
......@@ -297,6 +297,11 @@
(sel :many :field->id [User :first_name])
-> {\"Cam\" 1, \"Sameer\" 2}
;; Return a map of field value -> *entire* object. Duplicates will be discarded!
(sel :many :field->obj [Table :name] :db_id 1)
-> {\"venues\" {:id 1, :name \"venues\", ...}
\"users\" {:id 2, :name \"users\", ...}}
;; Return a map of ID -> specified fields
(sel :many :id->fields [User :first_name :last_name])
-> {1 {:first_name \"Cam\", :last_name \"Saul\"},
......@@ -345,6 +350,11 @@
(map (fn [{id# :id field-val# field#}]
{field-val# id#}))
(into {})))
:field->obj `(let [[entity# field#] ~entity]
(->> (sel :many entity# ~@forms)
(map (fn [obj#]
{(field# obj#) obj#}))
(into {})))
:fields `(let [[~'_ & fields# :as entity#] ~entity]
(map #(select-keys % fields#)
(sel :many entity# ~@forms)))
......
......@@ -5,7 +5,8 @@
[monger.core :as mg]))
(def ^:dynamic *mongo-connection*
"Bound by top-level `with-mongo-connection` so it may be reused within its body."
"Connection to a Mongo database.
Bound by top-level `with-mongo-connection` so it may be reused within its body."
nil)
(defn -with-mongo-connection
......
(ns metabase.driver.mongo.test-data
"Functionality related to creating / loading a test database for the Mongo driver."
(:require [colorize.core :as color]
[medley.core :as m]
(monger [collection :as mc]
[core :as mg])
[metabase.db :refer :all]
[metabase.driver :as driver]
[metabase.driver.mongo.util :refer [with-mongo-connection]]
(metabase.models [database :refer [Database]]
[field :refer [Field]]
[table :refer [Table]])
[metabase.test-data :refer :all]
[metabase.test-data.data :as data]))
(declare load-data)
;; ## CONSTANTS
(def ^:private ^:const mongo-test-db-conn-str
"Connection string for the Metabase Mongo Test DB." ; TODO - this needs to come from env var or something so we can get tests working in CircleCI too
"mongodb://localhost/metabase-test")
(def ^:private ^:const mongo-test-db-name
"Name of the Mongo test database."
"Mongo Test")
;; ## MONGO-TEST-DB + OTHER DELAYS
(def mongo-test-db
"A delay that fetches or creates the Mongo test `Database`.
If DB is created, `load-data` and `sync-database!` are called to get the DB in a state that we can use for testing."
(delay (or (sel :one Database :name mongo-test-db-name)
(let [db (ins Database
:organization_id @org-id
:name mongo-test-db-name
:engine :mongo
:details {:conn_str mongo-test-db-conn-str})]
(load-data)
(driver/sync-database! db)
db))))
(def mongo-test-db-id
"A Delay that returns the ID of `mongo-test-db`, forcing creation of it if needed."
(delay (:id @mongo-test-db)))
;; ## FNS FOR GETTING RELEVANT TABLES / FIELDS
(def ^{:arglists '([table-name])} table-name->table
"Return Mongo test database `Table` with given name.
(table-name->table :users)
-> {:id 10, :name \"users\", ...}"
(let [-table-name->table (delay (m/map-keys keyword (sel :many :field->obj [Table :name] :db_id @mongo-test-db-id)))]
(fn [table-name]
{:pre [(or (keyword? table-name)
(string? table-name))]
:post [(map? %)]}
(@-table-name->table (keyword table-name)))))
(defn table-name->id [table-name]
{:pre [(or (keyword? table-name)
(string? table-name))]
:post [(integer? %)]}
(:id (table-name->table (keyword table-name))))
(defn table-name->field-name->field [table-name]
(let [table (table-name->table table-name)]))
;; ## LOADING STUFF
(defn- load-data
"Load the data for the Mongo test database. This can safely be called multiple times; duplicate documents will *not* be inserted."
[]
(with-mongo-connection [mongo-db @mongo-test-db]
(doseq [[collection {fields :fields rows :rows}] data/test-data]
(let [fields (map :name fields)
rows (map-indexed (partial vector) rows)]
(doseq [[i row] rows]
(try
(mc/insert mongo-db (name collection) (assoc (zipmap fields row)
:_id (inc i)))
(catch com.mongodb.MongoException$DuplicateKey _)))
(println (color/cyan (format "Loaded data for collection '%s'." (name collection))))))))
......@@ -224,8 +224,8 @@
@test-db ; force lazy evaluation of Test DB
(map-table-kws (fn [table-kw]
(->> (-> table-kw name .toUpperCase)
(sel :one [Table :id] :db_id @db-id :name)
:id)))))
(sel :one [Table :id] :db_id @db-id :name)
:id)))))
(def
^{:doc "A map of Table name keywords -> map of Field name keywords -> Field IDs.
......@@ -237,14 +237,14 @@
table-fields
(delay
@test-db ; force lazy evaluation of Test DB
(map-table-kws (fn [table-kw]
(->> (sel :many [Field :name :id] :table_id (@tables table-kw))
(map (fn [{:keys [^String name id]}]
{:pre [(string? name)
(integer? id)
(not (zero? id))]}
{(keyword (.toLowerCase name)) id}))
(into {}))))))
(map-table-kws (fn [table-kw]
(->> (sel :many [Field :name :id] :table_id (@tables table-kw))
(map (fn [{:keys [^String name id]}]
{:pre [(string? name)
(integer? id)
(not (zero? id))]}
{(keyword (.toLowerCase name)) id}))
(into {}))))))
;; ## Users
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment