Sinatra: using partials with xml builder

After working mostly with Java for last few years I am back to using Ruby as a main language for my every day work. I have to say just thinking of that makes me smile :). We use Sinatra to cover our web needs and I love it.
Recently I had to generate some outbound xml feeds and wanted to reuse builder templates. Following is my take on a builder partial implementation :

module Sinatra
  module BuilderHelper
    def helper_modules
      @helper_mods ||= Sinatra::Application.ancestors.select{|m| m.name =~ /Helper/}
    end

    def builder_partial(template, xml, locals = {}, helper_mods = nil)
      template = "#{template}.builder" unless "#{template}" =~ /[.]builder$/
      helper_mods ||= self.helper_modules

      class << (context = OpenStruct.new({:xml => xml}.merge(locals))); self; end.send(:include, *helper_mods)

      File.open(File.join(settings.views, "#{template}")) do |f|
        eval f.read, context.send(:binding)
      end
    end
  end

  helpers BuilderHelper
end

As you can see, I am using OpenStruct as a context object in order to limit variable scope to the locals being passed to the partial… If you use other Sinatra helper modules and follow a naming convention, helper_mod will find it and make them available to the builder template…
This is a pretty simple helper module… but I am hoping it will save somebody time.

Advertisements

JQuery: Collect input data

Working on a simple data entry app I’ve ran into a need to collect data from multiple rows of input fields in order to post json data back to the server. Following is a simple jquery plugin, that in combination with few extra html attributes allows to collect data and convert it into json:

(function( $ ){
  $.fn.collectFields = function(fieldSelector) {
	var convert = function(type, value) {
		switch (type) {
			case "int"     : return value ? parseInt(value) : 0;
			case "float"   : return value ? parseFloat(value): 0.0;
			case "boolean" : return Boolean(value);
			default        : return value;	
		}
	};

	var result = [];
	this.each(function() {
	  	var fields = {};
		$(this).find(fieldSelector).each(function(){
			var name = $(this).attr('name');
			if (name) {
				fields[name] = convert($(this).attr("json-type"), $(this).val());
			}
		});
		result.push(fields);
	});
	return result;

  };  
})( jQuery );

As you can see, I am using “json-type” attribute to indicate a type of the data field. In html it looks something like the following:


<tr class="player">
  <td><input type="hidden" id="id__5" name="_id" value="5" class="field" /></td>
  <td><input type="text" id="number__5" name="number" value="23" class="field" json-type="int"/></td>
  <td><input type="text" id="name__5" name="name" value="Some Good Player" class="field"/></td>
</tr>
...

Script to collect data for all players would look something like this:

<script>
  var players = $(".player").collectFields(".field");
</script>

Sinatra request headers helper

It is pretty simple, but here is an example of getting request headers from the Rack Environment in a Sinatra application :

require 'rubygems'
require 'sinatra'

helpers do
  def request_headers
    env.inject({}){|acc, (k,v)| acc[$1.downcase] = v if k =~ /^http_(.*)/i; acc}
  end  
end

get '/headers' do
  puts request_headers.inspect
 end

request_headers helper will filter all HTTP headers and downcase names.

Easy Mocking in Erlang

Working on yarmo and trying to do test driven development I ran into need to mock some modules to avoid need for hitting database every time. After a bit of trying and errors I ended up using pretty simple set up based on parametrized modules. Basic idea is to pass a proplist, with mock responses for methods I am trying to mock, into the module as module parameter and have methods look it up:

-module(mock_store, [MockStore]).
-export([read/1, create/1]).

read(Key) ->
	callback(read, [Key]).

create(Key, Document) ->
	callback(create, [Key, Document]).

%% Helper Functions

callback(Name, Args) ->
	case proplists:lookup(Name, MockStore) of
		none -> undefined;
		{Name, Fun} when is_function(Fun) -> Fun(Args);
		{Name, Value} -> Value
	end.

The callback is pretty simple, but allows to pass in ether mock result or a function, which will generate response based on parameters, passed to the method.
Now I can mock read/create in the test as following:

test_mod(StoreOptions) ->
	Store = mock_store:new(StoreOptions),
	yarmo_destination:new(Store).

....

Mod = test_mod([{read, not_found}]),
.....

Mod = test_mod([{read, fun([Key]) -> ?assertEqual("sample", Key), Doc end}])

Nothing special, but so far it is helping me to keep my tests from hitting real storage 🙂

More fun with Erlang

I am working on a prototype of an application that needs to proxy client HTTP requests to different origins. I needed a function that will filter HTTP headers before I forward them. Application is in Erlang, but since I’ve been a big Ruby fan for a while now… Here is a comparison of possible implementations:

