module RestResource
  def self.append_features(base)
    super
    base.extend(ClassMethods)
  end
  module ClassMethods
    def rest_resource(model_id, options = {})
      singular_name = model_id.to_s
      class_name  = options[:class_name] || singular_name.camelize
      plural_name   = singular_name.pluralize
      suffix    = options[:suffix] ? "_#{singular_name}" : ""
      
      module_eval <<-"end_eval",__FILE__,__LINE__
        def #{singular_name}_xml
          require 'rexml/document'
          template = <<-end_template
xml.tag!(@obj.class.to_s.downcase,{:id => @obj.id}) {
  @obj.class.content_columns.each { |col|
    xml.tag!(col.name,@obj[col.name])
  }
  @obj.class.reflect_on_all_associations.each { |assoc|
    if assoc.macro == :belongs_to || assoc.macro == :has_one
      rels = [@obj.method(assoc.name).call]
    end
    if assoc.macro == :has_many || assoc.macro == :has_and_belongs_to_many
      rels = @obj.method(assoc.name).call
    end
    rels.each { |rel|
      if rel
        name = rel.class.to_s.downcase
        xml.tag!(name,{:id=>rel.id, :href =>url_for(:only_path=>false,:action => name+"_xml",:id=>rel.id)})
      end
    }
  }
}
end_template
          if request.post?
            xml = REXML::Document.new(request.raw_post)
            @data = {}
            xml.elements.each("/#{singular_name}/*") { |elt| 
              @data[elt.name] = elt.text
            }
            if params[:id]
              @obj = #{class_name}.update(params[:id],@data)
              render(:inline=>template,:type => :rxml,:layout=>false)
            else
              @obj = #{class_name}.create(@data)
              response.headers['Location'] = url_for(:action => '#{singular_name}_xml', :id => @obj)
              return render(:text => "", :status => 201)
            end
          end
          if request.get?
            @obj = #{class_name}.find(params[:id])
            render(:inline=>template,:type => :rxml,:layout=>false)
          end
          if request.delete?
            @obj = #{class_name}.find(params[:id])
            @obj.destroy()
            return render(:text => "", :status => 204)
          end
        end
      end_eval
    end
  end
end
