Skip to content
spanner edited this page Sep 13, 2010 · 34 revisions

This is a fork of the multi_site extension. The main addition is a scoped finder that can be applied to any model by calling is_site_scoped, but there are a few other minor changes and the site detection mechanism is shifted to ApplicationController so that a current_site accessor can be made available alongside current_user,

There are several other forks of multisite that enforce various fixed but probably popular scoping patterns. I needed something a bit more flexible and I feel more comfortable with a solution that hooks into ActiveRecord rather than sitting on top of radiant. The main purpose of this version is to underpin other extensions that need to be site-scoped, most of which will appear here shortly.

The additions are all very new and untried but everything is specced properly and the tests pass.


class Forum < ActiveRecord::Base
  is_site_scoped

  # and you'll need a site_id column
  # but that's it
end

You can also scope an existing Radiant model class by setting a configuration parameter in the config.after_initialize block:


      MultiSite::Config.scoped_models = [:layouts, :snippets]

The effect is to completely hide any instance of that class that doesn’t belong to the current site. It’s as though they don’t exist.

There are three main interventions, all quite simple:

  • a site association is declared and validated
  • an alias_method_chain means that Forum.find(:all) is effectively the same as current_site.forums.find(:all)
  • a before_validation filter sets forum.site ||= current_site

Where current_site is a class method that returns Page.current_site, which has been set in the usual way by the controller’s before_filter :set_current_site (which I’ve moved but not changed).

(In fact the main alias is not :find but :find_every, through which I think all find operations travel, including find_by_ids and all the the attribute-based finders.)

As is usual, if Model.find(...) fails we raise a ActiveRecord::RecordNotFound but Model.find_by_name(...) finds nothing it just returns nil. If a site can’t be found during any of these operations we raise a MultiSite::SiteNotFound exception. I probably want to catch that and redirect to admin/sites (without triggering another one) but I haven’t really thought that part through yet.

The forum model in this example must have a site_id column, by the way, and if it validates_uniqueness_of anything then you probably want to add :scope => :site_id. Apart from that it just works.

Clone this wiki locally