Ruby:

  NO_FORWARD = ['Host', 'Content-Length', 'Accept-Encoding']
  
  def filter_headers(headers)
      headers.inject({}) do |result, (name, value)|
         result[name.to_s] = value unless NO_FORWARD.include?(name.to_s)
         result
      end
  end

Now, same code … but in Erlang:


filter_headers(Headers) ->
NoForward = ['Host', 'Content-Length', 'Accept-Encoding'],

Pred = fun({Name, Value}, L) ->
case lists:member(Name, NoForward) of
false ->
Key = case is_atom(Name) of
true -> atom_to_list(Name);
false -> Name
end,
[{Key, Value} | L];
true -> L
end
end,

lists:foldl(Pred, [], Headers).

I think given a bit more effort, each code sample might be even more compact, but even what I have looks pretty readable 🙂

Easy Helpers for Sinatra

I am spending more time with Sinatra apps. I think it is a perfect framework to start application with. What I like about Sinatra the most is how easy it is to extend it. Recently I was building a small app, that processes user provided templates and was looking for an easy way to add template components (helpers) to give customers a sort of DSL to work with. What I ended up doing was the following:

 
module Components
  
  components_path = File.expand_path(File.dirname(__FILE__) + '/components')

  files = Dir.new(components_path).select{|f| f =~ /.*\.rb/ } || []
  files.each do |f|
    body = File.new(File.join([components_path, f])).read
    name = File.basename(f, '.rb').capitalize + "Helper"
    module_eval <<-"end;"
      module #{name}
        #{body}
      end  
    end;
    Sinatra.helpers(const_get(name))
  end

end

Link to the file: http://gist.github.com/141220

As you can see this pretty simple Ruby magic allows me to put my “components” into a subdirectory and add them all as Sinatra helpers. Since the body of the component is wrapped into a module, component development becomes very easy. Following code, once saved into components directory will add a search helper to your app:

def search(options = {})
......
end

Pretty simple, but still fun 🙂

Ruby wrapper for Google App Engine URL Fetch service

I am still playing with my Sinatra app, running on GAE. Just in case if do that too… and might need to fetch some external data, following is a wrapper code I’m using :

require 'java'

module UrlFetch
  
  module UF
    import java.net.URL;
    import java.net.URLEncoder;    
    import com.google.appengine.api.urlfetch.HTTPHeader
    import com.google.appengine.api.urlfetch.HTTPMethod
    import com.google.appengine.api.urlfetch.HTTPRequest
    import com.google.appengine.api.urlfetch.HTTPResponse
    import com.google.appengine.api.urlfetch.URLFetchService
    import com.google.appengine.api.urlfetch.URLFetchServiceFactory
    
    Service = URLFetchServiceFactory.getURLFetchService()
  end
  
  module InstanceMethods
    def fetch_url(options = {})
      self.class.fetch_url(options)
    end

  end

  module ClassMethods
  
    # = Fetch URL proxy
    # === Accepted options:
    # :url     - request url
    # :method  - HTTP method ('get', 'post' ..)
    # :headers - hash of request headers
    # :params  - request params. Only valid if the method is post
    #
    # === Response:
    # Rack stype responce:
    # [response_code, headers, body]
    
    def fetch_url(options = {})
      return nil unless (options[:url])
      
      url = UF::URL.new(options[:url])
      request = UF::HTTPRequest.new(url, UF::HTTPMethod.valueOf((options[:method] || 'get').upcase))
      
      options[:headers].each{|name, value| request.addHeader(UF::HTTPHeader.new(name, value))} if options[:headers] && options[:headers].is_a?(Hash)
      
      if options[:method] == 'post' && options[:params]
        payload = options[:params].collect{|name, value| "#{UF::URLEncoder.encode(name, 'UTF-8')}=#{UF::URLEncoder.encode(value, 'UTF-8')}" }
        request.setPayload(payload.to_java_bytes)
      end
      response = UF::Service.fetch(request)
      [
        response.getResponseCode,
        response.getHeaders().inject({}){|hash, header| hash[header.name] = header.value; hash },
        (String.from_java_bytes(response.getContent) if response.getContent)
      ]
    rescue => e
      [500, {}, e.to_s]
    end

  end
  
  def self.included(base)
    base.send :include, InstanceMethods
    base.send :extend,  ClassMethods
  end
  
end

I hope this is will save some typing 🙂

Here is a link to GitHub gist: git clone git://gist.github.com/111006.git gist-111006