View Source The State and Methods

The State

In Tamnoon, every app keeps a state. The state is a map consisting of multiple variables, which can be read and changed by the app. It can be thought of similarly to an agent. To set the initial state, change Tamnoon's child_spec in your supervision tree as such:

{Tamnoon, [[initial_state: %{msgs: [], name: "", curr_msg: ""}]}

As you can see, we are storing the user's name, the message the user is currently typing, and the messages. In addition, instead of providing a map, we can provide a function that returns a map. The function will be reran for each new client, keeping the initial state updated.

Note: The state should not have string keys, only atoms.

Methods

When we want something to happen, we need to trigger methods. Methods are the client's way of interacting with the server. Tamnoon comes with a few different built-in methods for interacting with the state and for implementing PubSub functionality (more on that later):

  • get: Returns the value of the requested variable to the client.

  • update: Sets the value of the requested variable to the the value specified in the request, and returns the new value to the client.

  • sync: Returns all of the state to the client.

  • sub and unsub: Subscribe and unsubscribe the client from the requested channel.

  • pub: Sends the request under the "action" field to all the other clients in the requested channel.

  • subbed_channels: Returns a list of the channels the client is currently subscribed to.

Tamnoon abstracts this whole process, so you don't need to worry about it. However, FYI: methods are triggered by the client sending a json object to the server. The update and get methods both expect a field with the key "key", which is a name of a variable in the state. update also expects a field with the key "val" which is the new value of the variable.

Custom Methods

You may also create additional methods if you wish. To do so, you need to make a methods module. Make a file named "methods.ex" inside "lib", and add the following content to it:

defmodule TamnoonChatroom.Methods do
  import Tamnoon.MethodManager

  defmethod :log do
    IO.inspect(req)
    IO.inspect(state)
    {nil, state}
  end
end

Here we are utilizing the Tamnoon.MethodManager.defmethod/2 macro, imported by the use Tamnoon.Methods line. A method can access the state and req variables, and needs to return a tuple containing the value to return to the client (usually a map) and the updated state.

Before we can test it, we need to add the module to our methods modules. Inside your application.ex, change the start function as such:

def start(_type, _args) do
    children = [
      {Tamnoon, [[initial_state: %{msgs: [], name: "", curr_msg: ""},
      methods_modules: [TamnoonChatroom.Methods]]]}
    ]
    # ...
  end
end

Note: Tamnoon.Methods will be automatically added to the methods modules list.

To test it, let's create a button to trigger the method. add the following to your "app.html.heex" file:

<button onclick=@log>push me!</button>

For now, don't worry about the onclick=@log part. That is Tamnoon HEEx, which we will go over in the next guide. Once you restart the server and reload the page, you should see the following output on your console:

%{
  "element" => "<button class=\" tmnnevent-onclick-log\">push me!</button>",
  "method" => "log",
  "val" => ""
}
%{name: "", msgs: [], curr_msg: ""}

We can now move on to Tamnoon HEEx, which will allow you to interact with the server in real-time.