<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Subdomain Fu's Blog</title>
  <link href="http://actsascommunity.com/projects/subdomain-fu/blog/posts?page=1" rel="self"/>
  <link href="http://actsascommunity.com/projects/subdomain-fu/blog/posts?page=1" rel="alternate"/>
  <id>http://actsascommunity.com/projects/subdomain-fu/blog/posts?page=1</id>
  <updated>2008-06-23 15:11</updated>
  <author>
    <name>Acts_as_community</name>
  </author>
  <entry>
    <title>SubdomainFu: A New Way To Tame The Subdomain</title>
    <link href="http://actsascommunity.com/posts/show/19" rel="alternate"/>
    <id>http://actsascommunity.com/posts/show/19</id>
    <updated>2008-06-23 15:11</updated>
    <author>
      <name>Subdomain Fu</name>
    </author>
    <content type="html">
&lt;div class='htmlized'&gt;&lt;p&gt;Resyndicated from &lt;a href="http://intridea.com/2008/6/23/subdomainfu-a-new-way-to-tame-the-subdomain"&gt;The Intridea Blog&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;An extremely common practice for Rails applications is to provide keyed&lt;br /&gt;
access through subdomains (i.e. http://someaccount.awesomeapp.com/). However,&lt;br /&gt;
there has never been a real unified convention for handling this functionality.&lt;br /&gt;
&lt;a href="http://github.com/rails/account_location/tree/master"&gt;DHH&amp;#8217;s Account Location&lt;/a&gt;&lt;br /&gt;
works for some circumstances but is more tailored for a &lt;a href="http://www.basecamphq.com/"&gt;Basecamp&lt;/a&gt; domain model&lt;br /&gt;
(i.e. the app is on a separate domain from all other functionality, so you&lt;br /&gt;
can always expect a subdomain) than the more common usage of one domain only.&lt;/p&gt;
&lt;p&gt;SubdomainFu aims to provide a simple, generic toolset for dealing with subdomains&lt;br /&gt;
in Rails applications. Rather than tie the functionality to something specific&lt;br /&gt;
like an account, SubdomainFu simply provides a foundation upon which any&lt;br /&gt;
subdomain-keyed system can easily be built.&lt;/p&gt;
&lt;h3&gt;Usage Fu&lt;/h3&gt;
&lt;p&gt;SubdomainFu works by riding on top of the &lt;span class="caps"&gt;URL&lt;/span&gt; Rewriting engine provided with&lt;br /&gt;
Rails. This way you can use it anywhere you normally generate URLs: through&lt;br /&gt;
&lt;code&gt;url_for&lt;/code&gt;, in named routes, and in &lt;code&gt;resources&lt;/code&gt;-based routes. There&amp;#8217;s a small&lt;br /&gt;
amount of configuration that is needed to get you running (though the defaults&lt;br /&gt;
should work for most).&lt;/p&gt;
&lt;p&gt;To set it up, you can modify any of these settings (the defaults are shown):&lt;/p&gt;
&lt;pre&gt;&amp;lt;code class='ruby'&amp;gt;# in environment.rb
  
# These are the sizes of the domain (i.e. 0 for localhost, 1 for something.com)
# for each of your environments
SubdomainFu.tld_sizes = { :development =&amp;gt; 0,
                          :test =&amp;gt; 0,
                          :production =&amp;gt; 1 }

# These are the subdomains that will be equivalent to no subdomain
SubdomainFu.mirrors = ["www"]

# This is the "preferred mirror" if you would rather show this subdomain
# in the URL than no subdomain at all.
SubdomainFu.preferred_mirror = "www"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now when you&amp;#8217;re in your application, you will have access to two useful&lt;br /&gt;
features: a &lt;code&gt;current_subdomain&lt;/code&gt; method and the &lt;span class="caps"&gt;URL&lt;/span&gt; Rewriting helpers.&lt;br /&gt;
The &lt;code&gt;current_subdomain&lt;/code&gt; method will give you the current subdomain or&lt;br /&gt;
return nil if there is no subdomain or the current subdomain is a mirror:&lt;/p&gt;
&lt;pre&gt;&amp;lt;code class='ruby'&amp;gt;# http://some_subdomain.myapp.com/
current_subdomain # =&amp;gt; "some_subdomain"

# http://www.myapp.com/ or http://myapp.com/
current_subdomain # =&amp;gt; nil

# http://some.subdomain.myapp.com
current_subdomain # =&amp;gt; "some.subdomain"&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The &lt;span class="caps"&gt;URL&lt;/span&gt; rewriting features of SubdomainFu come through a &lt;code&gt;:subdomain&lt;/code&gt; option&lt;br /&gt;
passed to any &lt;span class="caps"&gt;URL&lt;/span&gt; generating method. Here are some examples (in these examples,&lt;br /&gt;
the current page is considered to be &amp;#8216;http://intridea.com/&amp;#8217;):&lt;/p&gt;
&lt;pre&gt;&amp;lt;code class='ruby'&amp;gt;url_for(:controller =&amp;gt; "my_controller", 
  :action =&amp;gt; "my_action", 
  :subdomain =&amp;gt; "awesome") # =&amp;gt; http://awesome.intridea.com/my_controller/my_action
  
users_url(:subdomain =&amp;gt; false)  # =&amp;gt; http://intridea.com/users

# The full URL will be generated if the subdomain is not the same as the
# current subdomain, regardless of whether _path or _url is used.
users_path(:subdomain =&amp;gt; "fun") # =&amp;gt; http://fun.intridea.com/users
users_path(:subdomain =&amp;gt; false) # =&amp;gt; /users&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;While this is just a simple set of tools, it can allow the easy creation&lt;br /&gt;
of powerful subdomain-using tools. Note that the easiest way to locally&lt;br /&gt;
test multiple subdomains on your app is to edit &lt;code&gt;/etc/hosts&lt;/code&gt; and add&lt;br /&gt;
subdomains like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;127.0.0.1	localhost subdomain1.localhost subdomain2.localhost www.localhost&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Adding an entry for each subdomain you want to use locally. Then you need&lt;br /&gt;
to flush your local &lt;span class="caps"&gt;DNS&lt;/span&gt; cache to make sure your changes are picked up:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo dscacheutil -flushcache&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Installation&lt;/h3&gt;
&lt;p&gt;SubdomainFu is available both as a traditional plugin and as a GemPlugin&lt;br /&gt;
for Rails 2.1 and later. For a traditional plugin, install like so:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;script/plugin install git://github.com/mbleigh/subdomain-fu.git&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For a GemPlugin, add this dependency to your &lt;code&gt;environment.rb&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;config.gem 'mbleigh-subdomain-fu', :source =&amp;gt; "http://gems.github.com/", :lib =&amp;gt; "subdomain-fu"&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Implementing A Simple Account Key System&lt;/h3&gt;
&lt;p&gt;Let&amp;#8217;s take this functionality and implement a simple account-key system based&lt;br /&gt;
off of the subdomain. We&amp;#8217;ll start with some controller code (assuming that&lt;br /&gt;
we have an Account model with a &amp;#8216;subdomain&amp;#8217; field):&lt;/p&gt;
&lt;pre&gt;&amp;lt;code class='ruby'&amp;gt;class ApplicationController &amp;lt; ActionController::Base
  protected
  
  # Will either fetch the current account or return nil if none is found
  def current_account
    @account ||= Account.find_by_subdomain(current_subdomain)
  end
  # Make this method visible to views as well
  helper_method :current_account
  
  # This is a before_filter we'll use in other controllers
  def account_required
    unless current_account
      flash[:error] = "Could not find the account '#{current_subdomain}'"
      redirect_to :controller =&amp;gt; "site", :action =&amp;gt; "home", :subdomain =&amp;gt; false
    end
  end
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&amp;#8217;s really all we need for a basic setup, now let&amp;#8217;s say we have a&lt;br /&gt;
&lt;code&gt;ProjectsController&lt;/code&gt; that you must specify an account to access:&lt;/p&gt;
&lt;pre&gt;&amp;lt;code class='ruby'&amp;gt;class ProjectsController &amp;lt; ApplicationController
  # Redirect users away if no subdomain is specified
  before_filter :account_required
end&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&amp;#8217;s lots more you can do with the plugin, but this is a simple use case&lt;br /&gt;
that everyone can relate to.&lt;/p&gt;
&lt;h3&gt;Resources and Plans&lt;/h3&gt;
&lt;p&gt;A feature that I hoped would make it to the first release of SubdomainFu&lt;br /&gt;
but is now a planned feature is subdomain-aware routing so that you can&lt;br /&gt;
add conditional subdomain routes to your &lt;code&gt;routes.rb&lt;/code&gt; file. Keep an eye&lt;br /&gt;
out for more on that in the future.&lt;/p&gt;
&lt;p&gt;In the meantime, the project will live at its home on &lt;a href="http://www.actsascommunity.com/projects/subdomain-fu/"&gt;Acts As Community&lt;/a&gt; for intermittent&lt;br /&gt;
updates, &lt;a href="http://github.com/mbleigh/subdomain-fu/"&gt;is available on GitHub&lt;/a&gt; as always, and bugs/feature requests may&lt;br /&gt;
be passed on through the &lt;a href="http://mbleigh.lighthouseapp.com/projects/13148-subdomain-fu"&gt;Lighthouse&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;    </content>
  </entry>
</feed>
