Ruby on rails 将ActionCable与服务对象一起使用并响应消息

Ruby on rails 将ActionCable与服务对象一起使用并响应消息,ruby-on-rails,ruby,websocket,actioncable,service-object,Ruby On Rails,Ruby,Websocket,Actioncable,Service Object,为这个问题命名非常困难,但本质上,我的Rails应用程序中有一个服务对象,它创建了一个简历处理流程。我正在尝试使用ActionCable连接我的前端和后端。目前我这样做的方式是在我的控制器中实例化我的服务对象: def从恢复创建 ... ResumeParseService.new(@candidate,当前用户) 结束 然后,我的服务开始向我的前端广播,以打开相应的模式: 服务: 类服务 属性读取器:用户 属性读取器:员工 属性读取器:候选人 def初始化(候选、用户) @用户=用户 @em

为这个问题命名非常困难,但本质上,我的Rails应用程序中有一个服务对象,它创建了一个简历处理流程。我正在尝试使用ActionCable连接我的前端和后端。目前我这样做的方式是在我的控制器中实例化我的服务对象:

def从恢复创建
...
ResumeParseService.new(@candidate,当前用户)
结束
然后,我的服务开始向我的前端广播,以打开相应的模式:

服务

类服务
属性读取器:用户
属性读取器:员工
属性读取器:候选人
def初始化(候选、用户)
@用户=用户
@employee=user.employee
@候选人
@进度=0
-->广播开始
结束
def begin_from_parse_modal
广播进展(10)
parsed_resume=获取_a_resume_,同时隐藏_实现_详细信息
广播进度(兰特(40..60))
...
广播进度(100-@进度)
...
结束
私有的
开始广播
ResumeParseChannel.广播和设置服务(自我、用户、{
事件名称:“过渡屏幕”,
道具:{
到:'解析',
},
})
结束
def广播_进度(添加)
@进度+=添加
ResumeParseChannel.broadcast_to(用户、{
事件名称:“进度”,
道具:{
进度:@进度,
},
})
结束
def广播转换屏幕(屏幕名称,正文=nil)
ResumeParseChannel.broadcast_to(用户、{
事件名称:“过渡屏幕”,
道具:{
收件人:屏幕名称,
资料来源:body,
},
})
结束
结束
Rails频道

#冻结的字符串文字:true
类ResumeParseChannel
然后由我的频道负责。稍后,我的频道将发回“进度更新”,让我的服务知道模式已成功打开: JS频道

consumer.subscriptions.create(
{频道:“ResumeParseChannel”},
{
连接的(){
document.addEventListener(“恢复解析:屏幕已转换”,事件=>
-->执行(“屏幕转换”,事件细节)
);
},
}
);
现在,我的问题是,一旦消息被发送回我的(ruby)通道,我想不出一种方法让它找到我的服务对象的现有实例并使用它。正如您所看到的,我尝试在第一次广播时使用服务对象实例在频道上设置实例var,但这(以及一百万其他事情)不起作用。我需要调用#begin_from_parse_modal,一旦我得到屏幕名称为“parse”的“screen_transitioned”。理想情况下,我希望尽可能地分离广播逻辑和解析逻辑

我知道频道的实例可以被视为实际订阅,但我不明白在一个系统中,我可以发送一条“做这个”消息,然后在收到一条“它已经做了”消息后再做一些事情的最佳实践是什么

如果我遗漏了任何解释和/或代码,请告诉我。请随时告诉我,下次我问什么问题时是否应该做些不同的事情!这是我第一次询问stackoverflow,但这是我第十亿次寻找答案:)


编辑:我仍然对这种看似普通的情景感到目瞪口呆。仅仅让通道充当服务对象可能是最佳实践吗?如果是这样,我们将如何在其上存储状态?我能想到的以任何形式工作的唯一可能方法是在每个WS消息中发送完整状态。或者至少将id添加到处于状态的每条记录,然后查找每条消息上的每条记录。这似乎过于复杂和昂贵。我搜索了其他问题,甚至是ActionCable教程,以找到任何使用服务对象接收消息的人,但什么也没找到。求救

为什么需要连接到服务对象的特定实例(与仅仅创建一个服务对象的新实例并调用它相比?@rmlockerd,我必须保留一些在业务逻辑中使用的实例变量。即使我没有这样做,我如何将
@candidate
传递给服务对象的新实例。似乎该对象需要从annel,它没有状态…通道不是服务对象;它更像控制器。你说在消息中传递ID“非常复杂和昂贵”,但这正是HTTP请求和
ActionController
的工作方式。理想情况下,你应该使用持久化机制(数据库或类似redis的东西)维护消息之间的状态。如果必须的话,我想您可以将通道设置为可观察的,并让您的服务对象实例注册以进行更新;我不确定这与您现在使用的实例变量路由是否有显著不同。@rmlockerd从本质上讲,您是说不重用st是有意义的在消息之间吃点东西(可能会有很多,因为主要是ui事件),然后从数据库中获取每一条消息的记录?我的意思是,也许在这里使用redis是有意义的。我可以在redis中几乎有一个状态实例包含ord中的记录