I'm building a Rails 3 app where users can select one of a number of templates and build a little website. I'm trying to initialize all of the available templates when the application starts. That's essentially a file that let's me define them all, then calls Template.add(template)
for each one of them, which in turn stores them in @@templates
and I can access them via Template.find(name)
.
The problem is that in development mode, the initializer I have making the calls to Template.add
are getting loaded on the first request, then wiped out on reload!
. I've read about config.to_prepare
, but it isn't working for me, likely because I'm requiring the templates like this:
# template config at app/templates/template_name/template_name.rb
path = File.expand_path(Rails.root + 'app/templates')
Dir[File.join(path, '/*')].each do |template|
name = File.basename(template)
require File.join(path, name, "#{name}.rb")
end
What can I do to either reload these files after reload!
or keep them from getting trashed at all? Also, if you have a recommendation for a better way to handle this, I'm all ears. I'm still getting my footing with Rails, especially in regards to configuration stuff.
I'm temporarily avoiding this problem by loading the data in the class. Save me from this ugly, non-modular nastiness.
I think you ought to be able to do this with config.to_prepare
if you move your calls to Template.add
out of the template_name.rb
files (I am assume that is where they are now), and into your loading code, just after the require
. For example, consider adding this class method to your Template class, and then maybe even calling it from the class itself when it first gets loaded:
class Template
def self.load_all
# template config at app/templates/template_name/template_name.rb
path = File.expand_path(Rails.root + 'app/templates')
Dir[File.join(path, '/*')].each do |template|
name = File.basename(template)
require File.join(path, name, "#{name}.rb")
# Register the template even if the class itself is already loaded.
Template.add(name)
end
end
# Initially load all templates.
Template.load_all
end
Then remove the Template.add(name)
code from the template_name.rb
files where they are registering themselves. (Again, I am assuming this is where that currently happens - I am not quite clear on this from your original post.) Or perhaps you just want to make sure Template.add
is idempotent and silently discards duplicates.
Lastly, add the following to config/environments/development.rb
:
config.to_prepare do
Template.load_all
end
That will reload all your templates after the Template
class reloads.
I haven't tried this, but with the call to Template.load_all
I suggested at the end of the Template
class, you may not even need the config.to_prepare
part.
How about storing the lookup of template names to their files in a memory store like memcached or Redis, or even in the database. The initializer could load up the memory store or ensure that the database is up to date with all the values, and then Template.find
could just look to the store to see where the files are, or even just get the class name if they are already going to be loaded. Simply seeing if the class name is defined can tell you if you need to require the template file or just go ahead and create your new instance.
Basically store @@templates
outside of the rails process memory, or at least enough information that you could build the parts of @@templates
that you need on the fly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With