Rails 3 Foreign Domain routing - cannot get this to work!

Hello,
I’m trying to build an app (mysuperapp.com) that allows users to create an account in which a default subdomain (IE: joeshmoe.mysuperapp.com) will be
created as their homepage. In their profile settings, I also want to give them the ability to add their own domain name so their homepage now can be joeshmoe.com. I know this is possible in rails w/ plugins like subdomainfu and w/out plugins in rails3. I’ve searched countless websites on the subject and I’m attempting to build an app based on this example:

glacialis

so, as in this example, I’ve created lib/personalized_domain.rb


# lib/personalized_domain.rb
class PersonalizedDomain
  def self.matches?(request)
    case request.host
    when 'www.#{APP_CONFIG[:domain]}', '#{APP_CONFIG[:domain]}', nil
      false
    else
      true
    end
  end
end

and in my routes I have this:


# config/routes
constraints(PersonalizedDomain) do
  namespace :personalized, :path => '/' do
    root :to => "projects#show"
    resource :project
  end
end


root :to => "home#index"

in my model I have:


# app/models/project.rb
before_validation :cache_domain

validates_uniqueness_of :subdomain, 
                        :cached_domain
validates_uniqueness_of :cname_alias, 
                        :allow_blank => true
validates_presence_of   :subdomain,
                        :cached_domain
validates_exclusion_of  :subdomain,
                        :in => %w(admin blog), 
                        :message => "is taken"

def cache_domain
  self.cached_domain = if self.cname_alias.blank?
    "#{self.subdomain}.#{APP_CONFIG[:domain]}"
  else
    "#{self.cname_alias}"
  end
end

as per the example, my base controller:


# app/controllers/personalized/base_controller.rb
class Personalized::BaseController < ApplicationController
  before_filter :get_project

protected
  def get_project
    @project = Project.first(:conditions => { 
        :cached_domain => request.host 
    })
  end
end

One thing I noticed, in PersonalizedDomain, was that if I put a debug statement in the self.matches? method as such:


class PersonalizedDomain
  def self.matches?(request)
    Rails.logger.info("****(PersonalizedDomain::self.matches?)-->>APP_CONFIG[:domain]: #{APP_CONFIG[:domain]}")
    case request.host
    when 'www.#{APP_CONFIG[:domain]}', '#{APP_CONFIG[:domain]}', nil
      false
    else
      true
    end
  end
end

the debug statement never get’s executed.

Thanks for any help

I think your first problem is that single quotes in ruby do not allow variable interpolation:

case request.host
when 'www.#{APP_CONFIG[:domain]}', '#{APP_CONFIG[:domain]}', nil

But your logger gets called before that line, so it appears matches() isn’t being called at all. I don’t know much about rails, but here:

http://bcardarella.com/post/716951242/custom-subdomains-in-rails-3

it says routes.rb should look like this:

# config/routes.rb

TestApp::Application.routes.draw do |map|
  constraints(PersonalizedDomain) do
    root :to => "customers#index"
  end
  
  root :to => "home#index"
end

Thanks for the reply. You are correct about the single quotes - pretty dumb oversite.

Nonetheless, both the changes you suggested didn’t solve the problem. I find it very strange that self.matches method doesn’t seem to be being called.

I quickly glanced over the example you linked to. Did you remember to do this:

Make sure you load this file. You can do this by adding lib to your autoload paths:

# config/application.rb
module ExampleApp
  class Application < Rails::Application
    ...
    config.autoload_paths += %W(#{config.root}/lib)
    ...
  end
end

thanks for the reply.

That’s exactly what I have in application.rb.

Here’s an update - I did figure out why my custom constraint wasn’t working correctly and here’s the changes I made:

In PersonalizedDomain I changed the self.matches? method from a class method to an instance method as such:


# lib/personalized_domain.rb
class PersonalizedDomain
  def matches?(request)
    case request.host
    when "www.#{APP_CONFIG[:domain]}", "#{APP_CONFIG[:domain]}", nil
      false
    else
      true
    end
  end
end

and in routes I did this:


constraints(PersonalizedDomain.new) do
      resources :posts
      resources :personalized
  end