The post belongs to NectarCommerce and Extension Framework Awareness
Extension Framework Game Plan
- Introduction to Metaprogramming
- Ecto Model Schema Extension
- Ecto Model Support Functions Extension
- Phoenix Router Extension
- Phoenix View Extension
- Running Multiple Elixir Apps Together
- Extension Approach Explained
- Developer Experience and Workflow developing Favorite Product Extension
- Developer Experience and Workflow testing Favorite Product Extension
What will be NectarCommerce
Off-the-shelf Opensource E-commerce application for building an online store.
Provides an Extension Framework to support features not included in core as extensions.
Strives for unobtrusive parallel development of NectarCommerce and Extensions
NectarCommerce is committed to providing a ready-to-use e-commerce solution but the definition of 100% is different under different business domains. It aims to solve common use-cases as part of the project and relying on extension framework to tap the rest.
Metaprogramming in Elixir
If you are already familiar and experienced with Elixir Metaprogramming, you can jump toas it lists Metaprogramming resources
and constructs used in upcoming blogs when creating different extension DSL’s.
are excellent resources to get familiar with Metaprogramming:
Understanding Elixir Macros blog
- Understanding Elixir Macros, Part 1 – Basics
- Understanding Elixir Macros, Part 2 – Micro Theory
- Understanding Elixir Macros, Part 3 – Getting into the AST
- Understanding Elixir Macros, Part 4 – Diving Deeper
- Understanding Elixir Macros, Part 5 – Reshaping the AST
- Understanding Elixir Macros, Part 6 – In-place Code Generation
Why another tutorial on an already well-documented metaprogramming topic ?
To revise and refresh something that we would refer time and again when reviewing Model, Router, View extension DSLs
Extension DSLs will be using below constructs to get the job done
Registers an attribute. By registering an attribute
, a developer is able to customize how Elixir will store and accumulate the attribute values.
- Registers an attribute. By registering an attribute
- Puts an Erlang attribute to the given module with the given key and value
that will be invoked before the module is compiled
- It allows us to inject code into the module when its definition is complete
- A hook
Checkout the title
for the usage & context and
in link above
looks and invokes
macro defined in
- Checkout the title
Find the documentation under title
in the link above
, we can automatically disable unquoting while still injecting the desired variables into the tree
- Find the documentation under title
- Ensures the given module is loaded
Invokes the given
with the array of arguments
- Invokes the given
- Recursively escapes a value so it can be inserted into a syntax tree
Metaprogramming pattern as used across extensions
Minimum three parts are needed to create & use an extension effectively:
- Library Code
- Service Code
- Consumer Code
An extension and its use with Nectar can be viewed as Producer / Consumer relationship bound by a communication protocol.
Extensionwhich wants to add a route, say a list of favorites, is a Producer (Service Code)
Nectar Routeris a Consumer (Consumer Code)
allowing the route additions through a communication protocol (Library Code)
defines a macro providing a DSL, say
Collect all definitions provided using DSL from Service code
in Module attribute, say
hook to add a macro extracting all collected definitions from module attribute, as module attributes are cleaned up as compilation completes
Inject generated code into targeting module Consumer code
hook as invoked by
Our aim with these posts is to start a dialog with the Elixir community on validity and technical soundness of our approach. We would really appreciate your feedback and reviews, and any ideas/suggestions/pull requests for improvements to our current implementation or entirely different and better way to do things to achieve the goals we have set out for NectarCommerce.
Enjoy the Elixir potion !!