Dynamic template system with RoR

I’m brand new to Ruby and Rails, but I’ve read a lot of the requisite
tutorials and feel pretty comfortable with most of it. I’ve been
developing sites in PHP for the better part of a decade, so please bear
in mind that I’m still trying to break myself out of “thinking” in PHP.
:wink:

The last remaining problem I can’t seem to find any answer to – maybe
I’m just not searching correctly – is how to control the template
system. Let me give you an example of what I want to do.

For this site, we will be accepting clients with their own domain name.
All of these domain names will be pointed to the same directory on our
server, where the client application lives. I need to be able to use all
the same logic – the controllers, right? – but load a different
template for each domain, so that each looks like its own site. I have
already determined how to get the domain name being accessed, and can
look up which theme the site is using in my database. My confusion comes
in what to do next, and how to organize this.

In PHP, I would have a /themes/ directory with a bunch of different
subdirectories, each containing a set of templates. When the client’s
site first loads, I would do a query to find out which theme path they
are supposed to be using. Let’s say it’s /themes/silver. I would set
that as a session variable and use it whenever loading a template file.
How should I approach this in RoR?

Thanks for your patience and help! Remember, I haven’t actually
implemented anything in RoR yet, so speak slowly. :slight_smile:

On Mar 12, 2007, at 11:42 AM, Matthew wrote:

template for each domain, so that each looks like its own site. I have
file.
How should I approach this in RoR?

There would be at least a couple of options, depending on how you
want to implement the themes and how much they should differ from one
another.

One would be to use the same views for the actions but have a
different layout for each client. You could then use a method in your
controller to select the appropriate layout:

class MyController < ApplicationController
layout :select_layout

def my_action
# Perform action here
end

private

Say we have a field in our table defining the layout for the client

def select_layout
@client = Client.find() // whatever your query is
layout = @client.layout
end
end

See the documentation for the layout method at:

http://api.rubyonrails.org/classes/ActionController/Layout/
ClassMethods.html#M000129

Alternatively you could look at a theming engine like liquid: http://
home.leetsoft.com/liquid

James.


James S.

Work: Processing Greenbelt 2009 – James Stewart
Play: http://james.anthropiccollective.org

In PHP, I would have a /themes/ directory with a bunch of different
subdirectories, each containing a set of templates. When the client’s
site first loads, I would do a query to find out which theme path they
are supposed to be using. Let’s say it’s /themes/silver. I would set
that as a session variable and use it whenever loading a template file.
How should I approach this in RoR?

My initial thought is using layouts:

You can define the layout for a controller as a function, meaning you
could
do something like this

def MyController < ApplicationController
layout :themed_layout

def themed_layout
session[:layout] ||= Layout.find_by_domain()
end
end

What the above code does is call the themed_layout function whenever
someone
accesses an action in MyController.
The function will use some code to find out which layout should be used
(Here, I’m doing it via a call to a lookup table in an imaginary DB),
and
cache that into the session[:layout] variable… meaning that the first
time it is called, it pulls from the DB, and thereafter, it will simply
use
what’s stored in session[:layout]. If the session is somehow
invalidated,
it will re-make the DB call and restore it in the session.

Is this kind of what you’re looking for?

Thank you to both of you, I think that will get me somewhere. I think
the rest of my task is to understand how RoR handles layouts. One
additional piece of functionality I’d like is to be able to have one
layout “fail back” to a default layout; that is, if the template file
for the specified layout doesn’t exist, it will use a template file with
that name in some default directory. That way, I can create themes that
“inherit” from another theme, and only have the files that need to be
changed in the new theme’s directory.

Matt,
I’m going to be trying to do exactly what you describe in your post.
I’m going to try to build one domain CMS type website that handles
many different domains and changes not only the data but also the HTML
code on each site that comes from a database record.
Would it be ok if I asked you a few questions along the way?
David
dak AT itracker DOT com

On Mar 12, 12:19 pm, Matthew R. [email protected]

BraveDave,

You’ll notice that I just posted this thread yesterday, and I’ve never
written anything in Rails. I don’t think I’m the right person to ask!
However, once I do figure it out, I’ll make sure I write up a guide and
come back here and post it.

I’m still trying to figure out how to have the default fail-back method
I talked about above.

You really need to read AWDWR (Agile Web D. With Rails… you
can
find it here: http://www.pragmaticprogrammer.com/titles/rails)… it’s
great, it teaches you how to do most everything you want to do with
Rails,
and will give you a good framework to build on to find the things it
doesn’t
teach… basically, it seems like what you need is a mixture of layouts,
partials, and the ability to use File.exist? wisely… I would
definitely
read that book, and quite probably also read Programming Ruby (
https://pragprog.com/titles/ruby/programming-ruby-2nd-edition/) for a good intro
to
the language Rails was written with, and that you will be using to
customize
your Rails app to fit your needs.