Universal url mounting point for rack applications
https://github.com/hassox/url_mount
22daa83b53
Fixes NoMethodError for add_bundler_dependencies |
||
---|---|---|
lib | ||
test | ||
.document | ||
.gitignore | ||
Gemfile | ||
Gemfile.lock | ||
LICENSE | ||
README.textile | ||
Rakefile | ||
url_mount.gemspec |
README.textile
h1. UrlMount UrlMount is a universal mount point designed for use in rack applications. It provides a simple way to pass a url mounting point to the mounted application. This means that when you mount an application in the url space, it's a simple call to url to get the mount point of where the application is. h2. Example Say you mount an application at "/foo/bar" <pre><code>router.mount("/foo/bar").to(my_app) # behind the scenes, the routers mount method should do this: if my_app.respond_to?(:url_mount=) mount_point = UrlMount.new("/foo/bar") my_app.url_mount = mount_point end </code></pre> This means that if an application can handle a url_mount, you give it one. This then allows the +my_app+ applciation, to know where it's mounted. Generating a url is now as simple as <pre><code>File.join(url_mount.url, "/local/url/path")</code></pre> The benefit of this is that all routers or applciations can make use of this. If used, it can act as a universal glue between rack applications where parent apps can let the child applications know where they're mounted so the child applciations can have a chance of generating full routes, even when they're not in the request path. h3. Show me the code url_mount is made to be used with many routers that are currently available. <pre><code> # simple string mounting point mount = UrlMount.new("/foo/bar") mount.url == "/foo/bar" # Mount Point including variables mount = UrlMount.new("/foo/:bar", :bar => "bar") mount.url(:bar => "something") == "/foo/something" mount.url #=> Raises UrlMount::Ungeneratable because a required variable was not found mount.required_variables == [:bar] # UrlMount::Ungeneratable raised when a route cannot be generated without options no_mount = UrlMount.new("/foo/:bar") # fails because the mount point cannot be generated with no options # Mount Point including optional variables mount = UrlMount.new("/foo/:bar(/:baz)", :bar => "bar") mount.url(:bar => "doh") == "/foo/doh" mount.url(:bar => "doh", :baz => "hah") == "/foo/doh/hah" mount.required_variables == [:bar] mount.optional_variables == [:baz] # Mount Point with defaults mount = UrlMount.new("/foo/:bar(/:baz)", :bar => "default_bar") mount.url == "/foo/default_bar" mount.url(:baz => "baz_value") == "/foo/default_bar/baz_value" mount.url(:bar => "other_bar") == "/foo/other_bar" # Using procs for mount point defaults mount = UrlMount.new("/foo/:bar", :bar => proc{"some_bar"}) mount.url == "/foo/some_bar" # Nested mounting point mount_parent = UrlMount.new("/foo/bar") mount_child = UrlMount.new("/baz/:barry) mount_child.url_mount = mount_parent mount_parent.url == "/foo/bar" mount_child.url(:barry =>"barry_value") == "/foo/bar/baz/barry_value" </code></pre> Considering that UrlMounts can be nested, when you mount an application you should do it something like this. <pre><code> if mounted_app.respond_to?(:url_mount=) mount = UrlMount.new(path, deafult_options) # If this app is mounted, add this apps mount point to # the mount point for the child app mount.url_mount = self.url_mount if self.url_mount mounted_app.url_mount = mount end </code></pre> h2. Generating routes When you generate routes, you can see which variables will be used by the mount point, so that you can remove these options from the options hash. otherwise, depending on the generating application, you may get query string options. <pre><code> url = UrlMount.new(/"foo/:bar(/:baz)", :bar => "some_bar") generation_options = {:baz => "baz", :bar => "bar"} mount_point = url.url(generation_options) # We can now at this point ask the mount point what variables it will use if present. url.variables.each{|v| generation_options.delete(v)} # use the generation_options now without the mount_point variables to interfere with a query string </code></pre> h2. Callbacks When generating the routes, you can provide one or more callbacks to the mount point. Inside the callbacks you can set options for the routes based on the Rack request. <pre><code>mount = UrlMount.new("/foo/:bar") do |env, opts| opts[:bar] ||= "my_bar" end mount.url(env) # Rack::Request === env #=> /foo/my_bar </code></pre> NOTE: callbacks are only run when a rack environment is given to the url method h2. Note on Patches/Pull Requests * Fork the project. * Make your feature addition or bug fix. * Add tests for it. This is important so I don't break it in a future version unintentionally. * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull) * Send me a pull request. Bonus points for topic branches. h2. Copyright Copyright (c) 2010 Daniel Neighman. See LICENSE for details.