| Paste number 65702: | Adding mixins to an instance |
| Pasted by: | bobbysmith007 |
| 3 months, 1 week ago | |
| #lisp | Context in IRC logs | |
| 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 1: | correction |
| Pasted by: | bobbysmith007 |
| 3 months, 1 week ago | |
| Context in IRC logs | |
| 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))) |
| Annotation number 2: | Abstracted adding a mixin to an instance as a method call |
| Pasted by: | bobbysmith007 |
| 3 months, 1 week ago | |
| Context in IRC logs | |
| 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)))) |