Creating an App that Supports Communities
Prerequisites:
Install all of the necessary rulesets for communities.
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.