Permalink
Browse files

basic implementation

  • Loading branch information...
0 parents commit b5e0da4a90e5fdae1b6be507303a40002d57ab16 @paraseba committed May 28, 2010
Showing with 115 additions and 0 deletions.
  1. +4 −0 .gitignore
  2. +15 −0 README
  3. +4 −0 project.clj
  4. +3 −0 script/config_repl.clj
  5. +5 −0 script/repl
  6. +44 −0 src/resource_url/core.clj
  7. +40 −0 test/resource_url/core_test.clj
@@ -0,0 +1,4 @@
+pom.xml
+*jar
+lib
+classes
@@ -0,0 +1,15 @@
+# resource-url
+
+FIXME: write description
+
+## Usage
+
+FIXME: write
+
+## Installation
+
+FIXME: write
+
+## License
+
+FIXME: write
@@ -0,0 +1,4 @@
+(defproject resource-url "0.1.0-SNAPSHOT"
+ :description "FIXME: write"
+ :dependencies [[org.clojure/clojure "1.2.0-master-SNAPSHOT"]
+ [org.clojure/clojure-contrib "1.2.0-SNAPSHOT"]])
@@ -0,0 +1,3 @@
+(require 'clojure.contrib.repl-utils)
+(set! *print-length* 500)
+(clojure.contrib.repl-utils/add-break-thread!)
@@ -0,0 +1,5 @@
+#!/usr/bin/env bash
+
+CLASSPATH=`lein classpath`
+rlwrap java -Xmx1G -cp $CLASSPATH clojure.main -i script/config_repl.clj -r
+
@@ -0,0 +1,44 @@
+(ns resource-url.core
+ (:import (java.net URLEncoder))
+ (:require
+ [clojure.contrib.string :as s]
+ [clojure.contrib.except :as exc]))
+
+
+(defn url-encode-str [s] (URLEncoder/encode (s/as-str s) "UTF-8"))
+
+(defn url-encode-map [m]
+ (s/join "&"
+ (map
+ (fn [[k v]]
+ (str (url-encode-str k) "=" (url-encode-str v)))
+ m)))
+
+(defn url [parts & objs]
+ (let [[ev-parts params] (reduce
+ (fn [[out vals] part]
+ (if (string? part)
+ [(conj out part) vals]
+ (if (first vals)
+ [(conj out (part (first vals))) (next vals)]
+ (exc/throw-arg "Can't generate url for parts %s from %d objects" parts (count objs)))))
+ [[] objs]
+ parts)
+
+ params (apply hash-map params)
+ anchor (url-encode-str (:anchor params))
+ params (dissoc params :anchor)
+ base (map #(s/replace-first-re #"/+$" "" (s/as-str %)) ev-parts)
+ base (s/join "/" base)
+ base (if (empty? params)
+ base
+ (str base "/?" (url-encode-map params)))]
+
+ (if (s/blank? anchor)
+ base
+ (str base "#" anchor))))
+
+(defmacro named-url [name & parts]
+ `(defn ~name [& args#]
+ (apply url (vector ~@parts) args#)))
+
@@ -0,0 +1,40 @@
+(ns resource-url.core-test
+ (:use [resource-url.core] :reload-all)
+ (:use [clojure.test]))
+
+(deftest urls-without-parameters
+
+ (named-url news-path "news")
+ (named-url best-news-path "news" "best")
+ (named-url best-news-with-slash-path "news/" "best//")
+
+ (is (= (news-path) "news"))
+ (is (= (best-news-path) "news/best"))
+ (is (= (best-news-with-slash-path) "news/best"))
+
+ (testing "with anchor"
+ (is (= (news-path :anchor 1) "news#1"))
+ (is (= (best-news-path :anchor "this is my anchor") "news/best#this+is+my+anchor"))))
+
+(deftest urls-with-parameters
+
+ (named-url user-path "users" :id)
+ (named-url user-images-path "users" :id "images")
+ (named-url user-images-with-slashes-path "users//" :id "images///")
+ (named-url user-image-path "users" :id "images" #(:title %))
+
+ (testing "no extra parameters"
+ (is (= (user-path {:id 1}) "users/1"))
+ (is (= (user-images-path {:id "foo"}) "users/foo/images"))
+ (is (= (user-images-with-slashes-path {:id :foo}) "users/foo/images"))
+ (is (= (user-image-path {:id :foo} {:title :bar}) "users/foo/images/bar"))
+ (is (= (user-image-path {:id :foo} {:title "bar//"}) "users/foo/images/bar")))
+
+ (testing "with extra parameters"
+ (is (= (user-path {:id :foo} "sort" "recent" :value 1) "users/foo/?value=1&sort=recent"))
+ (is (= (user-image-path {:id :foo} {:title :bar} :value 1) "users/foo/images/bar/?value=1"))
+ (is (= (user-path {:id :foo} "sort" "the recent" :value 1) "users/foo/?value=1&sort=the+recent")))
+
+ (testing "with anchor"
+ (is (= (user-path {:id :foo} :anchor :my-id "sort" "the recent" :value 1) "users/foo/?value=1&sort=the+recent#my-id"))))
+

0 comments on commit b5e0da4

Please sign in to comment.