[英]How to set has_many association between parent app's model and mounted engine's model?
Following to RailsGuides instruction, I have created an engine for blogging system in my app. 按照RailsGuides指令,我在我的应用程序中创建了一个用于博客系统的引擎。 This blog engine is mounted as /blog. 此博客引擎安装为/ blog。
RailsGuides shows how to add belongs_to
association to the mounted engine's Article
model. RailsGuides显示了如何将belongs_to
关联添加到已挂载引擎的Article
模型。 However, the parent app's User
model still requires has_many
association to the engine's Article
model which is in different namespace. 但是,父应用程序的User
模型仍然需要has_many
关联到引擎的Article
模型,该模型位于不同的命名空间中。
How to set has_many association between parent app's model and mounted engine's model? 如何在父应用程序模型和挂载引擎模型之间设置has_many关联?
Thanks in advance. 提前致谢。
In the rails application, you know what module you include, so you can simply specify the relation with the class name ;) 在rails应用程序中,您知道包含哪个模块,因此您只需指定与类名称的关系;)
has_many :articles, class_name: 'Blog::Article'
check if this is the right syntax for your database adapter, eg I'm using this for Mongoid, but it should be the same with ActiveRecord AFAIK 检查这是否是您的数据库适配器的正确语法,例如我将其用于Mongoid,但它应该与ActiveRecord AFAIK相同
The accepted answer requires manual modification of main_app's parent model in order to set the has_many relationships to the engine's child model. 接受的答案需要手动修改main_app的父模型,以便将has_many关系设置为引擎的子模型。 So each time you add the engine to one your main_apps you would have to go into the main_apps models and set up all required relationships by hand. 因此,每次将引擎添加到main_apps中时,您都必须进入main_apps模型并手动设置所有必需的关系。
A more robust, although more complicated, solution would be to use the decorator pattern in the engine so that the engine will auto-configure main_app's parent model with the relationships it needs. 更强大但更复杂的解决方案是在引擎中使用装饰器模式,以便引擎将自动配置main_app的父模型及其所需的关系。
By using this method you just need to add a setting to the engine initializer in your main_app and the engine will handle the rest. 通过使用此方法,您只需要在main_app中为引擎初始化程序添加一个设置,引擎将处理其余的。
In engine: 在引擎中:
blog.gemspec.rb blog.gemspec.rb
s.add_dependency 'decorators' #this will install the decorators gem for use in engine
lib/blog/blog.rb LIB /博客/ blog.rb
module Blog
class Engine < ::Rails::Engine
isolate_namespace Blog
engine_name 'blog'
#to set up main_app objects via decorators in engine
config.to_prepare do
Decorators.register! Engine.root, Rails.root
end
end
end
lib/blog.rb LIB / blog.rb
require 'decorators'
module Blog
mattr_accessor :user_class #Can now reference this setting as Blog.user_class
class << self
#the following lets us add functionality to main_app user model
def decorate_user_class!
Blog.user_class.class_eval do
has_many :articles, :class_name => "Blog::Article", :foreign_key => "user_id"
end
end
end
end
app/decorators/lib/blog/user_class_decorator.rb 应用程序/装饰/ lib目录/博客/ user_class_decorator.rb
if Blog.user_class
Blog.decorate_user_class!
else
raise "Blog.user_class must be set in main_app blog.rb initializer"
end
In main app: 在主应用程序中:
app/initializers/blog.rb 应用程序/初始化/ blog.rb
Blog.user_class = User
If you run rails console from main app, you will see relationships will have been set properly. 如果您从主应用程序运行rails控制台,您将看到关系已正确设置。 The decorator pattern in the engine can also be used to extend the main_app's models and controllers in different ways, not just Activerecord relationships. 引擎中的装饰器模式也可用于以不同方式扩展main_app的模型和控制器,而不仅仅是Activerecord关系。 Almost complete decoupling achieved! 实现了几乎完全解耦!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.