Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed Rails 8 Course - Beginner to Intermediate!
Preview
Video Player
00:00
00:00
00:00
- 2x 2x
- 1.75x 1.75x
- 1.5x 1.5x
- 1.25x 1.25x
- 1.1x 1.1x
- 1x 1x
- 0.75x 0.75x
- 0.5x 0.5x
This video demonstrates how to implement a dynamic like button in a Rails application using Turbo Frames and Turbo Streams, allowing users to like and unlike posts, updating the like counter in real-time.
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
Okay, so the next thing on our to do
list is to add a dynamic like button.
0:00
As you can see on the screen now,
there's a like button.
0:03
And if I like it, it adds or
increments to the like counter.
0:05
In this case,
it decremented because I unliked it.
0:08
If I add it, it makes it red and
also adds one to the like counter.
0:10
So we're just gonna add this simple
like button to our application.
0:14
It works exactly the same way as Twitter.
0:17
So let's get started.
0:19
Okay, guys, the first thing that we're
going to do is run a command to generate
0:20
a resource for the likes.
0:23
So stop the server and
hit do clear, as we always do.
0:24
And in this case, we're going to run
a command called rails g resource like.
0:28
And then because it's gonna be
attached to two other models.
0:33
The first one is the user model,
because each user will have a liked post.
0:37
So the user has many likes.
0:41
This is called a bi-directional
relationship because the user has
0:43
many likes and
the likes belong to the user,
0:46
and then also the likes belong to
the post and the post has many likes.
0:49
So to do that, we're gonna have to put in
post references and user colon references.
0:53
This essentially establishes
that the user has many likes,
1:00
and the post has many likes, and
that the like belongs to the post and
1:03
that the like also belongs to the user.
1:06
So let's enter on that command and
then run rails db migrate.
1:09
Now that we've got that out the way, we're
gonna run our server again with rails s.
1:12
Okay, so the first thing that we're going
to do is go to config routes rb and
1:16
inside of here, just like the comments,
we're going to have to nest the likes
1:19
inside of the posts, and that's
because the likes belong to the posts.
1:23
So take this resources likes and
1:26
put it inside the post resources
inside of the do block.
1:28
This is called a do block.
1:31
And so just like the comments,
we're gonna go posts 1/likes.
1:32
If we were actually going to go to the
likes link, next we're going to go to app
1:36
controllers and we've got a new controller
here called the likes controller.
1:39
And inside of here is where we're
gonna do the bulk of our work.
1:42
We need to have two methods,
one that creates a like and
1:44
one that destroys a like so that we
can actually like and unlike a post.
1:47
So let's go ahead and do that.
1:50
We're first going to
create the create method.
1:51
So we're gonna do def create then end.
1:53
And it's not gonna be that complicated.
1:55
We're gonna do @post.likes.create and
then we're gonna search for the user and
1:56
the user is gonna be the current_user.
2:01
And then we're gonna say
render turbo_stream and
2:03
we're gonna say turbo stream.replace and
then we're gonna say like section and
2:06
then we'll pass in the post id and
then we're gonna do partial.
2:12
So the partial.
2:17
And then we're gonna say
posts/like_section which is a partial that
2:18
we have yet to create.
2:22
And then we're gonna do another comma and
we're gonna say locals and
2:23
that's gonna be post is @post.
2:27
And that's because we have to
pass the post variable for
2:29
the partial to actually understand.
2:31
Then we're gonna copy this method again
and instead of post.likes.create,
2:33
we're gonna do post.likes.find_by.
2:38
And then we're gonna do current user so
2:40
that the current user only has one like,
right?
2:42
And then we will say and.destroy.
2:44
So that's going to destroy the likes.
2:47
And we can leave this exactly the same.
2:49
Now this @post variable we have to.
2:50
It isn't coming from the sky,
we have to actually define it.
2:52
So at the top we're gonna do
before underscore action and
2:54
we're gonna call it set post.
2:57
This is the same as if we
go to the post controller.
2:58
It's the same way they do it there.
3:00
So it says before action set post.
3:02
And if we actually look at the set post,
3:05
it's just finding the post
via a param called id.
3:07
So let's just copy that and that's gonna
work for our likes inside of the action.
3:10
So we're gonna do,
I might just copy the whole.
3:14
Actually, no, it's fine.
3:16
So def set underscore post and
then end and
3:17
then copy that in there at post
is @post.findparams.expect.id.
3:20
That should be all working.
3:26
And that's it for the Lex controller.
3:27
I might have forgot to mention this, but
3:29
make sure to add method
post outside of this.
3:31
So make sure to have the method
post outside of that.
3:33
Next we're gonna search up font
awesome cdn, because we need that for
3:36
the actual like button itself,
the heart icon.
3:40
So let's go ahead and search up font
awesome the cdn and we should get the cdn.
3:43
So we're gonna copy and paste this.
3:47
Then we're gonna go to the posts view.
3:49
So go to views, posts,
posts and then show.
3:51
And we're gonna copy this
at the top of the page.
3:55
So do link.
3:58
And then we're gonna do href
just means the locations.
3:59
Then copy that in there and then we're
gonna say rel is equal to stylesheet so
4:03
that we know that it's a style sheet.
4:07
Now that we've done that, we have
access to everything on font awesome,
4:09
which has like icons,
which is really useful.
4:12
And now we're actually going
to write our like section.
4:14
So we're gonna do turbo frame.
4:17
And then the id is gonna be
equal to the inside of here.
4:20
We're gonna say like section and
then we're gonna pass in
4:24
the ruby of post.id because
we want it to be unique.
4:29
And then inside of here we're gonna
say render partial and we're gonna
4:34
say like section, like underscore section,
like underscore section.
4:39
And we also need to pass
in the post variable.
4:44
So let's pass in the post variable.
4:46
Post is equal to app post.
4:48
And then we're going to write turbo frame
to end off that Turbo frame tag because
4:50
it's just a HTML tag.
4:53
We can also get it in rails, but we're
just using the HTML to simplify things.
4:55
Now we're just going to
delete this likes folder,
4:57
we don't actually need that
because there's nothing in there.
4:59
And now we're actually going to create
a new partial called underscore,
5:02
like_section.HTML.erb.
5:06
In the post folder, you have to start
every partial with an underscore,
5:08
that's why we did that.
5:11
And inside of here we're going to
actually add another turbo frame.
5:13
So I'm just gonna go back to the show
page, copy and paste this turbo frame and
5:15
then put it inside of the like section.
5:19
And then we'll also have
the ending tag turbo frame.
5:21
And then inside of here we're
gonna create an if statement.
5:24
So we're gonna do if at
post likes that exist,
5:25
then we'll pass in a user current_user.
5:31
Then we're gonna show an unlike button.
5:36
And if not,
then we're gonna show an like button.
5:39
So do end else and end.
5:42
So inside of the first one for
the unlike button we're gonna do
5:45
button underscore to,
post underscore like underscore path.
5:48
Then we're gonna pass in
the outpost variable and
5:52
then we're gonna do @post.likes.find
underscore by user is gonna be
5:55
the current underscore user and
the method is going to be delete.
5:59
Then we'll just create a do block.
6:04
And then inside of here
we're going to add an icon.
6:05
So have an add tag there.
6:07
And so the icon is gonna be I and a class.
6:09
And we're gonna say fast far heart and
6:11
then we're gonna say style and
then it's gonna be color is red.
6:14
We're gonna have that.
6:19
And then for the actual like button, we're
just gonna copy and paste this in there.
6:22
But instead of the method delete, we're
gonna have the method post actually make
6:25
sure to have a colon before delete and
post like that.
6:28
And then we're also gonna get rid of
the this part, so we don't need that.
6:31
And then the color of
the icon is gonna be gray.
6:35
And then we also need to
add another end tag too.
6:38
I'm just gonna fix up this
formatting a little bit.
6:40
And then just before the end
we're going to add a div.
6:42
And inside of this div is gonna
be the actual post like count.
6:45
So we're gonna do Ruby sign and
then @post.likes.count, simple.
6:48
Okay, so now that we've completed our
controller, we've completed the view,
6:54
we've completed the show page and
we've completed the partial.
6:57
We've also done the routes.
6:59
This should all work.
7:01
And the like button should be working.
7:02
So let's test our solution.
7:03
Okay, so I'm on the web page now and
I'm just gonna sign in.
7:04
Okay, and now that I'm signed in,
I'm actually going to create a new post.
7:07
So I'm gonna click create post.
7:10
So I click create post and I'm getting
this error undefined method likes for
7:12
an instance of post.
7:15
Let's go and see our post model to see
if the connections are actually there.
7:16
Go to post B and as you can see,
it says has many comments,
7:19
but it does not say has many likes.
7:22
So inside of here we're gonna
say has many and then likes.
7:24
And hopefully that fixes our issue.
7:27
We're also gonna do the same thing for
the actual user.
7:29
So the user is gonna have many likes too.
7:31
So refresh and as you can see it says
the post is successfully created.
7:34
So let's go and see.
7:37
And so if we go to posts,
as you can see now there's a new post.
7:38
If we actually go and show this post,
we're getting an error.
7:41
It says undefined method exists for
an instance of if we go to VS code,
7:44
it looks like I'm just
forgetting the question mark.
7:48
So let's go to that place,
it should be in here.
7:51
And we're just gonna add a question
mark at the end of exists and
7:55
that should fix that issue.
7:59
And then we're getting another error and
it says undefined method like and
8:00
we need to make that likes.
8:03
I just, I'm getting a routing error.
8:04
We're going to post/1/like/1 method post.
8:06
Looks like the actual route
is wrong in the link itself.
8:10
So I'm just gonna change this to likes.
8:13
So post likes pass.
8:15
And now if we go back to the post,
we should be able to like it with ease.
8:16
Now we're getting another error,
just full of errors and
8:19
we're saying param is missing or
the value is empty or invalid id.
8:22
So we're just going to go to
the post to that likes controller.
8:26
And so
at the bottom here in the set post method,
8:29
instead of saying params expect
we're just gonna pass in params.
8:31
And then inside of here we're gonna
pass in post_id because if we
8:35
actually go to the like section,
we are passing the post and so
8:39
that means that we're also passing
the post id and that way we can find
8:43
the post via the post id instead of
the id of the post, if you get that.
8:48
So we're gonna refresh and hopefully
we'll be able to like the thing now.
8:53
And I'm getting yet another error.
8:56
It says wrong number of arguments.
8:57
It looks like I'm forgetting
the square brackets there.
8:59
So I'm just going to go to VS code and
then go to likes controller and
9:01
then inside of here I'll
add the square brackets.
9:05
So just wrap the post id in square
brackets instead of parentheses and
9:08
then we should be good to go.
9:12
So I'm gonna try one more time.
9:14
Somehow nothing is happening
when I click the button.
9:15
We need to go to VS code and
9:17
then we need to make sure that this post
id here is actually being recognized.
9:18
So make sure to add a hashtag before there
to make it so that it actually shows up.
9:22
Now if we try again and I just
realized we have two create methods,
9:26
so we're gonna make one
of them a destroy method.
9:28
So do def destroy.
9:31
And then now if we go back,
actually working.
9:32
And so, yeah, this is the light counter
using turbo frames and turbo Stream.
9:35
The likes are not real time, however,
they are updating for the actual user.
9:38
Just to give you an overview
of what's happening.
9:41
If we go to the show page, this is
a turbo frame, which is like a marker and
9:43
this is a partial
rendering the like section.
9:46
So if we go to the like section,
let's say we actually like.
9:48
Then we press this button,
we go to the post_likes_path and
9:51
we pass in the post variable.
9:54
Then let's follow that and
let's go to the likes controller.
9:56
And inside of here we're actually creating
a like for that post and for that user.
10:00
And then with this line of code,
with this render turbo stream,
10:04
we are updating the original turbo frame,
this one here,
10:07
and we are updating it
with the like section.
10:10
That way the like counter updates.
10:13
Because this is essentially
refreshing with the new information.
10:15
Because we're also passing
in the post variable.
10:18
And so that's why it works and
that's why it's dynamic.
10:20
Okay, so our application is looking good.
10:22
We've got a light counter, we've got real
time comments which work real time and
10:23
they work very well.
10:27
We've got images and application,
10:29
we've got usernames,
we've got user authentication.
10:30
It's really going well.
10:32
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up