简体   繁体   中英

How do I provide a default class definition from /lib in Rails?

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??

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 )

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM