Creating an App that Supports Communities

Prerequisites:

  1. Install all of the necessary rulesets for communities.

  2. Set up a Manifold instance that supports communities

A guide to doing both of these can be found here.

The Process:

We are going to alter a ruleset that already exists to support communities. We are going to work on the io.picolabs.journal app. Here is what the ruleset looks like before we modify it:

ruleset io.picolabs.journal { meta { shares __testing, getEntry } global { __testing = { "queries": [ { "name": "__testing" } , { "name": "getEntry", "args": [ "title" ] } ] , "events": [ { "domain": "journal", "type": "new_entry", "attrs": [ "title", "content" ] } , { "domain": "journal", "type": "delete_entry", "attrs": [ "timestamp" ] } , { "domain": "journal", "type": "edit_entry", "attrs": [ "timestamp", "newContent" ] } ] } getEntry = function(title) { (title) => ent:entries.filter(function(x){ x{"title"} == title })[0] | ent:entries; } app = {"name":"journal","version":"0.0"/* img: , pre: , ..*/}; bindings = function(){ { //currently no bindings }; } } rule discovery { select when manifold apps send_directive("app discovered...", {"app": app, "rid": meta:rid, "bindings": bindings(), "iconURL": "https://image.flaticon.com/icons/svg/201/201642.svg"} ); } rule new_entry { select when journal new_entry pre { entry = { "timestamp" : time:now(), "title" : event:attr("title"), "content" : event:attr("content") } } always { ent:entries := ent:entries.defaultsTo([]).append(entry); } } rule delete_entry { select when journal delete_entry pre { timestamp = event:attr("timestamp"); toDelete = ent:entries.filter(function(x) { x{"timestamp"} == timestamp })[0]; toDeleteIndex = ent:entries.index(toDelete); } if (toDelete == -1) then noop(); notfired { ent:entries := ent:entries.defaultsTo([]).splice(toDeleteIndex, 1); } } rule edit_entry { select when journal edit_entry pre { newContent = event:attr("newContent"); timestamp = event:attr("timestamp"); toChange = ent:entries.filter(function(x) { x{"timestamp"} == timestamp })[0]; } if (toChange == -1) then noop(); notfired { ent:entries := ent:entries.defaultsTo([]).map(function(x){ (x == toChange) => x.put("content", newContent) | x; }) } } }

The first thing we’ll do is add in our intents in the global block:

intents = [ { "domain": "journal", "type": "new_entry", "attrs": ["title", "content"], "description": "Adds a journal entry to each thing in a community for some reason" } ];

The intents let the community pico know which rules can be raised by a community. We share the domain, type, attributes, and a description. We can share as many domains and types as we want with the community. The specific rule we’re sharing with the community will allow the community to make a new journal entry.

The community gets the intents by raising a publish_intent rule in each thing in the community. We need to create this rule inside our journal app like this:

rule publish_intent { select when community publish_intent foreach sub:established().filter(function(x){x{"Tx_role"} == "Community_Community"}) setting (x) pre { toSend = {}.put(x{"Rx"}, intents); } event:send({"eci": x{"Tx"}, "domain": "community", "type": "accept_intent", "attrs": { "intents" : toSend }}) }

Now create a thing in your manifold instance with our journal app installed. Add it to a community, and try to raise the new entry rule from the community!

Copyright Picolabs | Licensed under Creative Commons.