In the previous installment, we displayed some dynamic
content in our webpage that was loaded from an ets table. Even a
social network themed around The Wire is no fun if you can’t add
your favorite quotes to it. Let’s hook up a form so that we can submit
to post new tweets, and a resource to accept that POST.
Creating tweets
Our HTML file already has portions of a form in it, but let’s add the
ability to select your character.
Now we need some JavaScript to show and hide the “form”, and submit it.
If you refresh the browser and click the button to “POST!”, you should
get an error in the JavaScript console, specifically 405 Method Not
Allowed. This is because our TweetList resource doesn’t accept
POST!
We have two options here, we can modify our existing resource or
create a new resource to handle the form submission. The difference
will be whether we can tolerate the extra logic for accepting the form
amongst the logic for producing a list of tweets, or whether we prefer
to create a resource that only accepts the form. Personally, I could
handle either way (and potentially change my mind later) but I’m going
to choose the latter for clarity and to demonstrate another feature of
Webmachine. Let’s create our new resource!
Now, the whole goal of this resource was to accept POST requests, so
we better allow them.
Now we can talk about what our options are for accepting the form. We
can take two paths: first, we assume the accepting resource always
exists and simply handles the POST in its own way; second, we assume
the resource CREATES new resources, and treat it as a PUT to a new
URI.
The latter way will feel very familiar if you’ve used Rails before,
except that you need to pick the new URI before the request body is
accepted! This trips developers up frequently, but is easy to work
around. Since we already know how to allocate unique identifiers using
monotonic_time, constructing a new unique URI should be
straightforward.
Our first step is to tell Webmachine that our resource doesn’t
exist, that POST means creating a new resource, and that it’s okay
to allow POST when the resource doesn’t exist:
Now we should pick the URI where our new tweet will live. Whether or
not we allow fetching that new URI is another question entirely! We
might revisit that later in the tutorial.
If our application were backed by a database like PostgreSQL, we
could use an SQL query here to fetch the next ID in the table’s
sequence. Instead, we just call monotonic_time. Note how we
capture the generated ID in the resource state for when we insert
the tweet into the ETS table.
We’re submitting application/json from the Ajax request, but
Webmachine doesn’t know that it’s ok to accept it, or what to do with
it when it arrives. Similar to content_types_provided, we can
specify this with the content_types_accepted callback.
Finally, we parse the incoming JSON, extract the fields, and put
the data in the ETS table.
Before our new resource will work, however, we need to dispatch to it!
Since we wanted to use the same URI as the TweetList resource, we
need to make sure that only POST requests make it to the Tweet
resource. This is where a route guard comes in. Route guard functions
take one argument, the req_data we’ve been passing around, and
should return a boolean. If the route is a 4-tuple, with the second
element being a route guard function, that guard will be tested before
dispatching is done (but after the path has matched).
Now reload mix and see if you can post a tweet! (You might need to
reload the page after posting too.)
Up next
In our next and final installment, we’ll learn how to deliver live
updates to the client.