【问题标题】:Design pattern for implementing plugins in rails applications在 Rails 应用程序中实现插件的设计模式
【发布时间】:2015-01-21 22:38:01
【问题描述】:

我正在编写一个 Rails 应用程序,它必须允许第三方创建为我的应用程序添加服务支持的插件(即 gems)。这些插件都将实现相同的方法。

我了解到,最好的方法是使用单表继承 (STI),将所有逻辑保留在模型子类中并远离控制器。

这方面的一个例子是指标仪表板应用程序,它使用 Pingdom 插件将最近的网站响应时间添加到图表中。该插件将添加一个 Pingdom 子类,扩展一个 Metric 模型,实现 run 方法。此方法将由应用程序在运行每个插件的 run 方法的任务中调用。

制作这样一个基于插件的应用程序的正确方法是什么?它应该为所有逻辑使用模型吗?有没有更好的办法?

【问题讨论】:

  • 第三方将如何与您的代码集成?你会添加他们的宝石吗?
  • @eabraham 可能会使用宝石,是的。
  • 那么您将把他们的 gem 添加到您的 Gemfile 并运行 bundle install?
  • 您提到了运行方法和“实现相同的方法”。这些“宝石”会是一小段简单的代码吗?他们将如何与数据库交互?阅读和写作?
  • @eabraham 是的,它们将是用于实现第三方服务的一小段代码(参见我的示例)。插件将实现抽象方法(例如,在这种情况下,应用程序中的任务将运行插件实现的方法)。插件只会写入数据库;所有插件都将使用相同的字段。

标签: ruby-on-rails design-patterns plugins


【解决方案1】:

当然单表继承在这种情况下会很有用。

# /app/models/user.rb
class User < ActiveRecord::Base
  # define your base methods, variables and constants
end
# /app/models/pluginuser.rb
class PluginUser < User
  # The gem builders can extend your methods, variables and constants or define their own
end

需要注意的是,所有插件代码都将在同一个命名空间中运行。插件一可以调用插件二的子类方法。这是要求吗?

【讨论】:

  • 我知道问题中提到的 STI,但我更愿意避免缺少命名空间。如果在赏金期结束之前没有更好的答案,我可能会接受你的答案。
  • 我希望可以为您提供更多帮助,但您的问题很难以问答形式表达。许多细节将在开发过程中变得明显。如果您有任何更具体的问题,我很乐意为您提供帮助。
【解决方案2】:

只需我的 0.02 美元,并且知道会有有效的替代答案。

我认为我编写的 gem 是完全独立的服务。这意味着:

  1. 您的代码不能对 gem 如何处理其功能提出任何要求/假设。它应该将该宝石视为一个黑匣子。
  2. gem 不能对应用程序其余部分的设计或行为方式提出任何要求/假设。

由此产生的逻辑后果是,唯一您的应用程序和他们的 gem 应该同意的是通用 API - 他们的 gem 命令将哪些数据作为输入以及他们如何响应。

因此,您可以向正在构建新 gem 的人员提出这些请求似乎是合理的(您可以根据需要更改方法名称等):

  • 任何构建的 gem 都应该有一个命令调用 run!,它接受一组对您有意义的规范/架构的参数。
  • 该 gem 必须从该命令返回一个响应对象,该对象响应常见的 set 方法,例如success?bodyerrors

但是,您决定保留该数据、操作该数据等需要您的应用程序负责处理。 gem 不应该对您的应用程序数据库架构、它如何处理持久性等做出假设。这种方法可能会奏效一段时间,但不可避免地会出现大问题并且是一场噩梦。

如果您对我为什么偏爱这种方法有任何疑问,或者想讨论任何替代方法,请告诉我。

编辑:

我想补充一点,上述建议是基于您在 cmets 中提供的条件,即通过安装 gems 需要此功能。我应该澄清一下,这种情况有很多与之相关的安全风险(以及其他问题)。

您最好构建功能以允许以可以构建应用程序功能但实际上不会与应用程序代码交互的方式编写附加组件/扩展。

如果您查看如何为 Heroku (https://devcenter.heroku.com/articles/building-a-heroku-add-on) 构建附加组件或如何构建 Chrome 扩展程序 (https://developer.chrome.com/extensions/getstarted),您会看到应用程序和扩展程序的关注点是如何完全分离的。

【讨论】:

    【解决方案3】:

    为什么不将插件实现为通过 http 服务调用的微服务?例如,插件需要实现像/data 这样的单个端点,根据用户使用标准参数调用它。如果您需要安全性,您可以加密用户凭据。

    优点:

    • 您不必审查作为 gem 添加的代码(我不相信,我什至不相信代码审查)
    • 插件的提供者不必使用 ruby​​
    • 您可以更改插件,而无需重新部署整个应用程序。
    • 测试版插件将在 heroku 上免费提供。

    heroku 博客上有一篇很棒的文章:

    【讨论】:

      猜你喜欢
      • 2012-03-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 2011-09-17
      • 1970-01-01
      相关资源
      最近更新 更多