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?
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)
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.
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>
.
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):
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>
.
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:
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
.
So we adjust the function typeCatch()
to:
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)
You might have to add this special route to Ruby on Rails (not sure about the following, my rails is a bit rusty):
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:
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:
@post.authors << current_user
Again: Thanks to @Micha, @user2257149 and @Michael Koper. I upvoted your answers.
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".
So currently EssayController
has a show
action like
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
<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.
UPDATE 2:
As @Yarek T stated, instead of $("#post").on("keypress", typeCatch);
the jQuery function one
can be used:
function typeCatch(){
$.ajax({
type: "POST",
url: '/posts/123/add_current_author',
data: JSON.stringify({_method: 'put'})
});
}
$("#post").one("keypress", typeCatch);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With