The post belongs to NectarCommerce and Extension Framework Awareness Series
- NectarCommerce Vision
- 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
- Learning from failures: First Experiment at NectarCommerce Extension Approach
- Developing NectarCommerce Extensions
- Building an exrm release including NectarCommerce
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.
Ecto Model Schema Extension
We want to allow Extensions to modify the schema of existing Nectar Models without changing the Nectar Models.
Extensions should be able to add new fields and associations to existing models as and when needed.
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.
Extension which wants to add a virtual field, say special, to Nectar Product Model Schema is a Producer (Service Code).
Nectar Model is a Consumer (Consumer Code) allowing the schema changes through a communication protocol (Library Code)
Letâ€™s begin the journey of incremental changes to bring consumer, service and library code into existence starting from a simple use-case of adding a virtual boolean field, say special, to Nectar Product.
Note: Please refer Introduction to Metaprogramming for more information on Metaprogramming in Elixir
A straightforward way to add a virtual field, say special, to Nectar Product would be adding it directly in Nectar.Product Schema definition, but it requires change in Nectar source. Letâ€™s move to the next step for avoiding any modification to Nectar.Product
We can add a function to Nectar Model Schema to which other extensions can delegate the responsibility of schema changes, see full version here. See Nectar.ExtendProduct example below on how to use it.
Now, with delegation function
extensionsin place, we can work towards providing a way to register the schema changes, see full version here. Please check the usage of Module attributes for same below.
Earlier, Module.put_attribute was used multiple times to define multiple schema changes whereas now we wrapped it in an anonymous function to encapsulate the collection of schema changes through a simple and consistent interface, see full version here. There can be multiple extensions used for different functionality and hence multiple schema changes need to be registered and defined
Now, Nectar.ExtendProduct is getting cluttered with ancillary method definitions. Letâ€™s move it out to another module and use it, see full version here
Letâ€™s further reduce the boilerplate of registering schema_changes module attribute and importing add_to_schema method definition with using callback, see full version here
Reference of schema_changes Module attribute is scattered across Nectar.ExtendProduct and Nectar.ModelExtension so letâ€™s move it out to Nectar.ModelExtension to consolidate the usage via
__before_compile__and definition together, see full version here
With above changes, itâ€™s now possible to define schema changes any number of times, see full version here. Also, schema changes can now be added using
include_methodin Nectar.ExtendProduct without making any changes to Nectar.Product.
Check all the revisions at once, here
Now, in the final version, you can easily find the three components, consumer, service and library code, as desired in extensible system
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 !!