 (defn table-name [model-name]
   (pluralize (if (string? model-name) model-name (name model-name))))
 
-(defn to-conditions [attributes]
+(defn to-conditions
+  "Converts the given attribute map into a clojure.contrib.sql style 'where-params,'
+  a vector containing a parameterized conditions string followed by ordered values for the parameters.
+  Conditions will be ANDed together.
+  Nil attributes will be turned into 'attr_name IS NULL' with no value in the vector."
+  [attributes]
   (let [[parameterized-conditions values] (reduce
       (fn [[parameterized-conditions values] [attribute value]]
         (if (nil? value)

      attributes)]
    (apply vector (str-utils/str-join " AND " parameterized-conditions) values)))

(defn create [model-name attributes]
  (sql/with-connection db
    (let
      [key-vector (keys attributes)

            (sql/with-query-results rows ["VALUES IDENTITY_VAL_LOCAL()"] (:1 (first rows))))] ; XXX: db-vendor-specific
      (get-record model-name id))))

(defn find-records
  "Returns a vector of records matching (-> attributes to-conditions)."
  [model-name attributes]
  (let [[parameterized-where & values] (to-conditions attributes)
        select-query (format "select * from %s where %s" (table-name model-name) parameterized-where)]
    (sql/with-connection db
      (sql/with-query-results rows (apply vector select-query values)
        (doall (map #(merge {} %) rows))))))

(defn update
  "Updates by (partial-record :id), updating only those columns included in partial-record."
  [model-name partial-record]
  (sql/with-connection db
    (sql/update-values (table-name model-name) ["id = ?" (:id partial-record)] (dissoc partial-record :id))))

(defn destroy-record
  "Deletes by (record :id)."
  [model-name record]
  (sql/with-connection db
    (sql/delete-rows (table-name model-name) ["id = ?" (:id record)])))

(defn destroy-records
  "Deletes all records matching (-> attributes to-conditions)."
  [model-name attributes]
  (sql/with-connection db
    (sql/delete-rows (table-name model-name) (to-conditions attributes))))

