问题
Probably a confusing title, but not sure how else to put it. Example should make it clearer. I have many different models that share many of the same attributes. So in each model I have to specify those same attributes and THEN the attributes that are specific to that particular model.
Is there any way I can create some class that lists these basic attributes and then inherit from that class without using Single-Table Inheritance? Because if I put all the shared attributes and Mongoid includes into a single model and inherit from that base model in the other models, then STI is enforced and all my models are stored in a single mongodb collection, differentiated by a "_type" field.
This is what I have:
class Model_1
include Mongoid::Document
field :uuid, :type => String
field :process_date, :type => String
...
end
class Model_2
include Mongoid::Document
field :uuid, :type => String
field :process_date, :type => String
...
end
But this is the functionality I'm after:
class Base_model
field :uuid, :type => String
field :process_date, :type => String
end
class Model_1 < Base_model
# To ensure STI is not enforced
include Mongoid::Document
# Attribute list inherited from Base_model
end
The issue is that if you don't have the "include Mongoid::Document" in the Base_model, then that base model doesn't know about the "field ..." functionality. But if you do put the mongoid include in the base model and inherit from it, STI is enforced.
I can't do STI for this particular situation but it's a coding nightmare to have multiple models, all with the same attributes list specified over and over (there are a growing number of models and each share about 15-20 attributes, so anytime I have to change a model name it's a lot of effort to change it everywhere...).
回答1:
You can define the common attributes in a module and include that.
require 'mongoid'
module DefaultAttrs
def self.included(klass)
klass.instance_eval do
field :uuid, :type => String
end
end
end
class Foo
include Mongoid::Document
include DefaultAttrs
field :a, :type => String
end
class Bar
include Mongoid::Document
include DefaultAttrs
field :b, :type => String
end
回答2:
I had the exact same question and wanted to go for the mixin approach initially. However, after talking to some experts it turns out that using mongoids single table inheritance (one collection for all child elements) may be the way to go, depending on your use case. Please see my post here: single collection vs. separate collections for inherited objects
回答3:
You can bundle them into a new module, i.e.
module Mongoid
module Sunshine
extend ActiveSupport::Concern
included do
include Mongoid::Document
include Mongoid::Timestamps
include Mongoid::TouchParentsRecursively
include Mongoid::Paranoia
include Mongoid::UUIDGenerator
end
end
end
class School
include Mongoid::Sunshine
end
来源:https://stackoverflow.com/questions/10317376/rails-3-using-mongodb-via-mongoid-adapter-is-there-any-way-to-share-attribute