ruby-on-rails - 人们在 Rails 应用程序中使用什么 app/services/

标签 ruby-on-rails

我现在和他们都会在 ruby​​ on rails 生态系统中遇到这种情况:

class LocalizeUrlService
class Services::UpdateUserRegistrationForOrder
class ProductionOrderEmailService
UserCart::PromotionsService.new(
Shipping::BulkTrackingService.new(bulk_update, current_spree_user)

您还可以查看示例 here

但是,在例如“Ruby On Rails Guides”的官方示例中,我从未见过这种情况。这让我相信这是一个来自不同于 Rails/OOP 的另一种语言/范式的概念。

这种范式/趋势从何而来?有教程/书吗
这些人受到了影响?这些人是否对几年前的 SOA 趋势持反对态度?

将代码放在 app/service/blah_service.rb 中是个好主意吗?
如果是,哪些逻辑/代码可以被视为“服务” Material 。
是否有任何类型的代码可以/不属于服务?

什么 gem/plugin 创建了 app/services 文件夹? vanilla rails 应用程序一开始并没有附带它。

sidetone:就我个人而言,我对实例化服务有疑问。我觉得 ametuer 程序员滥用类和实例化。我觉得类和实例化是“为了一件事”,而服务是“做”的事情
所以 mixins/defs/include 应该是我觉得应该走的路。

最佳答案

服务对象用于不适合正常 MVC 范式的事物。它们通常用于业务逻辑,否则会使您的模型或 Controller 太胖。通常,它们没有状态(保存在模型中)并执行诸如与 API 或其他业务逻辑对话之类的事情。服务对象让您的模型保持精简和专注,每个服务对象也很精简并专注于做一件事。

Rails Service Objects: A Comprehensive Guide有使用服务对象来管理与 Twitter 的对话或封装可能跨多个模型的复杂数据库事务的示例。

Service Objects in Ruby on Rails…and you显示创建服务对象来管理新用户注册过程。

EngineYard 博客发布 Using Services to Keep Your Rails Controllers Clean and DRY以进行信用卡处理的服务对象为例。

如果您正在寻找起源,Service objects in Rails will help you design clean and maintainable code. Here's how.是从 2014 年他们来到现场时开始的。

Services has the benefit of concentrating the core logic of the application in a separate object, instead of scattering it around controllers and models.

The common characteristic among all services is their lifecycle:

  • accept input
  • perform work
  • return result


如果这听起来很像函数的作用,那你是对的!他们甚至推荐使用 call作为服务上的公共(public)方法名称,就像 Proc .您可以将服务对象视为一种命名和组织大型子例程的方法。

Anatomy of a Rails Service Object解决了服务对象和关注点之间的区别。它涵盖了服务对象相对于模块的优势。它详细介绍了什么是好的服务对象,包括......

  • Do not store state
  • Use instance methods, not class methods
  • There should be very few public methods
  • Method parameters should be value objects, either to be operated on or needed as input
  • Methods should return rich result objects and not booleans
  • Dependent service objects should be accessible via private methods, and created either in the constructor or lazily


例如,如果您有一个应用程序将用户订阅到可能是三个模型的列表:用户、列表、订阅。
class List
  has_many :subscriptions
  has_many :users, through: :subscriptions  
end

class User
  has_many :subscriptions
  has_many :lists, through: :subscriptions
end

class Subscription
  belongs_to :user
  belongs_to :list
end

使用基本的create,在列表中添加和删除用户的过程非常简单。和 destroy方法和关联,也许还有一些回调。

现在你的老板想要一个复杂的订阅流程,它可以进行大量的日志记录、跟踪统计信息、向 Slack 和 Twitter 发送通知、发送电子邮件、进行大量验证……现在是一个简单的 createdestroy成为一个复杂的工作流程,联系 API 并更新多个模型。

你可以把这些都写成关注点或模块,把所有的东西都包含在这三个以前简单的模型中,然后写大Subscription.register。和 Subscription.remove类方法。现在您的订阅可以在 Slack 上发推文和发帖,并验证电子邮件地址并执行背景调查?奇怪的。您的模型现在充斥着与其核心功能无关的代码。

相反,你可以写 SubscriptionRegistrationSubscriptionRemove服务对象。这些可以包括发布和存储统计数据以及执行背景检查等的能力(或者更有可能将其放入更多服务对象中)。他们每个人都有一个公共(public)方法:SubscriptionRegistration.perform(user, list)SubscriptionRemove.perform(subscription) . User、List 和 Subscription 不需要知道任何关于它的信息。您的模型保持 slim 并做一件事。您的每个服务对象都做一件事。

至于你的具体问题...

Where is this paradigm/trend coming from?



据我所知,这是“胖模型/瘦 Controller ”趋势的结果;我就是这样想到的。虽然这是个好主意,但您的模型通常会变得太胖。即使有模块和关注点,塞进一个类(class)也太难了。通常会使模型或 Controller 膨胀的其他业务逻辑进入服务对象。

What gem/plugin creates the app/services folder?



你做。 app/ 中的所有内容在 Rails 5 中自动加载。

关于ruby-on-rails - 人们在 Rails 应用程序中使用什么 app/services/,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52526322/

相关文章:

sql - Rails PG::UndefinedTable:错误:缺少表的 FROM 子句条目

ruby-on-rails - PG::ConnectionBad FATAL:角色 "Myname"不存在

ruby-on-rails - 在不使用 `at_exit` 的情况下,如何确保操作在 Rails 退出之前运行?

ruby-on-rails - Rails - 单个表单上多个模型的用户输入 - 如何

sql - 我怎样才能加快这段代码的速度?

ruby-on-rails - 在 Rails 中,我应该如何使用 ajax 更新数据库中的值?

ruby-on-rails - 代表用户进行 Stripe 付款

ruby-on-rails - 检查日期是否超过一天、超过一年等?

ruby-on-rails - 如何在一个域(和子域)上提供多个 Rails 应用程序?

ruby-on-rails - 打开新的终端窗口后,为什么需要使用 “rvm use default”?