Created
April 4, 2009 00:03
-
-
Save ashafa/90052 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; I want to be able to do something like this... | |
(defdbtest has-and-belongs-to-many-creates-find-functions | |
(let [humedai (manufacturer/create (valid-manufacturer-with {:name "Humedai Automotive"})) | |
s3000xi (product/create {:name "S-3000xi" :manufacturer_id (:id humedai)}) | |
s3000xl (product/create {:name "S-3000xl" :manufacturer_id (:id humedai)}) | |
chambars (dealer/create {:name "Chambers Motors"}) | |
ira (dealer/create {:name "IRA Autos"}) | |
tundre (dealer/create {:name "Tundre Automotives"})] | |
(dealer/insert-relationship chambars (:id s3000xi)) | |
(dealer/insert-relationship chambars (:id s3000xl)) | |
(dealer/insert-relationship ira (:id s3000xl)) | |
(product/insert-relationship s3000xl (:id tundre)) | |
(are (= _1 _2) | |
[s3000xi s3000xl] (dealer/find-products chambars) | |
[chambars] (product/find-dealers s3000xi) | |
[chambars ira tundre] (product/find-dealers s3000xl)))) | |
;; So I did this... | |
(defn has-and-belongs-to-many | |
"Called indirectly via clj-record.core/init-model. | |
Experimental." | |
[model-name association-name table-name] | |
(let [associated-model-name (singularize (name association-name)) | |
foreign-key-attribute-1 (keyword (str model-name "_id")) | |
foreign-key-attribute-2 (keyword (str associated-model-name "_id")) | |
join-table-name (if (keyword? table-name) (name table-name) table-name) | |
; Next line assumes the join table namespace is the same as the table name created in the database. Ideally, | |
; maybe create the table in the DB *only if it does not exist* and call the init-model on the join table model | |
; in this fn. This would get rid of the model clj file for the join table. | |
join-table-namespace (symbol (str (str-utils/str-join "." | |
(drop-last (str-utils/re-split #"\." (str *ns*)))) | |
"." join-table-name)) | |
find-fn-name (symbol (str "find-" association-name)) | |
destroy-fn-name (symbol "destroy-relationship") | |
insert-fn-name (symbol "insert-relationship")] | |
`(do | |
(require '~join-table-namespace) | |
(defn ~find-fn-name [record#] | |
(let [associations# (clj-record.core/find-records ~join-table-name {~foreign-key-attribute-1 (record# :id)})] | |
(if (empty? associations#) | |
associations# | |
(clj-record.core/find-records ~associated-model-name {:id (apply query/in | |
(map ~foreign-key-attribute-2 associations#))})))) | |
(defn ~destroy-fn-name [record#] | |
(clj-record.core/destroy-records ~join-table-name {~foreign-key-attribute-2 (record# :id)})) | |
(defn ~insert-fn-name [record# id#] | |
(clj-record.core/insert ~join-table-name {~foreign-key-attribute-1 (record# :id) ~foreign-key-attribute-2 id#}))))) | |
;; The model init would look like this for both of the affected models... | |
(clj-record.core/init-model | |
:table-name "productos" | |
(:associations | |
(belongs-to manufacturer) | |
(has-and-belongs-to-many dealers :dealers_products))) | |
(clj-record.core/init-model | |
:table-name "dealers" | |
(:associations | |
(has-and-belongs-to-many products :dealers_products))) | |
;; And this is the join table model init which I mentioned in the comment in | |
;; the has-and-belongs-to-many assocaition fn that I think I can get rid | |
;; of if it's eval'd in the association fn. | |
(clj-record.core/init-model :table-name "dealers_products") ;; :table-name included to prevent pluralization. | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment