Search the API Reference:
My First Acre App
So, you're intrigued by Acre and you want to start playing with it but you don't know how to start? Great, this tutorial is for you.
What you need to start
To start you only need a modern web browser, that's it, you don't have to install anything: Acre is an application hosting environment that you interact with directly thru your browser and runs your code directly on our servers.
This tutorial assumes that you're familiar with HTML and Javascript. Don't worry if you don't know much about Freebase or its query language MQL or its APIs as this tutorial won't require them.
Let's dive right in
- go to http://acre.freebase.com/
- sign in if you aren't already signed in Freebase (or, sign up if you don't already have a freebase account)
- create a new acre app and type 'test' in both fields (or chose whatever name you want and whatever URL prefix, but you can easily change them both later)
- a new acre app with a single 'index' template file has been created for you
- click the 'view with console' button on the top right of the page to view the result of the execution of your template
- a new tab (or windows, depending on your browser) is displayed that shows you the results of that template
Note how the top part of this new view page contains a 'console' that you can use to obtain debugging information about the execution of your pages... and you can write to it from your scripts or templates with the 'console' object, just like you would do with Firebug if your javascript page was running on the client side).
Server Side Javascript Hello World
The default index template is pretty unimpressive as it looks like any other HTML page, so let's add a little bit of spice to it.
Where it says:
<!-- YOUR CODE GOES HERE --> <i>This app doesn't do anything (yet).</i>
change it to
<acre:script>var message = "Hello, World!"</acre:script> <p>${message}</p>
and click again "View with Console" (or refresh the tab/window that you had before).
You'll see the "Hello, World!" message appear: the first line you added uses the <acre:script> tag to incorporate javascript logic inside the template and the second line uses the ${...} to evaluate the value of that javascript variable in place.
Calling Freebase
Now let's do something a little more useful: let's see how we can get a list of Micheal Jackson's music albums and show it as an HTML table.
Replace your scripted hello world line above with the following
<acre:script> var query = [{ "type": "/music/album", "artist": { "id": "/en/michael_jackson" }, "id": null, "name": null, "release_date": null, "sort": "release_date" }]; var query_result = acre.freebase.mqlread(query).result; </acre:script>
where the query variable contains the MQL query that says we want all topics of type /music/album and made by the artist who's freebase ID is /en/michael_jackson, then the null values are basically the 'fill the blanks' parts that Freebase will fill up for you and also we want the results ordered by release_date which by default is 'ascending', so we'll get the oldest albums first (you can use -release_date if you want descending order instead.
The query_result variable contains the result of the query, directly as a javascript array. Acre templates (also known as MJT templates, pronounced 'midget') provide a simple and effective way to iterate over javascript arrays and generate HTML content like this
<table> <tr acre:for="album in query_result"> <td>${album.name}</td> <td>${album.release_date}</td> </tr> </table>
Place that in your template and hit 'view with console' again and you'll see a list of all Micheal Jackson's albums that Freebase knows about.
Avoiding Missing values
If you try the code above, Acre will signal with red text if values are undefined or null, but that might not be the result you want. One way to fix this is to use conditionals, like this
<td acre:if="album.release_date">${album.release_date}</td>
which tells acre to generate the <td> element in the results only if the album.release_date value is present. You can also decide to do something else in case the value is missing, for example
<td acre:if="album.release_date">${album.release_date}</td> <td acre:else="">N/A</td>
Linking back to Freebase's Edit View
One useful feature might be to link back to the Freebase edit interface for a given topic to allow the user to enter the data that Freebase is currently missing, here is how: change the first <td> line of your acre:for loop in:
<td><a href="http://www.freebase.com/edit/topic${album.id}">${album.name}</a></td>
where you're basically using the album id to send the user to its edit view.
Components in Acre Apps
One very nice feature Acre offers is the ability to fragment your app into pieces that can be more easily reused later (or by other apps). One of the problems with the template we built so far is that the MQL query is built right into the template and cannot be reused. To fix this, we need to take it out into its own file and tell the template to make use of it.
Here is how to do it:
- click the "new file" button on the top left side of the app editor window (on the left of the 'save' button)
- in the dialog that shows up, select "query" from the radio button and type "albums" as the name of the query
- a new file was created named "album" and placed in the 'queries' section on your left sidebar
Note how the app editor editing interface has changed for the MQL queries, this is a special 'query editor' that can help you pick the right identifiers for schemas and topics. Type the previous MQL query that we used to get Michael Jackson's albums in there
[{ "type": "/music/album", "artist": { "id": "/en/michael_jackson" }, "id": null, "name": null, "release_date": null, "sort": "release_date" }]
note that MQL is always a JSON object so we had to remove the var query = beginning part. Click on the run button at the bottom to know if your query worked as expected.
Now save the query and click on the 'index' file in the left sidebar to go back to the main template of your app.
There, we have to change the query part with:
var query = acre.require("albums").query;
which tells Acre to 'import' the 'albums' query, parse it and return the query object already prepared for use.
Generalizing your app
Wouldn't it be nice if this app was able to list not just Michael Jackson's albums but every artist's? Doing that is remarkably easy with acre.
First, we need to have a way to pass the identifier of the artist we want to the app, and for that we'll expect to pass it to the template as a regular HTTP GET parameter named artist and this is what we do to retrieve it:
var id = acre.request.params.artist;
note how we made use of the fact that in javascript params.artist and params['artist'] are actually the same thing and in fact they would both work in this case.
But what happens if the 'artist' parameter is undefined? well, that's easy, we can default to Micheal if that's the case, which can be done as simply as
var id = acre.request.params.artist; if (!id) id = '/en/michael_jackson';
or even more compactly with a nice little javascript trick:
var id = acre.request.params.artist || "/en/michael_jackson";
Now that we have the artist id and we know it to be always defined, we need to alter the MQL query to use that ID as the restriction instead of the value that it already contains.
Acre provides a handy API call that does exactly that and here is how to use it:
var query = acre.require("albums").query; var query_patch = { "artist" : { "id" : id } }; query = acre.freebase.extend_query(query, query_patch);
which basically get the query as-is from the 'albums' file and then 'overloads' some of its internals with the query_patch JSON object that we pass as the second argument to extend_query. The resulting query has the id parameter replaced with the content of the 'id' variable that we previously collected from the HTTP GET parameter.
To make sure, this is the case, you can add
console.log(query);
and inspect the object directly in the console log (which you can expand by clicking on it).
Note how the 'console' view of your template has a text area right next to the URL, that can be used to easily pass parameters directly to your app, so type ?artist=/en/madonna into that text box next to the URL and hit return (or click 'Run'), and Madonna's albums should be appearing.
In case you got a little lost in the process, here is the entire template:
<acre:script> var id = acre.request.params.artist || "/en/michael_jackson"; var query = acre.require("albums").query; var query_patch = { "artist" : { "id" : id } }; query = acre.freebase.extend_query(query, query_patch); var query_result = acre.freebase.mqlread(query).result; </acre:script> <table> <tr acre:for="album in query_result"> <td><a href="http://www.freebase.com/edit/topic${album.id}">${album.name}</a></td> <td acre:if="album.release_date">${album.release_date}</td> <td acre:else="">N/A</td> </tr> </table>
Completing the Interaction
We can't really expect people to discover the fact that the template reacts to the presence of the 'artist' parameter, so we should make it more obvious: the simplest way is to add a form field by addind this HTML before the <table> tag:
<form action="" method="GET"> Artist ID: <input id="artist" type="text" name="artist" value="$id"/> </form>
Now you can type the freebase ID of the artist who's albums you want to list directly from the page.
Completing your app with Freebase Suggest
But we can't really expect people to know the Freebase identifiers for all musical artists they are interested in, can we? This is where Freebase Suggest comes to the rescue.
Freebase Suggest is a jQuery plugin that we wrote to turn a simple input box like the one we used above into a powerful tool to search for particular topics and resolve their Freebase identifiers.
Let's see how to use it.
First, being a jQuery plugin, we need to load jQuery into the app, then the javascript library for Freebase Suggest and its CSS stylesheets. To do this add the following fragment right below your <html> tag:
<head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script type="text/javascript" src="http://freebaselibs.com/static/suggest/v0.9/suggest.min.js"></script> <link rel="stylesheet" type="text/css" href="http://freebaselibs.com/static/suggest/v0.9/suggest.min.css"> </head>
Now we've linked jQuery and Freebase Suggest into your template so that they will be lodaded by your browser when it loads the page, but we have associate the Freebase Suggest behavior so that it's executed when the user types into the input field, to do so add the following fragment right below the <link> tag that we just inserted (inside the <head> section)
<script> $(function() { $("#artist").suggest({ "mql_filter": [{ "type": "/music/artist" }] }).bind("fb-select", function(e,data) { $("#artist").val(data.id); $("form").submit(); }).focus(function() { this.select(); }); }); </script>
This deserves a little bit of explaination in case you're not familiar with jQuery. The first line $(function() { and the last one }); basically enclose an initialization function that is executed by the browser on the client side as soon as page is loaded and ready to be manipulated.
Then $("#artist") selects the HTML element with id 'artist' (which is our text input box in the page) and binds a function to the fb-select event (which is implemented by Freebase Suggest). This function is passed the data object that is retrieved by Freebase Suggest and we use it to store the value of the artist id data.id as the value of the input field (which is what $("#artist").val(data.id) does). Then we forcefully submit the form.
The focus part is responsible for selecting the contained text to improve the interaction with the application.
Here is the full template, in case you got lost:
<html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> <script type="text/javascript" src="http://freebaselibs.com/static/suggest/v0.9/suggest.min.js"></script> <link rel="stylesheet" type="text/css" href="http://freebaselibs.com/static/suggest/v0.9/suggest.min.css"> <script type="text/javascript"> $(function() { $("#artist").suggest({ "mql_filter": [{ "type": "/music/artist" }] }).bind("fb-select", function(e,data) { $("#artist").val(data.id); $("form").submit(); }).focus(function() { this.select(); }); }); </script> </head> <body> <acre:script> var id = acre.request.params.artist || "/en/michael_jackson"; var query = acre.require("albums").query; var query_patch = { "artist" : { "id" : id } }; query = acre.freebase.extend_query(query, query_patch); var query_result = acre.freebase.mqlread(query).result; </acre:script> <form id="form" action="" method="GET"> Artist ID: <input id="artist" type="text" name="artist" value="$id"/> </form> <table> <tr acre:for="album in query_result"> <td><a href="http://www.freebase.com/edit/topic${album.id}">${album.name}</a></td> <td acre:if="album.release_date">${album.release_date}</td> <td acre:else="">N/A</td> </tr> </table> </body> </html>
Now you can click "view" and enjoy interacting with your application or tweaking it to make it prettier and/or more useful.