Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Making Modules

Making Modules

Discover why ColdBox Modules are awesome and how you can go quickly from idea to ForgeBox

Eric Peterson

July 20, 2017
Tweet

More Decks by Eric Peterson

Other Decks in Programming

Transcript

  1. What this talk is — An overview of modules —

    Module + ColdBox superpowers — Testing strategies for modules — Ways to quickly go from idea to ForgeBox
  2. Other Sessions Ge!ing Started with Docker Mark Drew — NPC

    Ballroom Building Progressive Web Apps Using CFML Miles Rausch — Conference Rooms
  3. Who am I? Eric Peterson ! Utah " O.C. Tanner

    " Ortus Solutions # Maintainer of ColdBox Elixir and ForgeBox.io $ Prolific Package Author % 1 wife, 2 kids
  4. /** * Returns the character at a certain position in

    a string. * * @param str String to be checked. * @param pos Position to get character from. * @return Returns a character. * @author Raymond Camden ([email protected]) * @version 1, December 3, 2001 */ function CharAt(str,pos) { return Mid(str,pos,1); } — From CFLib
  5. // instantiate it directly new modules.CFMLParser.File( ... ); // or

    register it in WireBox binder.map( "File@CFMLParser" ).to( "modules.CFMLParser.File" );
  6. What are good candidates for modules? Module Short Description coldbox

    Full MVC Framework testbox Testing Framework javaloader Java Class Loader str String Utility Library cbtemplate-advanced-script Application Template contentbox Full CMS integrated Integration Testing Plugin semver Semantic Versioning Utility Library rollbar Rollbar LogBox appender ses-on-request Automatically sets the SES URL on every request cfcollection Functional Programming Library
  7. Why Use Modules? — Don't repeat yourself — Don't reinvent

    the wheel — Automatic configuration — Benefit from and give back to the community — Semantic Versioning
  8. What do you get in non-ColdBox applications? — Versioning —

    Dependency management — Installation location by convention (or setting)
  9. box.json Describes your project — Version — Dependencies — Module

    type — Installation data — Package scripts — Other metadata
  10. Package Scripts — Run arbitrary scripts with run-script "scripts":{ "generateAPIDocs":"docbox

    generate \ mapping=qb \ excludes=test|ModuleConfig \ strategy-outputDir=docs/apidocs \ strategy-projectTitle=qb", "commitAPIDocs":"run-script generateAPIDocs &&\ !git add docs/apidocs/* && \ !git commit -m 'Updated API Docs'" }
  11. Package Scripts Hook in to CommandBox interception points "scripts":{ "postVersion":"package

    set location='elpete/qb#v`package version`'", "onRelease":"run-script commitAPIDocs && publish", "postPublish":"!git push && !git push --tags" } — Publish with one bump command.
  12. What do you get in ColdBox applications? — Full MVC

    subapplication — Automatic WireBox mapping — Automatic Interceptors — Overridable settings
  13. ModuleConfig.cfc Properties Some of them... Property Purpose name The unique

    name of the module entryPoint The default route into this module. (i.e. api/ v1) autoMapModels Set to true to have WireBox automatically map your models folder dependencies Other dependencies that must be loaded before this one parseParentSettings Set to true to allow overrides from config/ ColdBox.cfc
  14. ModuleConfig.cfc Methods Method Purpose configure() Only interact with this module.

    Use onLoad() for cross-module, cross- framework dependencies. onLoad() When you need the framework loaded first onUnload() Undo what you did in load
  15. component { this.name = "cors"; this.author = "Eric Peterson"; this.webUrl

    = "https://github.com/elpete/cors"; function configure() {} function preProcess( event, interceptData, buffer, rc, prc ) { event.setHTTPHeader( name = "Access-Control-Allow-Origin", value = "*" ); } }
  16. redirectBack box.json (the key parts) { "name":"redirectBack", "version":"1.0.4", "location":"elpete/redirectBack#v1.0.4", "slug":"redirectBack",

    "shortDescription":"Caches the last request in the flash scope to give easy redirects back", "type":"modules", "scripts":{ "postVersion":"package set location='elpete/redirectBack#v`package version`'", "onRelease":"publish", "postPublish":"!git push && !git push --tags" }, "ignore":[ "**/.*", "test", "tests" ] }
  17. redirectBack ModuleConfig.cfc Module Properties this.title = "redirectBack"; this.author = "Eric

    Peterson"; this.webURL = "https://github.com/elpete/redirectBack"; this.description = "Caches the last request in the flash scope to give easy redirects back"; this.version = "1.0.1";
  18. redirectBack ModuleConfig.cfc configure method function configure() { /* * can

    override any of these settings in your `config/ColdBox.cfc` file. * `moduleSettings = { redirectBack = { key = "overridden_key" } };` * Or in CommandBox * `config set modules.redirectBack.key="overridden_key"` */ settings = { key = "last_url", }; interceptors = [{ class = "#moduleMapping#/interceptors/RedirectBack", name = "RedirectBack", properties = {} }]; }
  19. redirectBack ModuleConfig.cfc onLoad method function onLoad() { var helpers =

    controller.getSetting( "applicationHelper" ); arrayAppend( helpers, "#moduleMapping#/helpers/RedirectBackHelpers.cfm" ); controller.setSetting( "applicationHelper", helpers ); }
  20. redirectBack ModuleConfig.cfc onUnload method function onUnload() { controller.setSetting( "applicationHelper", arrayFilter(

    controller.getSetting( "applicationHelper" ), function( helper ) { return helper != "#moduleMapping#/helpers/RedirectBackHelpers.cfm"; } ) ); }
  21. Leveraging WireBox this.autoMapModels = true; Automatically maps all of your

    models to {modelName}@{moduleName}. property name="builder" inject="Builder@qb";
  22. Leveraging WireBox Use the full power of WireBox function configure()

    { binder.map( "DefaultGrammar" ) .to( "#moduleMapping#.models.grammars.MySQLGrammar" ); }
  23. Git Repos Pros — Versioning (via tags) — Can be

    shareable (Public repos) — Also can be private (Private repos) Cons — No semantic version ranges. (Must specify a tag.) — Must specify the full git path (as opposed to a ForgeBox slug).
  24. modules_app Pros — Committed to your git repo — Private

    to your application — Easily contain bits of your application like API versions Cons — No easy reuse outside your project — No versioning
  25. Unit Testing component extends="testbox.system.BaseSpec" { function beforeAll() { include "/root/functions/normalizeToArray.cfm";

    } function run() { describe( "normalizeToArray", function() { it( "returns an array unmodified", function() { var actual = normalizeToArray( [ 1, 2, 3, 4 ] ); expect( actual ).toBe( [ 1, 2, 3, 4 ] ); } ); it( "converts a list to an array", function() { var actual = normalizeToArray( "1,2,3,4" ); expect( actual ).toBe( [ 1, 2, 3, 4 ] ); } ); } ); } }
  26. TravisCI Integration language: java sudo: required jdk: - oraclejdk8 cache:

    directories: - $HOME/.CommandBox env: matrix: - [email protected] - ENGINE=lucee@5 - ENGINE=adobe@2016 - ENGINE=adobe@11 - ENGINE=adobe@10 before_install: - sudo apt-key adv --keyserver keys.gnupg.net --recv 6DA70622 - sudo echo "deb http://downloads.ortussolutions.com/debs/noarch /" | sudo tee -a /etc/apt/sources.list.d/commandbox.list install: - sudo apt-get update && sudo apt-get --assume-yes install commandbox - box install before_script: - box server start cfengine=$ENGINE port=8500 script: - box testbox run runner="http://127.0.0.1:8500/tests/runner.cfm" notifications: email: false
  27. Scaffolding Modules — Create box.json — Create ModuleConfig.cfc — Scaffold

    tests folder — specs folder — runner.cfm — tests/Application.cfc — Copy over .travis.yml file — Create git repo and GitHub repo. And then finally get coding....
  28. Now it is that easy for your modules: box install

    cb-module-template box module scaffold my-awesome-module "It will blow your mind!"
  29. What this does for you: — Create box.json — Create

    ModuleConfig.cfc — Scaffold tests folder — specs folder — runner.cfm — tests/Application.cfc
  30. What this does for you: (continuted) — Copy over .travis.yml

    file — Create git repo and GitHub repo — Create a GitHub token if it doesn't exist — Sets up TravisCI to accept builds — Creates a TravisCI token if it doesn't exist So you can start coding right away