4

author当用户开始输入表单时,我想将用户添加到帖子列表中。

例如,当用户在表单中键入任何字母(或按“输入”按钮)时,我会调用@post.authors.create(user_id: current_user.id)将用户添加到该特定帖子的作者列表中。我认为这不可能实现,但使用 javascript 提交 ajax 请求可能足以实现此方法。是否可以在 Rails 应用程序中实现这种方法?如果是这样,有人可以给我一些指示吗?

4

4 回答 4

11

您必须为按键创建事件处理程序并在第一次按下后删除。

function typeCatch(){
  $(this).off("keypress",typeCatch)//remove handler
  console.log("User start type");
}

$("$field_id").on("keypress",typeCatch)
于 2013-04-08T18:27:17.930 回答
3

对于以下答案,我假设您正在使用 jQuery 作为 javascript 框架运行 Ruby on Rails,并且当前用户 (=author) 已登录(即会话中的当前用户 ID)。我在解释@Mischa 的想法:使用按键事件。

因此,正如您所解释的,您有一个表单来编辑帖子。我猜你里面有一个带有帖子文本的文本区域。例如<textarea id="posting">This is a post</textarea>.

您的下一个要求是,告诉服务器“当用户在表单中键入任何字母(或按“输入”按钮)时”。因此,我们为“keypress”事件定义了一个事件处理程序。在按下第一个键后,应删除此事件处理程序。感谢@user2257149 提供以下代码(我稍微调整了一下):

    function typeCatch(){
      $(this).off("keypress",typeCatch) // remove handler
      console.log("User start type");
    }

    $("#post").on("keypress",typeCatch); // add handler

此 javascript 代码片段必须低于<textarea>.

现在我们有一个只触发一次的事件处理程序。在这个处理程序中,我们触发一个 ajax 调用来让服务器知道当前用户正在编辑当前帖子。当我们更新 post 对象中的特定属性时,我们应该触发类似以下 URL 的内容:

PUT http://www.example.com/posts/123/add_current_author

这意味着,我们应该使用 HTTP PUT方法来更新 ID 为123的帖子并触发方法add_current_author in PostsController

所以我们将函数调整typeCatch()为:

function typeCatch(){
  $(this).off("keypress",typeCatch)//remove handler
  $.ajax({
    type: "POST",
    url: '/posts/123/add_current_author',
    data: JSON.stringify({_method: 'put'})
  });
}

(由于大多数浏览器不支持 PUT 方法,Ruby on Rails 通过发送 POST 参数“_method”来欺骗,我从@Michael Koper 在他对 Ruby on rails - PUT method on update ajax 的回答中得到了这个)

您可能必须将此特殊路线添加到 Ruby on Rails(不确定以下内容,我的 Rails 有点生锈):

resources :posts do
  collection do
    put "add_current_author"
  end
end

现在,在您的 中PostsController,您必须定义 method add_current_author。我假设您实例化为a@post中的实际帖子(由 given 标识:idbefore_filter并将您当前的用户保存在current_user. 所以实际上它应该很简单:

def add_current_author
  @post.authors.create(user_id: current_user.id)
end

虽然我必须承认,它看起来有点奇怪(这是你的建议)。我想,我会在“帖子”和称为“作者”的“用户”之间建立 1:n 连接,并执行以下操作:

@post.authors << current_user

再次感谢@Micha、@user2257149 和@Michael Koper。我赞成你的答案。

更新: 如赏金评论中所述,OP 希望将当前功能从“显示时标记为已读”更改为“仅在用户按下评论表单中的键时标记为已读”。

所以目前EssayController有一个show动作

def show
  ...
  @essay.reader_links.create(reader_id: current_user.id)
  ...
end

应该删除给定的行,因为在显示时不应添加当前用户@essay。此外,<textarea>我在上面定义的是评论表单中的那个,所以 HTML 可能看起来像

<html>
  ...
  <form action="essay/123/comment" method="post">
    ...
    <textarea name="comment_text" id="comment"></textarea>
    ...
  </form>
  <script type="text/javascript">
    function typeCatch() {
      ...
    }
    $("#post").on("keypress", typeCatch);
  </script>
</html>

最后,正如我所假设的,actionadd_current_author不应该是 inPostController而是 inEssayController和 route 分别改变了。

更新 2:正如@Yarek T 所说,可以使用$("#post").on("keypress", typeCatch);jQuery 函数 代替:one

function typeCatch(){
  $.ajax({
    type: "POST",
    url: '/posts/123/add_current_author',
    data: JSON.stringify({_method: 'put'})
  });
}
$("#post").one("keypress", typeCatch);
于 2013-04-19T13:50:12.253 回答
1

Has everyone forgot about jQuery's $.one() function? Its functionally the same as doing $.on() and then inside that $.off().

于 2013-04-21T00:20:58.230 回答
0
var flag = 0;
$(document).on('keypress', function(e) {
    if(flag == 0) {
         doSomething();
         flag = 1;
    }   
});
于 2013-04-17T09:44:13.347 回答