开发者

Determine the domain in an ActiveRecord model

I am in the middle of migrating my application from using subdirectories for userspace to subdomains (ie. domain.com/~user to user.domain.com). I've got a method in my user class currently to get the "home" URL for each user:

class User
  def home_url
    "~#{self.username}"

    # How I'd like to do it for subdomains:
    #"http://#{self.username}.#{SubdomainFu.host_without_subdomain(request.host)}"
  end
end

I'd like to update this for subdomains, but without hardcoding the domain into the method. As you can s开发者_高级运维ee, I am using the subdomain-fu plugin, which provides some methods that I could use to do this, except that they need access to request, which is not available to the model.

I know it's considered bad form to make request available in a model, so I'd like to avoid doing that, but I'm not sure if there's a good way to do this. I could pass the domain along every time the model is initialized, I guess, but I don't think this is a good solution, because I'd have to remember to do so every time a class is initialized, which happens often.


The model shouldn't know about the request, you're right. I would do something like this:

# app/models/user.rb
class User
  def home_url(domain)
    "http://#{username}.#{domain}"
  end
end

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  # ...

  def domain
    SubdomainFu.host_without_subdomain(request.host)
  end

  # Make domain available to all views too
  helper_method :domain
end

# where you need it (controller or view)
user.home_url(domain)

If there is such a thing as a canonical user home URL, I would make a configurable default domain (e.g. YourApp.domain) that you can use if you call User#home_url without arguments. This allows you to construct a home URL in places where, conceptually, the "current domain" does not exist.


While molf's answer is good, it did not solve my specific problem as there were some instances where other models needed to call User#home_url, and so there would be a lot of methods I'd have to update in order to pass along the domain.

Instead, I took inspiration from his last paragraph and added a base_domain variable to my app's config class, which is the set in a before_filter in ApplicationController:

module App
  class << self
    attr_accessor :base_domain
  end
end

class ApplicationController < ActionController::Base
  before_filter :set_base_domain

  def set_base_domain
    App.base_domain = SubdomainFu.host_without_subdomain(request.host)
  end
end

And thus, when I need to get the domain in a model, I can just use App.base_domain.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