Ruby on rails RubyonRails-检查其他编辑器是否正在编辑同一篇文章

Ruby on rails RubyonRails-检查其他编辑器是否正在编辑同一篇文章,ruby-on-rails,ruby,notifications,Ruby On Rails,Ruby,Notifications,我有一个应用程序,作者可以发布内容,所有编辑可以编辑网站上添加的所有内容 有时,2-3名编辑正在编辑同一篇文章,这会引起一些问题。是否可以查看其他编辑是否在同一编辑视图/帖子/编辑上编辑同一帖子 我想做的是添加一个通知,说明[Editor\u name]正在更改此帖子或类似内容。我建议您将以下列添加到表lock\u版本中,以进行乐观锁定,以防止竞争条件current_editor_id以引用当前编辑器编辑\u从开始,如果当前编辑器仍处于“活动”状态,则具有引用 当编辑器开始编辑时,您必须检查当前

我有一个应用程序,作者可以发布内容,所有编辑可以
编辑网站上添加的所有内容

有时,2-3名编辑正在编辑同一篇文章,这会引起一些问题。是否可以查看其他编辑是否在同一
编辑视图/帖子/编辑
上编辑同一帖子


我想做的是添加一个通知,说明
[Editor\u name]正在更改此帖子
或类似内容。

我建议您将以下列添加到表
lock\u版本
中,以进行乐观锁定,以防止竞争条件
current_editor_id
以引用当前编辑器<代码>编辑\u从
开始,如果当前编辑器仍处于“活动”状态,则具有引用

当编辑器开始编辑时,您必须检查当前编辑器是否为实际编辑器或未设置。如果
当前编辑器
nil
当前编辑器
编辑器
相同,或者如果通过
编辑达到时间限制
此编辑器可以开始编辑

编辑开始时,您可以设置
当前编辑器
编辑开始于
并保存对象

当一个编辑器试图保存一个
post
时,您需要再次检查
当前编辑器和编辑器是否匹配。然后你就可以保存邮件了
并将
current\u editor
editing\u start\u在
更新为nil


在其他情况下,您可以打印错误消息

您可以使用乐观锁定。这个想法是每个记录都有一个锁定版本。每次成功更新都会增加该记录的锁定版本。更新记录时,将验证锁定版本。如果模型的版本与数据库中该记录的版本不同,则更新将失败,这意味着在从数据库加载该记录和尝试更新该记录之间,该记录已被其他人更改

在ActiveRecord中实现乐观锁定很容易。您只需在模型中添加一列
lock\u version

迁移

add_column :posts, :lock_version, :integer
currently_editing(current_user.id, Time.zone.now) if @post.current_editor.nil?
if @post.current_editor == current_user.id
  currently_editing(nil, nil) if updating?
  currently_editing(nil, nil) if publishing?
end

你需要一个像
PostEditor
这样的新模型,它将
Post
User
组合在一个
m*n
关系中(我知道单个用户不太可能同时编辑多个帖子,但我认为这应该是可能的)

PostsController
中,您需要在
edit
操作中创建该连接。当用户保存帖子或离开页面时,您需要删除连接(查看更多相关信息)

此外,当另一个用户被添加到
Post
postdeditor
列表中时,
User
编辑
Post
并显示信息时,您需要对数据库进行一些重复的
Ajax
调用

最后,在保存时,您应该检查,如果当前
用户开始编辑后保存了
Post
,请取消保存过程并显示两个版本的
diff
,或者类似的内容。当然,您需要使用
互斥锁
同步
您的
更新
方法


我希望这能让你知道该怎么做:)

谢谢大家的回答。根据所有的答案,我做了我需要的。其他答案很好,但对于我想要实现的目标来说,要复杂一些

这就是我所做的

添加迁移以向post数据库添加两个新列

add_column :posts, :current_editor, :integer
add_column :posts, :editing_started_at, :timestamp
岗位控制员

private
def currently_editing(editor, time)
  @post.current_editor = editor
  @post.editing_started_at = time
  @post.save
end
在posts控制器中,编辑操作

add_column :posts, :lock_version, :integer
currently_editing(current_user.id, Time.zone.now) if @post.current_editor.nil?
if @post.current_editor == current_user.id
  currently_editing(nil, nil) if updating?
  currently_editing(nil, nil) if publishing?
end
在posts控制器中,创建操作

add_column :posts, :lock_version, :integer
currently_editing(current_user.id, Time.zone.now) if @post.current_editor.nil?
if @post.current_editor == current_user.id
  currently_editing(nil, nil) if updating?
  currently_editing(nil, nil) if publishing?
end
我还在
edit#posts
视图中添加了一个Cancel edit。如果用户不想更改任何内容

- if @post.current_editor == current_user.id
  = link_to 'Cancel Edit', post_path(@post, 'post[current_editor]' => '', 'post[editing_started_at]' => ''), method: :put
向希望编辑同一帖子的其他编辑显示通知

- if @post.current_editor != current_user.id
  %p Somebody else is editing this post now

您确实遗漏了必须将
lock\u version
添加到更新表单中的内容。此外,它只跟踪记录上的修改。这并不意味着确实发生了编辑。例如,它可以是触摸或后台进程。@slowjack2k我认为您不应该这样做,因为工作流是将记录从数据库加载到模型,为其字段指定新值,然后将其保存回数据库。字段
lock\u version
无论如何都是从数据库加载的。我认为工作流是编辑器A加载帖子并编辑它。编辑器B加载文章并对其进行编辑。编辑器B在更新操作中加载并保存帖子。编辑加载并在更新操作中保存帖子。当编辑器B在编辑器A加载其帖子之前保存帖子时,两篇帖子都会保存,因为
锁定版本
看起来正常。只有当编辑器B加载其记录,编辑器A加载其记录,编辑器B保存其记录,然后编辑器A的
保存
失败时,您的版本才会工作。如果用户不使用提供的后退按钮,而是使用浏览器中的后退按钮,会发生什么情况?您的解决方案是可行的,但是对于这个特定的用例,它失败了。那么你是如何处理这个用例的呢?