How to… in Cloudfier?

How to make a property or parameter optional?

Specify a multiplicity with 0 as lower bound. In the example below, name is required but dateOfBirth is optional.

class Person
    attribute name : String;
    attribute dateOfBirth : Date[0,1];
end;

How to make a property unique?

Use the id modifier. That makes a property require unique values. Make sure to make it required as well or else the modifier is ignored.

class Person
    id attribute email : String;
end;

How to make a property be editable on creation but not updateable?

Use the readonly modifier. In the example below, the user/client can set the date an issue was reported when the issue is initially created, but not afterwards.

class Issue
    readonly attribute reportedOn : Date;
end;

How to assign a default value to a property or parameter?

Use an initialization expression. In the example below, the severity and reportedOn properties have default values. Note that a default value for a property can be set as a simple literal value, or using a block, any kind of expression. Parameters currently only admit literals as initialization expressions.

class Issue
    attribute severity : Severity := Normal;
    attribute reportedOn : Date := { Date#today() };
end;

How to ensure an action is only executable in some circumstances?

Use a precondition constraint. You can declare as many preconditions you want for an operation, and they all need to be satisfied for the operation to valid.

In the example below, a user/client can only reject an expense if the amount of the expense is higher than 50.

class Expense
    attribute amount : Double;

    operation reject(reason : Memo);
    precondition UnderAutoApprovalLimit { self.amount > 50 }
    begin
        ...
    end;
end;

How to make a property have its value computed based on another property?

You use derived properties. Derived properties are not modifiable by users/clients and are defined via a function that produces a value in terms of other properties. Derived properties are not stored in the database.

The example shows a property isAvailable is defined in terms of the assignee relationship. If an assignee does not exist, the issue is available.

class Issue
    attribute assignee : User[0,1];
    derived attribute isAvailable : Boolean := { self.assignee == null };
    ...
end;

How to prevent child objects from being added directly?

You can prevent create/delete behavior on related collection of objects by marking a collection as readonly. In the example, comments cannot be directly added/removed from an issue. That is handy when you want addition of related objects to be through an action.

class Issue
    readonly attribute comments : Comment[*];

    operation comment(text : Memo);
    begin
        var comment : Comment;
        comment := new Comment;
        comment.commented := text;
        link IssueComments(issue := self, comments := comment);
    end;
end;

How to declare an entity as representing a user role in the system?

Apply the role class modifier.

role class Person
    attribute name : String;
end;

You can have multiple User entities in an application, and then establish different permissions for each role.

How to find the currently logged in user?

Invoke System#user(). Example:

class Issue
    operation addComment(text : Memo);
    begin
        var comment : Comment;
        comment := new Comment;
        comment.user := System#user() as User;
    end;
end;

The cast is required as System#user() has no type.

How to make an action only available to a specific role?

Declare an access constraint based on the role of the logged in user. In the example below, there are two kinds of users. Only company personnel can complete an order.

role class Personnel
    attribute name : String;
end;

role class Customer
    attribute name : String;
end;

class Order
    operation complete()
        allow Personnel call;
    begin
        /* order completion behavior */
    end;
end;

The System#user() call returns the logged in user.

How to link two objects together?

Declare an association between the entities:

association WatchedIssues
    navigable role watchers : User[*];
    navigable role issuesWatched : Issue[*];
end;

then establish the relationship using the link command:

class Issue
    operation addWatcher(userToAdd : User);
    begin
        link WatchedIssues (issuesWatched := self, watchers := userToAdd);
    end;
end;

Tip: you can use the unlink command to break a relationship.

Have your own how-to question?

We will be glad to answer it. Ask it on the support forum or tweet to @cloudfier. See also the REST API and SimpleUI how-tos.