I want to add the user to a post's author
list when the user starts typing in a form.
我想在用户开始输入表单时将用户添加到帖子的作者列表中。
For example, when the user types any letter (or press the 'enter' button) in the form, I would call @post.authors.create(user_id: current_user.id)
to add the user to the list of authors of that specific post. I thought this would be impossible to implement, but using javascript to submit an ajax request might be sufficient to implement this method. Is it possible to achieve such method in a Rails application? If so, could anyone give me some directions?
例如,当用户在表单中键入任何字母(或按“输入”按钮)时,我会调用@ post.authors.create(user_id:current_user.id)将用户添加到该特定的作者列表中帖子。我认为这是不可能实现的,但使用javascript提交ajax请求可能足以实现此方法。是否有可能在Rails应用程序中实现此类方法?如果是这样,有人可以给我一些指示吗?
4 个解决方案
#1
3
For the following answer, I assume you are running Ruby on Rails with jQuery as javascript framework and have the current user (=author) logged in (i.e. the current user id in session). I'm explaining @Mischa's idea: Using the keypress event.
对于以下答案,我假设您使用jQuery作为javascript框架运行Ruby on Rails并且当前用户(= author)已登录(即会话中的当前用户ID)。我正在解释@Mischa的想法:使用按键事件。
So, as you explained, you have a form to edit a post. I guess you have a textarea inside there with the post's text. For example <textarea id="posting">This is a post</textarea>
.
因此,正如您所解释的,您有一个表单来编辑帖子。我猜你里面有一个textarea,帖子的文字。例如
Your next requirement was, to tell the server, "when the user types any letter (or press the 'enter' button) in the form". Hence we define an event handler, for the "keypress" event. This event handler should be removed, after the first key has been pressed. Thanks to @user2257149 for the following code (I adjusted it a little bit):
您的下一个要求是,告诉服务器,“当用户键入任何字母(或按”输入“按钮)时,”。因此,我们为“keypress”事件定义了一个事件处理程序。在按下第一个键之后,应删除此事件处理程序。感谢@ user2257149获取以下代码(我稍微调整了一下):
function typeCatch(){
$(this).off("keypress",typeCatch) // remove handler
console.log("User start type");
}
$("#post").on("keypress",typeCatch); // add handler
This javascript code fragment must be below the definition of the <textarea>
.
此javascript代码片段必须低于
Now we have an event handler which is only fired once. In this handler, we trigger an ajax call to let the server know, the current user is editing the current post. As we're updating a specific attribute in the post object, we should trigger something like the following URL:
现在我们有一个只触发一次的事件处理程序。在这个处理程序中,我们触发ajax调用让服务器知道,当前用户正在编辑当前帖子。当我们更新post对象中的特定属性时,我们应该触发类似以下URL的内容:
PUT http://www.example.com/posts/123/add_current_author
This means, we should use the HTTP PUT method to update the post with ID 123 and trigger method add_current_author in PostsController
.
这意味着,我们应该使用HTTP PUT方法更新ID为123的帖子和PostsController中的触发方法add_current_author。
So we adjust the function typeCatch()
to:
所以我们将函数typeCatch()调整为:
function typeCatch(){
$(this).off("keypress",typeCatch)//remove handler
$.ajax({
type: "POST",
url: '/posts/123/add_current_author',
data: JSON.stringify({_method: 'put'})
});
}
(As most browsers don't support the PUT method, Ruby on Rails tricks that by sending the POST parameter "_method", I got this from @Michael Koper in his answer to Ruby on rails - PUT method on update ajax)
(由于大多数浏览器不支持PUT方法,Ruby on Rails通过发送POST参数“_method”来欺骗它,我从@Michael Koper那里得到了关于Ruby on rails的回答 - 更新ajax上的PUT方法)
You might have to add this special route to Ruby on Rails (not sure about the following, my rails is a bit rusty):
您可能必须将此特殊路由添加到Ruby on Rails(不确定以下内容,我的rails有点生锈):
resources :posts do
collection do
put "add_current_author"
end
end
Now, in your PostsController
, you have to define method add_current_author
. I assume you instantiate @post
to be the actual post (identified by given :id
) in a before_filter
and have your current user saved in current_user
. So actually it should be as easy as:
现在,在PostsController中,您必须定义方法add_current_author。我假设你将@post实例化为before_filter中的实际帖子(由given:id标识),并将当前用户保存在current_user中。实际上它应该像以下一样简单:
def add_current_author
@post.authors.create(user_id: current_user.id)
end
Though I must admit, it looks a bit weird (it's what you suggested). I guess, I'd have a 1:n connection between "posts" and "users" called "authors" and do the following:
虽然我必须承认,它看起来有点奇怪(这是你的建议)。我猜,我在“posts”和“users”之间建立了1:n连接,称为“authors”,并执行以下操作:
@post.authors << current_user
Again: Thanks to @Micha, @user2257149 and @Michael Koper. I upvoted your answers.
再次感谢@Micha,@ user2257149和@Michael Koper。我赞成你的答案。
UPDATE: As stated in bounty comment, OP wants to change the current functionality from "mark read by user when shown" to "only mark as read, when user presses a key in comment form".
更新:正如赏金评论中所述,OP希望将当前功能从“用户在显示时读取的标记”更改为“仅当用户按评论形式按键时标记为已读”。
So currently EssayController
has a show
action like
所以目前EssayController有一个类似的节目动作
def show
...
@essay.reader_links.create(reader_id: current_user.id)
...
end
The given line should be removed, as current user should not be added when @essay
shown. Furthermore, the <textarea>
I defined above is the one in the comment form, so the HTML might look like
应删除给定的行,因为在显示@essay时不应添加当前用户。此外,我在上面定义的
<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>
Finally, action add_current_author
should not be, as I assumed, in PostController
but in EssayController
and the route changed respectively.
最后,动作add_current_author不应该像我假设的那样在PostController中但在EssayController中并且路径分别改变了。
UPDATE 2: As @Yarek T stated, instead of $("#post").on("keypress", typeCatch);
the jQuery function one
can be used:
更新2:正如@Yarek T所述,而不是$(“#post”)。on(“keypress”,typeCatch);可以使用jQuery函数:
function typeCatch(){
$.ajax({
type: "POST",
url: '/posts/123/add_current_author',
data: JSON.stringify({_method: 'put'})
});
}
$("#post").one("keypress", typeCatch);
#2
11
You must make event handler for keypress and remove after first press.
您必须为按键创建事件处理程序并在首次按下后删除。
function typeCatch(){
$(this).off("keypress",typeCatch)//remove handler
console.log("User start type");
}
$("$field_id").on("keypress",typeCatch)
#3
1
Has everyone forgot about jQuery's $.one()
function? Its functionally the same as doing $.on()
and then inside that $.off()
.
大家都忘记了jQuery的$ .one()函数吗?它的功能与$ .on()相同,然后在$ .off()内。
#4
0
var flag = 0;
$(document).on('keypress', function(e) {
if(flag == 0) {
doSomething();
flag = 1;
}
});
#1
3
For the following answer, I assume you are running Ruby on Rails with jQuery as javascript framework and have the current user (=author) logged in (i.e. the current user id in session). I'm explaining @Mischa's idea: Using the keypress event.
对于以下答案,我假设您使用jQuery作为javascript框架运行Ruby on Rails并且当前用户(= author)已登录(即会话中的当前用户ID)。我正在解释@Mischa的想法:使用按键事件。
So, as you explained, you have a form to edit a post. I guess you have a textarea inside there with the post's text. For example <textarea id="posting">This is a post</textarea>
.
因此,正如您所解释的,您有一个表单来编辑帖子。我猜你里面有一个textarea,帖子的文字。例如
Your next requirement was, to tell the server, "when the user types any letter (or press the 'enter' button) in the form". Hence we define an event handler, for the "keypress" event. This event handler should be removed, after the first key has been pressed. Thanks to @user2257149 for the following code (I adjusted it a little bit):
您的下一个要求是,告诉服务器,“当用户键入任何字母(或按”输入“按钮)时,”。因此,我们为“keypress”事件定义了一个事件处理程序。在按下第一个键之后,应删除此事件处理程序。感谢@ user2257149获取以下代码(我稍微调整了一下):
function typeCatch(){
$(this).off("keypress",typeCatch) // remove handler
console.log("User start type");
}
$("#post").on("keypress",typeCatch); // add handler
This javascript code fragment must be below the definition of the <textarea>
.
此javascript代码片段必须低于
Now we have an event handler which is only fired once. In this handler, we trigger an ajax call to let the server know, the current user is editing the current post. As we're updating a specific attribute in the post object, we should trigger something like the following URL:
现在我们有一个只触发一次的事件处理程序。在这个处理程序中,我们触发ajax调用让服务器知道,当前用户正在编辑当前帖子。当我们更新post对象中的特定属性时,我们应该触发类似以下URL的内容:
PUT http://www.example.com/posts/123/add_current_author
This means, we should use the HTTP PUT method to update the post with ID 123 and trigger method add_current_author in PostsController
.
这意味着,我们应该使用HTTP PUT方法更新ID为123的帖子和PostsController中的触发方法add_current_author。
So we adjust the function typeCatch()
to:
所以我们将函数typeCatch()调整为:
function typeCatch(){
$(this).off("keypress",typeCatch)//remove handler
$.ajax({
type: "POST",
url: '/posts/123/add_current_author',
data: JSON.stringify({_method: 'put'})
});
}
(As most browsers don't support the PUT method, Ruby on Rails tricks that by sending the POST parameter "_method", I got this from @Michael Koper in his answer to Ruby on rails - PUT method on update ajax)
(由于大多数浏览器不支持PUT方法,Ruby on Rails通过发送POST参数“_method”来欺骗它,我从@Michael Koper那里得到了关于Ruby on rails的回答 - 更新ajax上的PUT方法)
You might have to add this special route to Ruby on Rails (not sure about the following, my rails is a bit rusty):
您可能必须将此特殊路由添加到Ruby on Rails(不确定以下内容,我的rails有点生锈):
resources :posts do
collection do
put "add_current_author"
end
end
Now, in your PostsController
, you have to define method add_current_author
. I assume you instantiate @post
to be the actual post (identified by given :id
) in a before_filter
and have your current user saved in current_user
. So actually it should be as easy as:
现在,在PostsController中,您必须定义方法add_current_author。我假设你将@post实例化为before_filter中的实际帖子(由given:id标识),并将当前用户保存在current_user中。实际上它应该像以下一样简单:
def add_current_author
@post.authors.create(user_id: current_user.id)
end
Though I must admit, it looks a bit weird (it's what you suggested). I guess, I'd have a 1:n connection between "posts" and "users" called "authors" and do the following:
虽然我必须承认,它看起来有点奇怪(这是你的建议)。我猜,我在“posts”和“users”之间建立了1:n连接,称为“authors”,并执行以下操作:
@post.authors << current_user
Again: Thanks to @Micha, @user2257149 and @Michael Koper. I upvoted your answers.
再次感谢@Micha,@ user2257149和@Michael Koper。我赞成你的答案。
UPDATE: As stated in bounty comment, OP wants to change the current functionality from "mark read by user when shown" to "only mark as read, when user presses a key in comment form".
更新:正如赏金评论中所述,OP希望将当前功能从“用户在显示时读取的标记”更改为“仅当用户按评论形式按键时标记为已读”。
So currently EssayController
has a show
action like
所以目前EssayController有一个类似的节目动作
def show
...
@essay.reader_links.create(reader_id: current_user.id)
...
end
The given line should be removed, as current user should not be added when @essay
shown. Furthermore, the <textarea>
I defined above is the one in the comment form, so the HTML might look like
应删除给定的行,因为在显示@essay时不应添加当前用户。此外,我在上面定义的
<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>
Finally, action add_current_author
should not be, as I assumed, in PostController
but in EssayController
and the route changed respectively.
最后,动作add_current_author不应该像我假设的那样在PostController中但在EssayController中并且路径分别改变了。
UPDATE 2: As @Yarek T stated, instead of $("#post").on("keypress", typeCatch);
the jQuery function one
can be used:
更新2:正如@Yarek T所述,而不是$(“#post”)。on(“keypress”,typeCatch);可以使用jQuery函数:
function typeCatch(){
$.ajax({
type: "POST",
url: '/posts/123/add_current_author',
data: JSON.stringify({_method: 'put'})
});
}
$("#post").one("keypress", typeCatch);
#2
11
You must make event handler for keypress and remove after first press.
您必须为按键创建事件处理程序并在首次按下后删除。
function typeCatch(){
$(this).off("keypress",typeCatch)//remove handler
console.log("User start type");
}
$("$field_id").on("keypress",typeCatch)
#3
1
Has everyone forgot about jQuery's $.one()
function? Its functionally the same as doing $.on()
and then inside that $.off()
.
大家都忘记了jQuery的$ .one()函数吗?它的功能与$ .on()相同,然后在$ .off()内。
#4
0
var flag = 0;
$(document).on('keypress', function(e) {
if(flag == 0) {
doSomething();
flag = 1;
}
});