(loop for path in load-path do (byte-recompile-directory path 0))
To execute this from emacs: M-x eval-expression
(loop for path in load-path do (byte-recompile-directory path 0))
To execute this from emacs: M-x eval-expression
While writing a REST service (in JAX-RS implementation), I needed to create and modify resources using JSON as the exchange format. The client-side is written in GWT. In GWT when you want to convert a string to a Javascript object, you can use eval and it’s done.
But what about serializing objects into strings? Now supposing you’re sending data from a FormHandler, in the onSubmit method, you may want to set the values in the Javascript object and later send it as a string with RequestBuilder.sendRequest. GWT-Ext provides tools for the task, but maybe you’re not using them, so your question at this point would be: must I code a JSON tokenizer in Java for this? (yeah, you’re org.json library won’t work)
No, not at all, since you can use any external JS library from GWT. So go ahead and grab a normal Javascript to do the job, in example, Json2.js. Put the file in a directory reachable by the webrowser and load it with a script tag. The last step is writing an interface for your java code:
import com.google.gwt.core.client.JavaScriptObject;
public class JSON {
protected JSON() {}
public static final native String encode(JavaScriptObject object) /*-{
/** if you use a different library, check the method beneath **/
return $wnd.JSON.stringify(object);
}-*/;
public static final native <T> T decode(String json) /*-{
return eval('('+json+')');
}-*/;
}
When you want to refer to an external Javascript object, you must prefix the access to the object by $wnd. This way you tell GWT that your object is located in Window. Anyway, if you forgot to add it you’d have a compilation error, so you’d spotted it quickly. You have more information about the JNSI interface in this page.
Note: In the decode method, there’s a generic been used so the compiler can guess the type of the left side when you do an assignation. So take care to which type you’re doing the assignation before you get a conflict type error.
When I was starting up this blog, I missed a plugin which would work in the server-side to show the public repositories I had in GitHub, as I didn’t find anything, I wrote my own.
The steps I followed:
guillermo:typo$ script/generate plugin github_sidebar
guillermo:typo$ vim github_sidebar.rb
Typo has a nice class to inherit by sidebars, so you’ve little work to do. By the way, if you want to see how other plugins implement sidebars, like the tags sidebar, or the amazon’s one, you have them in RAILS_ROOT/vendor/plugins. Let’s code!
require 'net/http'
require 'uri'
class GithubSidebar < Sidebar
display_name "Github" #the name of the plugin in the plugins' list
description "Shows all the public projects in GitHub for a user"
# next are the preferences, they're saved in the database, but you don't have to mess around with ActiveRecord
# the first symbol, will create an attribute accessor with such name
setting :title, 'Github projects', :label => "Sidebar title"
setting :user, 'githubuser', :label => "Github username"
setting :refresh, '300', :label => "Time to purge the cache"
USER_INFO_BASE = "http://github.com/api/v1/json/"
def repositories
data = retrieve_reposdata
return [] if data.length < 2
user = JSON.parse data
user["user"]["repositories"]
end
private
def retrieve_reposdata
now = Time.now.to_i
timestamp = Rails.cache.read('GithubSidebar_repos_stamp').to_i || refresh.to_i
data = Rails.cache.read('GithubSidebar_repos')
unless data and (now - timestamp) < refresh.to_i
final_url = USER_INFO_BASE + user
response = Net::HTTP.get_response(URI.parse(final_url))
data = response.body
Rails.cache.write 'GithubSidebar_repos', data
Rails.cache.write 'GithubSidebar_repos_stamp', now.to_s
end
data
end
end
If you take a look to retrieve_reposdata method, instead of saving the ruby object in the cache, it’s saved the string sent by GitHub (more information about the GitHub Api). This is because most backends just store strings but not objects.
The timeout is saved in a different key because I couldn’t find a way to specify the timeout for an item.
require 'github_sidebar'
GithubSidebar.view_root = File.dirname(__FILE__) + "/views"
Two things to take care about: our model will be in scope as sidebar independently how we name our model’s class namesidebar and we must call our view content.rhtml.
So we create the views folder in our plugin’s directory and edit views/content.rhtml:
<h3><%= sidebar.title %></h3> <ul id="github_repos"> <%- sidebar.repositories.each do |repo| %> <li><a href="<%= repo["url"] %>" title="<%= repo["description"] %>"><%= repo["name"] %></a></li> <%- end %> </ul>
You’re done. Now just restart your application server.
If you’re too lazy to follow the steps above and you just want to use it, you can grab it from GitHub:
guillermo:typo$ script/plugin install git://github.com/guicifuentes/typo-github-sidebar.git