I'm presently using a git subtree to manage a directory of classes/libraries somewhere under /lib
. The idea is to share common classes and libraries from that directory between different projects that I manage. In it are default implementations of various classes, such as models, controllers, etc. The desired result is that any application I set up which has this subtree would not HAVE to define or customize the classes that come with default implementations, but can if needed.
For example, I have a default User
model, and wish to include it automatically so that there is no need to define one in /app/models
. The problem is that if I DO automatically include it, and then additionally define a User
class in /app/models
(say to add or override a method or some configs), that definition will never be included because the class already exists.
I'm attempting to take advantage of the fact that a class can be defined twice in Ruby, and it'll more or less "merge" the definitions. For example, defining a User
class twice in the following way will result in a single User
class with methods for both User.foo
and User.bar
:
class User
def self.foo; 'foo'; end
end
class User
def self.bar; 'bar'; end
end
The best way I've come up with to do this so far is to write code in an initializer like the following (note that the to_underscores
method isn't a standard String
method, it's my own):
Rails.configuration.to_prepare do
[
User,
# more classes...
].each do |klass|
filepath = Rails.root.join("app/models/#{klass.name.to_underscores}.rb")
require filepath if File.exist? filepath
end
end
I could clean this up a bit perhaps by looping through class definitions which exist in key subdirectories under /lib
so I don't have to manually list out class names that can be extended/overridden in this way, but I feel like there's got to be a better way. This list will be pretty long and a little silly to try and manage, not to mention it'll be a lot trickier with classes defined in a directory structure with subdirectories. I'd like something more automatic. Any thoughts??
CodePudding user response:
You're getting bitten by lazy loading and rails' constant resolver. If you already load a User
either from app/models
or lib
, rails won't think of looking for other definitions of this class in other places.
You can do what you are doing now. Or turn eager loading on (in your config/*.rb
, set config.eager_load = true
)
CodePudding user response:
Why not use inheritance? So your User
model inherits default behaviour from DefaultUser
class User < DefaultUser
end
class DefaultUser < ActiveRecord::Base
end
You can include the DefaultX
classes by making a gem to import in Gemfile that has all of these default classes defined.