Four Key Reasons to Learn Markdown
Back-End Leveling UpWriting documentation is fun—really, really fun. I know some engineers may disagree with me, but as a technical writer, creating quality documentation that will...
Using a subdomain as an account key is a great way to personalize a web application. Rails has a nifty plugin written just for this, but the implementation information is a bit scattered. Here’s a step-by-step guide for implementing, testing, and simulating this powerful feature.
1. Take a look at the Account Location Plugin
Coming in at a concise 30 lines of code, it’s an easy read.
2. Customize the plugin for your needs
The plugin assumes we’re working with an Account model and that an instance variable named @account
is the Account associated with the current subdomain. In my case, I wasn’t working with an Account class and I also didn’t want to assign the associated object to an instance variable of the same name (For example, in some cases @account
could be assigned to a different account than the one associated with the subdomain).
I’m working with a Heartbeat Dashboard. Here’s my modified code. Instead of installing the plugin, I created a DashboardLocation module:
module DashboardLocation
def self.included(controller)
controller.helper_method(:dashboard_domain, :dashboard_subdomain,
:dashboard_host, :dashboard_url,
:current_dashboard, :current_subscription)
end
protected
def default_dashboard_subdomain
current_dashboard.subdomain if current_dashboard
end
def dashboard_url(dashboard_subdomain = default_dashboard_subdomain,
use_ssl = request.ssl?)
(use_ssl ? "https://" : "http://") + dashboard_host(dashboard_subdomain)
end
def dashboard_host(dashboard_subdomain = default_dashboard_subdomain)
dashboard_host = ""
dashboard_host << dashboard_subdomain + "."
dashboard_host << dashboard_domain
end
def dashboard_domain
dashboard_domain = ""
dashboard_domain << request.subdomains[1..-1].join(".") + "." if request.subdomains.size > 1
dashboard_domain << request.domain + request.port_string
end
def dashboard_subdomain
request.subdomains.first
end
def current_dashboard
Dashboard.find(:first,
:conditions => ["subdomain = ? and subdomain IS NOT NULL",dashboard_subdomain])
end
def ensure_current_dashboard
return true if current_dashboard
flash[:warning] = "Please select a dashboard to login."
redirect_to(:controller => '/home') and return false
end
end
3. Install the plugin (or your own module)
If you don’t need to make any modifications, install the plugin straight-up:
ruby script/plugin install http://dev.rubyonrails.org/svn/rails/plugins/account_location/
If you need a customized module like me, put it in your lib folder (i.e. lib/dashboard_locaton.rb) and require it in your environment.rb file (require ‘dashboard_location’).
4. Add some Test Helpers
I added the methods below to TestHelper
to make it easier to test our subdomain functionality. Remember I’m using current_dashboard
instead of @account
to represent the subdomain record.
class Test::Unit::TestCase
# Puts a dashboard into the subdomain
def dashboard_setup(dashboard = dashboards(:derek_dashboard) )
@request.host = "#{dashboard.subdomain}.local.host"
assert_equal dashboard, current_dashboard
end
def clear_dashboard
@request.host = "local.host"
assert_nil current_dashboard,
"There is a current dashboard when there shouldn't be: #{current_dashboard}"
end
def current_dashboard
Dashboard.find(:first, :conditions => ["subdomain = ? and subdomain IS NOT NULL",dashboard_subdomain])
end
def dashboard_subdomain
@request.subdomains.first
end
end
# failure - invalid subdomain
@request.host = "invalid.local.host"
get :index
assert_redirected_to :controller => 'home'
assert_not_nil flash[:warning]
# success
dashboard_setup
get :index
assert_response :success
assert_template "dashboard/index"
6. Implement the functionality in our controllers
class ApplicationController < ActionController::Base
include DashboardLocation
# ...
end
7. Verify the tests pass
8. Simulate the environment on your development machine.
Alter your “hosts” file to re-route domain lookups to your local machine (127.0.0.1).
On Mac OSX and Linux:
$ sudo vi /etc/hosts
On Windows:
C:WINDOWSSYSTEM32DRIVERSetchosts
Add an entry for your application domain
127.0.0.1 heartbeathq.com
Add entries for any subdomain you want to test:
127.0.0.1 highgroove.heartbeathq.com
127.0.0.1 rubyonrails.heartbeathq.com
Refresh and clear your cache to make sure lookups are re-routed:
On Mac OSX:
Issue the command in the terminal:
$ sudo lookupd -flushcache
On Linux:
Linux is pretty good about reading your /etc/hosts file, but to be on the safe side, restart ncsd if it’s running:
$ sudo /etc/init.d/ncsd restart
On Windows:
Issue the command at the command prompt:
C:>ipconfig /flushdns
You’ll now be able to access your application through a pretty URL like: http://highgroove.heartbeat.com
.
9. Don’t forget…
If you’re like me, you may be dealing with 2 records – a record authenticated via the subdomain and a user authenticated and placed in the session. Don’t forget to ensure that the user in the session has access to the subdomain record.
Remove the entries we added to /etc/hosts
before your site launches.
Setup your real DNS server with a CNAME or other wildcard entry and your webserver of choice with the same wildcard mapping for your application.
That’s it! It’s another “why I love Rails” moment – subdomain-as-account-key functionality in 30 lines of code tested and ready for production.
P.S.
Heartbeat, our Ruby on Rails control panel built during RailsDay 2006, is getting ready to emerge with some very powerful new features. Videos to come late this week.
Writing documentation is fun—really, really fun. I know some engineers may disagree with me, but as a technical writer, creating quality documentation that will...
Humanity has come a long way in its technological journey. We have reached the cusp of an age in which the concepts we have...
Go 1.18 has finally landed, and with it comes its own flavor of generics. In a previous post, we went over the accepted proposal and dove...