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的保存失败时,您的版本才会工作。如果用户不使用提供的后退按钮,而是使用浏览器中的后退按钮,会发生什么情况?您的解决方案是可行的,但是对于这个特定的用例,它失败了。那么你是如何处理这个用例的呢?