| Paste number 65702: | Adding mixins to an instance |
| Pasted by: | bobbysmith007 |
| When: | 10 months, 1 week ago |
| Share: | Tweet this! | http://paste.lisp.org/+1EP2 |
| Channel: | #lisp |
| Paste contents: |
(defclass meta-mixin ()
()
(:documentation "A class that lets you pass in mixins to add to an instance, as initargs.
It will handle figuring out a reasonable class name, ensuring that it exists, and
changing the class on instance along the way"))
(defmethod initialize-instance :after ((obj meta-mixin) &rest args &key mixins &allow-other-keys)
(loop for mixin in (ensure-list mixins)
do
(unless (typep obj mixin)
(let* ((class-name (class-name (class-of obj)))
(class (closer-mop:ensure-class
(intern-concat (list class-name "-" mixin))
:metaclass (class-of (class-of obj))
:direct-superclasses (list (find-class class-name)
(find-class mixin)))))
(apply #'change-class obj (class-name class) args)
))))
;; root of our web component library
(defcomponent ucwb::adw-component (html-element meta-mixin)
((ucwb::attributes :accessor ucwb::attributes :initarg :attributes :initform ())
(ucwb::css-classes :initform '() :initarg :css-classes)
(ucwb::dom-unique-id :initform nil))
(:default-initargs :dom-id nil))
;; a mixin to allow us to identify search forms
(defclass search-composite-mixin ()
())
;; a mixin to allow us to identify elements that represent a bit of where clause on
;; a search form
(defclass search-component-mixin ()
((search-clause :accessor search-clause :initarg :search-clause :initform nil)))
;; a mixin to allow us to tag objects as representing a database column
(defclass database-column ()
((table :accessor table :initarg :table :initform nil)
(column :accessor column :initarg :column :initform nil)))
;; A dummy component that shows adding random bits of data to search form components based on its mixin list
(defcomponent search-test (adw-detail-component search-composite-mixin)
((name :accessor name
;; labelbox is our standard textbox that has an editability flag
;; determining how it renders
:component (xhtml-labelbox :search-clause "name like '%{value}%'"
:table "clients" :column "name"
:mixins 'search-component-mixin 'database-column))
(address :accessor address
:component (xhtml-labelbox :search-clause "address+city+state like '%{value}%'"
:mixins 'search-component-mixin))
(ordernumber :accessor ordernumber
:component (xhtml-labelbox :search-clause "ordernumber like '%{value}%' or CAST (billing_id as VARCHAR (16)) like '%{value}%'"
:mixins 'search-component-mixin))
))Annotations for this paste:
| Annotation number 2: | Abstracted adding a mixin to an instance as a method call |
| Pasted by: | bobbysmith007 |
| When: | 10 months, 1 week ago |
| Share: | Tweet this! | http://paste.lisp.org/+1EP2#2 |
| Paste contents: |
(defmethod add-mixin-to-instance ((obj t) (mixin symbol) &rest initargs)
"Adds a mixin to the passed in obj, using initargs for reinitialization
mixin should be a class-name, it should probably define a (shared-initialize :after)
if it wants to interact with the object (other than as slots)
"
(unless (typep obj mixin)
(let* ((class-name (class-name (class-of obj)))
(class (closer-mop:ensure-class
(intern-concat (list class-name "-" mixin))
:metaclass (class-of (class-of obj))
:direct-superclasses (list (find-class class-name)
(find-class mixin)))))
(apply #'change-class obj (class-name class) initargs))))| Annotation number 1: | correction |
| Pasted by: | bobbysmith007 |
| When: | 10 months, 1 week ago |
| Share: | Tweet this! | http://paste.lisp.org/+1EP2#1 |
| Paste contents: |
;;The name slot should actually be defined as follows
(name :accessor name
;; labelbox is our standard textbox that has an editability flag
;; determining how it renders
:component (xhtml-labelbox :search-clause "name like '%{value}%'"
:table "clients" :column "name"
:mixins '(search-component-mixin database-column)))