(in-package :lisp-on-lines) ;;;; * Relational Attributes (defvar *parent-relations* nil) ;;;; ** has-a ;;;; Used for foreign keys, currently only works with clsql. (defattribute relational-attribute () ()) (defdisplay :wrap-around ((attribute relational-attribute) object) (print (cons "parent-r" *parent-relations*)) (dletf (((value attribute) (attribute-value object attribute))) (unless (find (value attribute) *parent-relations* :test #'meta-model::generic-equal) (call-next-method)))) (defattribute has-a (relational-attribute) () (:default-properties :has-a nil :test 'meta-model::generic-equal)) ;; (define-layered-method attribute-value (object (attribute has-a)) (multiple-value-bind (obj key class) (meta-model:explode-foreign-key object (slot-name attribute) :nilp t) (if (persistentp object) obj (first (select class :where [= [slot-value class key] (call-next-method)] :flatp t ))))) (define-layered-method (setf attribute-value) ((value standard-object) object (attribute has-a)) (let ((val (slot-value value (find-if (curry #'primary-key-p value) (list-keys value))))) (setf (attribute-value object attribute) val))) (define-layered-function find-all-foreign-objects (o a)) (define-layered-method find-all-foreign-objects (object (attribute has-a)) (select (meta-model:find-join-class object (slot-name attribute)) :flatp t)) (defdisplay ((attribute has-a) object) (let ((args (plist-union (description.properties attribute) (has-a attribute))) (val (attribute-value object attribute))) (when val (setf (getf args :type) 'lol::one-line)) (apply #'display* val args))) (defdisplay :in-layer editor ((attribute has-a) object) (