Topic: Using core application code across multiple projects

I am developing an application that is being used by a number of clients (approximately 7).  Each client has their own copy of the code, which is being managed with Subversion.

For each client, there are a number of places where the core code is customized.  This makes updating the core application very challenging, as merging code from the core repository into the client repository often raises conflicts.

Ultimately, I'd like to extract all of the client code into its own directory so that the core code can be easily updated.  Ideally, I'd like anything in the client_code directory to automatically take precedence over its counterpart in the app directory.  This is where I hit a brick wall.  How do I do this?

For example, if my core app had a controller named "MyAccountController" and I wanted to overwrite its "index" action from the code in the client_code directory, how would I do that?

Any help is appreciated!

Re: Using core application code across multiple projects

I'm not too familiar with Rails Engines, but it sounds like they might be useful.

Put common code in the engine and you may override custom client code in your app.

Last edited by astaroth (2008-10-27 19:41:33)

Re: Using core application code across multiple projects

Thanks for the quick reply!

I checked out engines.  I think they're are a step in the right direction, but my situation would be the exact opposite - the common code would be in the application and the engine code would overwrite the common code.

Thanks for your help though!

Re: Using core application code across multiple projects

Saw your comment on railscasts.

Thought about it a bit and may be able to offer a solution.

Not sure if it will work with 2.3 or not, but in this article ( … y-on-rails) I show how to use a plugin's app/controllers and app/models, etc without engines.  I think this provides a little more flexibility, seemingly perfect for your problem.

From what I can tell about your situation, each client would probably have a plugin of their own which would be packed with all the files they would want to overwrite. 

For example, RAILS_ROOT/vendor/plugins/client1 would have app/controllers/.... and app/models and app/views of client1's own customizations.

Ok, so looking at my post, find the init.rb file and take a close look at it.
There is a way to tell rails about your plugin's models, controllers and views.

Normally, the plugins are meant simply to extend and to be overwritten by anything in the core applications code.  But in your situation, the rules are reversed.

So for views, add this to init.rb (note the use of prepend_view_path instead of the normally used append_view_path):

require 'application'
ApplicationController.prepend_view_path(File.join(File.dirname(__FILE__), 'app', 'views'))

For models, again, instead of appending, we need to load it's path first:
# This is what you normally have
#model_path = File.join(directory, 'app', 'models')
#$LOAD_PATH << model_path
#ActiveSupport::Dependencies.load_paths << model_path

# do this instead to put the plugin's file paths first:
model_path = File.join(directory, 'app', 'models')
$LOAD_PATH.insert(0, model_path)
ActiveSupport::Dependencies.load_paths.insert(0, model_path)

For controllers, same thing as models:
# instead of this:
#controller_path = File.join(directory, 'app', 'controllers')
#$LOAD_PATH << controller_path
#ActiveSupport::Dependencies.load_paths << controller_path
#config.controller_paths << controller_path

# do this:
controller_path = File.join(directory, 'app', 'controllers')
$LOAD_PATH.insert(0, controller_path)
ActiveSupport::Dependencies.load_paths.insert(0, controller_path)
config.controller_paths.insert(0, controller_path)

So everything in the client1 plugin (MVC-wise) would be considered first when posts controller is called or when the post model is called or when a particular view is requested.

Seems like it should work - let me know.