如何设置has_many父应用模型与挂载引擎模型的关联?
How to set has_many association between parent app's model and mounted engine's model?
按照 RailsGuides 说明,我在我的应用程序中创建了一个博客系统引擎。此博客引擎挂载为 /blog。
Rails指南展示了如何将 belongs_to
关联添加到安装引擎的 Article
模型。但是,父应用程序的 User
模型仍然需要 has_many
关联到位于不同命名空间中的引擎 Article
模型。
如何设置has_many父应用程序模型与挂载引擎模型之间的关联?
- Ruby 2.2.0
- Rails 4.2.0
提前致谢。
在 rails 应用程序中,您知道包含的模块是什么,因此您可以简单地指定与 class 名称的关系 ;)
has_many :articles, class_name: 'Blog::Article'
检查这是否是您的数据库适配器的正确语法,例如我将它用于 Mongoid,但它应该与 ActiveRecord AFAIK
相同
已接受的答案需要手动修改 main_app 的父模型,以便将 has_many 关系设置为引擎的子模型。因此,每次将引擎添加到 main_apps 时,您都必须进入 main_apps 模型并手动设置所有必需的关系。
一个更健壮但更复杂的解决方案是在引擎中使用装饰器模式,这样引擎将使用它需要的关系自动配置 main_app 的父模型。
通过使用此方法,您只需在 main_app 中向引擎初始化程序添加一个设置,引擎将处理其余部分。
在引擎中:
blog.gemspec.rb
s.add_dependency 'decorators' #this will install the decorators gem for use in engine
lib/blog/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
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
if Blog.user_class
Blog.decorate_user_class!
else
raise "Blog.user_class must be set in main_app blog.rb initializer"
end
在主应用中:
app/initializers/blog.rb
Blog.user_class = User
如果您从主应用程序 运行 rails 控制台,您会看到关系已正确设置。引擎中的装饰器模式也可用于以不同方式扩展 main_app 的模型和控制器,而不仅仅是 Activerecord 关系。几乎完全脱钩!
按照 RailsGuides 说明,我在我的应用程序中创建了一个博客系统引擎。此博客引擎挂载为 /blog。
Rails指南展示了如何将 belongs_to
关联添加到安装引擎的 Article
模型。但是,父应用程序的 User
模型仍然需要 has_many
关联到位于不同命名空间中的引擎 Article
模型。
如何设置has_many父应用程序模型与挂载引擎模型之间的关联?
- Ruby 2.2.0
- Rails 4.2.0
提前致谢。
在 rails 应用程序中,您知道包含的模块是什么,因此您可以简单地指定与 class 名称的关系 ;)
has_many :articles, class_name: 'Blog::Article'
检查这是否是您的数据库适配器的正确语法,例如我将它用于 Mongoid,但它应该与 ActiveRecord AFAIK
相同已接受的答案需要手动修改 main_app 的父模型,以便将 has_many 关系设置为引擎的子模型。因此,每次将引擎添加到 main_apps 时,您都必须进入 main_apps 模型并手动设置所有必需的关系。
一个更健壮但更复杂的解决方案是在引擎中使用装饰器模式,这样引擎将使用它需要的关系自动配置 main_app 的父模型。
通过使用此方法,您只需在 main_app 中向引擎初始化程序添加一个设置,引擎将处理其余部分。
在引擎中:
blog.gemspec.rb
s.add_dependency 'decorators' #this will install the decorators gem for use in engine
lib/blog/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
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
if Blog.user_class
Blog.decorate_user_class!
else
raise "Blog.user_class must be set in main_app blog.rb initializer"
end
在主应用中:
app/initializers/blog.rb
Blog.user_class = User
如果您从主应用程序 运行 rails 控制台,您会看到关系已正确设置。引擎中的装饰器模式也可用于以不同方式扩展 main_app 的模型和控制器,而不仅仅是 Activerecord 关系。几乎完全脱钩!