Comment puis-je utiliser Mongoid et ActiveRecord en parallèle dans Rails 3?
J'utilise rails 3 et j'ai commencé mon application avec ActiveRecord. Maintenant, j'ai beaucoup de modèles, et les relations commencent à se compliquer, et certains pourraient être plus simplement exprimés avec une structure orientée Document, donc j'aimerais essayer de migrer vers MongoDB et utiliser Mongoid.
J'ai toujours entendu dire que vous n'aviez pas besoin d'utiliser tout MongoDB ou Rien, mais que vous pouviez utiliser les deux en parallèle lors de la migration. Je ne vois pas comment s'y prendre avec les docs bien.
Par exemple, j'ai:
class User < ActiveRecord::Base
has_many :items
has_many :products, :through => :items
end
class Product < ActiveRecord::Base
has_many :items
end
class Item < ActiveRecord::Base
belongs_to :user
belongs_to :product
# alot of data that fits a hierarchical document-oriented structure
end
Je voudrais idéalement commencer par remplacer mon modèle d'élément activerecord par un document Mongoid, donc mes éléments sont stockés dans MongoDB, et mes Users
et Products
peuvent rester dans mon SQL DB
La chose est, Je ne vois pas comment faire cela. Je vais sur ce la bonne manière?
Peut-être une autre alternative est de garder un élément AR de base
class Item < ActiveRecord::Base
has_one :mongodb_item ?? # I know this is wrong
end
class MongodbItem
include Mongoid::Document
belongs_to AR_Item ??? # I know this is also wrong
end
Merci!
4 réponses
Je ne vois aucune raison pour laquelle vous ne pourriez pas avoir les deux modèles ActiveRecord et Mongoid dans la même application. Cela étant dit, je suis presque certain que vous rencontrerez des problèmes si vous essayez de créer des relations entre vos modèles ActiveRecord et Mongoid.
Si vos modèles ActiveRecord sont fortement interreliés, mais mieux adaptés à une structure de document, alors je suggère de mordre la balle et de les convertir tous en documents Mongoïdes. Je devais le faire récemment sur un (grand-ish) projet, et il est beaucoup moins stressant que vous ne le pensez.
Si vous avez de bons tests unitaires pour vos modèles, cela devrait être un snap total. Si vous n'écrivez pas d'abord vos tests unitaires, assurez - vous qu'ils passent avec ActiveRecord, puis commencez à migrer les choses vers Mongoid.
Ce que j'ai fait était juste de me moquer de la relation avec les méthodes dans chaque modèle AR et le modèle Mongoid comme ça.
# visit_session.rb
class VisitSession
include Mongoid::Document
include Mongoid::Timestamps
field :user_id, type: Integer
index({user_id: 1},{name: :user_id_index})
# Mock a belongs_to relationship with User model
def user
User.find(self.user_id)
end
end
# user.rb
class User < ActiveRecord::Base
# Mock a has_many relationship with VisitSession Mongoid model
def visit_sessions
VisitSession.where(user_id: self.id)
end
end
Bien sûr, vous n'aurez pas toutes les méthodes AR sur le modèle MongoId de VisitSession, mais vous pourrez au moins bien vous moquer de la relation entre les deux.
J'espère que cela aide.
... juste à des fins de suivi, Je voudrais ajouter quelque chose que je viens de découvrir sur ce champ:
J'ai créé un module pour usurper la relation dans les modèles d'enregistrements actifs.
module MongoRelations
def belongs_to_mongo(name, options = {})
id_name = "mongo_#{name}_id".to_sym
mongo_model = options[:through] || "Mongo::#{name.to_s.camelize}".constantize
define_method(name) do
id = send(id_name)
mongo_model.find(id) if id.present?
end
define_method("#{name}=") do |value|
send("#{id_name}=".to_sym, value.try(:id).to_s)
end
end
end
Dans ma table SQL, je nomme mes relations mongo en utilisant la convention mongo_XXX_id, au lieu de XXX_id
J'ai aussi l'espace de noms Tous mes modèles mongo sous Mongo::
Dans mon modèle d'enregistrement actif
class Foo < ActiveRecord::Base
belongs_to_mongo :XXX
end
Qui permet
Foo.new.XXX = Mongo.find('123')
Foo.XXX
Ou
Foo.new.XXX_id = '123'
Foo.XXX