2014-10-19 59 views
0

我有一个帖子系统,同一组中的所有用户都可以看到相同的帖子并编辑同一帖子。但是,如果我例如编辑帖子,并且我的朋友编辑同一帖子,那么我遇到了问题,那么我或我的朋友会失去我们刚刚做出的更改,并且只有最后一次保存的内容才会被保存。页面权限,用户组ROR

所以我的问题是: 有什么方法可以限制两个用户从同一组在同一时间看到相同的帖子。 因此,如果我例如正在编辑帖子,我的朋友在帖子即时通讯中按下编辑,他会收到一条消息(Nicolai正在编辑此帖子,等待他完成),当我离开编辑页面时,他和他人我所在的同一组将能够再次编辑该帖子。但是只有一个。

我在rails 4上使用Ruby,并设计用户注册。

我不知道如何做到这一点。 希望有人能给我一个想法或一些灵感来做到这一点。

在此先感谢。

回答

1

我想你可能需要看看从Active Record的乐观和悲观锁定:http://api.rubyonrails.org/classes/ActiveRecord/Locking/Optimistic.html

这可以帮助你保护系统免受造成同时访问同一记录错误,但没有解决的问题用户无法真正打开编辑页面。

简单的解决方案是设置一个标志(db中的列),它将设置记录上的锁定。您更新访问编辑页面的锁定并清除保存。听上去怎么样?

+0

听起来很有趣。我会毫不犹豫地阅读。感谢您的链接。但我可能很快就会有另一种解决方案。如果用户全部准备好在页面上,将会警告新用户。 – niiicolai 2014-10-19 19:45:49

0

如果您有一个railscasts订阅,以下是乐观锁定的一个很好的资源。这不完全是你想要的,但一个较少侵入性的替代品optimistic locking

另一种选择是pessimistic locking。这将允许您使用活动记录来实际锁定数据库记录。然后,您可以检查该记录上的锁定以禁用编辑按钮(或类似的东西)。这将是更多的工作来完成,但听起来像悲观锁定是你想要的。

+0

感谢您的建议。 – niiicolai 2014-10-19 20:45:08

0

SASS为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 

帖子表有以下字段:

标题,内容,状态。


我真的很喜欢这个解决方案,但所有它实际上做的是提醒其他用户已在编辑他要编辑的帖子的用户。

因此,用户可以使用他的浏览器“控件元素”功能来删除警告。 因此,我会研究“悲观锁定”以使其安全。

享受..请告诉我,如果你知道更好的方法。