我有一个帖子系统,同一组中的所有用户都可以看到相同的帖子并编辑同一个帖子。但我有一个问题,如果我是编辑一个帖子,我的朋友编辑相同的帖子,然后我或我的朋友将失去我们刚刚做的更改,只有内容最后保存他们的计数。
所以我的问题是: 有什么方法可以限制来自同一组的两个用户一次看到相同的帖子。 因此,如果我正在编辑帖子而我的朋友在帖子中按下编辑,他将收到一条消息(Nicolai正在编辑此帖子,等到他完成后),当我离开编辑页面时他和其他人都来自同一个帖子第一组将能够再次编辑该帖子。但是时间只有一个。
我在rails 4上使用Ruby并设计用户注册。
我不知道如何做到这一点。 希望有人可以给我一个想法或一些灵感来做到这一点。
提前致谢。
答案 0 :(得分:1)
我认为您可能需要查看Active Record中的乐观和悲观锁定:http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html
这可以帮助您保护系统免受因同时访问相同记录而导致的错误,但无法解决用户无法实际打开编辑页面的问题。
简单的解决方案是设置一个标志(db中的列),它将设置记录上的锁定。您在访问编辑页面时更新锁定并清除保存。这听起来怎么样?
答案 1 :(得分:0)
如果您有railscasts订阅,以下是乐观锁定的良好资源。这不是你想要的,而是一个不那么具有侵入性的替代optimistic locking
另一种选择是pessimistic locking。这将允许您使用活动记录来实际锁定db记录。然后,您可以检查该记录上的锁定以禁用编辑按钮(或类似的东西)。这将是更多的工作要完成,但听起来像悲观锁定是你想要的。
答案 2 :(得分:0)
SASS for edit.html.haml
.editingback
position: absolute
width: 100%
height: 102%
background: rgba(0, 0, 0, 0.3)
z-index: 500
display: none
.editing
z-index: 501
width: 300px
height: 150px
background: #eee
border: 1px solid #adadad
border-radius: 3px
position: absolute
top: 40%
left: 50%
transform: translate(-50%, -50%)
box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.5)
font-family: $la
padding: 15px
text-align: center
font-size: 13px
display: none
#editing_button
border: 1px solid #eee
background: #383838
color: white
padding: 7px
edit.html.haml
.editingback
.editing
= @post.state
is editing this post at the moment, please try again later!
%br
%br
= link_to 'OK', posts_path, id: 'editing_button'
= form_for (@post) do |f|
= f.text_field :title
= f.text_area :content
= f.submit 'Create'
:javascript
var pageid = '<%= @post.id %>';
var statevalue = '<%= @post.state %>';
var currentuser = '<%= current_user.email %>';
window.onload = checkstate();
function checkstate() {
if (statevalue == "") { // If statevalue is equal to "" it will send a ajax request to the updatestate action with the posts id. //
$.ajax({
url : '/posts/changestate/' + pageid,
type : 'POST',
data : $('#changenotestate').serialize(),
});
window.onbeforeunload = removestate; // When the user leave the site will it run the removestate function to remove state //
} else if (statevalue != currentuser) { // If a new user enter the page after you and the statevalue not is equal to the currentuser, show the warning //
$(".editingback").show();
$(".editing").fadeIn(2000);
} else {
}
};
// A function there will send a ajax request to the removestate action //
function removestate(){
$.ajax({
url : '/posts/removestate/' + pageid,
type : 'POST',
data : $('#changenotestate').serialize(),
});
};
posts_controller.rb
def edit ## Edit post action
@post = Post.find(params[:id])
end
def update ## Update post action
@post = Post.find(params[:id])
@post.update(post_params)
if @post.save
redirect_to posts_path
else
render 'edit'
end
end
def updatestate ## Action there will add current_user.email to the state field
@post = Post.find(params[:id])
@post.update(:state => current_user.email)
redirect_to :back
end
def removestate ## Action there will remove current_user.email to the state field
@post = Post.find(params[:id])
@post.update(:state => '')
redirect_to :back
end
的routes.rb
resources :posts # RESTFULL ROUTES
post '/posts/changestate/:id' => 'posts', :action => 'updatestate' #ROUTE TO UPDATE POST STATE
post '/posts/removestate/:id' => 'posts', :action => 'removestate' # ROUTE TO REMOVE POST STATE
帖子表包含以下字段:
Id,Title,Content,State。
我真的很喜欢这个解决方案,但它实际上只是警告用户另一个用户已经在编辑他想要编辑的帖子。
因此用户可以使用他的浏览器“控制元素”功能来删除警告。 因此,我会研究“悲观锁定”以确保其安全。
享受..如果你知道更好的方法,请告诉我。
答案 3 :(得分:0)
我想你可以看看semaphores和他们implementation in Ruby with Redis。
通过使用它们,您可以限制一次只能访问一个人(但是您必须自己编写所有逻辑) - redis为您提供了非常好的工具atomic operations。