Bummer! This is just a preview. You need to be signed in with a Basic or Pro account to view the entire video.

Start a free Basic trial
to watch this video

Sign up for Treehouse

Managing Friendships


In our previous stages, we've learned how to create methods, add routes, do validations, and more. Now we're going to start putting it all together. We'll start by implementing user blocking.

Video Transcript

  • 0:01

    ?music? [treehouseā„¢]

  • 0:03

    [Building Social Features in Ruby on Rails] [Stage 5: Managing Friendships with Jason Seifer]

  • 0:06

    In previous stages, we've added the ability for users to request the friendship of other users.

  • 0:12

    They can also delete these friendships later.

  • 0:15

    In this stage, we're going to use all of the concepts that we learned in previous stages,

  • 0:19

    to let users block other users from requesting their friendship.

  • 0:24

    So, let's get started.

  • 0:30

    Okay. So, now what we're going to do is start managing our user friendships.

  • 0:36

    The first thing that we're going to do is let users block other users.

  • 0:41

    This is something that can happen on social networks--

  • 0:44

    maybe somebody doesn't like somebody else's status updates--

  • 0:47

    and we want to give them the option not to see them.

  • 0:49

    The first thing that we're going to do is add another state

  • 0:54

    in our user friendship class for being blocked.

  • 0:59

    So, let's go ahead and open up our user friendship model.

  • 1:04

    And what we'll be doing is putting the blocked state right up in here

  • 1:08

    inside of our state machine.

  • 1:12

    Now, before we do that, let's go ahead and write a test.

  • 1:21

    So, I'll go down to the bottom of the file here in the user friendship test,

  • 1:25

    and I will make a context for the block method,

  • 1:35

    and this will hold some of our logic for the block method with an exclamation point.

  • 1:42

    Now, the block method with the exclamation point is something that the state machine gen

  • 1:46

    adds for us once we create a state for it.

  • 1:51

    So, let's go ahead and set up a user friendship instance variable that we'll work with

  • 1:55

    in a couple of these tests.

  • 2:08

    And we'll use the request method,

  • 2:12

    and we'll use a couple of our user fixtures.

  • 2:18

    Now, the first thing that we'll do is make sure that the state on the user friendship

  • 2:22

    gets set to blocked.

  • 2:36

    And then we'll make sure that the state is now blocked

  • 2:38

    on the user friendship

  • 2:48

    Okay, now let's run this test and watch it fail since we haven't written this code yet.

  • 3:00

    Okay, and it looks like I misspelled this.

  • 3:03

    So, let's run it again, make sure we still get the correct failing test.

  • 3:08

    Okay, undefined method block--that's what we wanted.

  • 3:15

    So, let's go back to our user friendship model

  • 3:19

    and we'll make another state for this called "blocked."

  • 3:23

    And then we will also make an event for this "block"

  • 3:32

    which transitions any state to a blocked state.

  • 3:41

    Now, that should make our test pass.

  • 3:45

    Okay, great.

  • 3:47

    Now, the next thing that we want to do is make sure that we update that

  • 3:50

    mutual friendship object that we keep track of

  • 3:53

    because both users want to keep track of their friends lists,

  • 3:57

    so let's also make sure that the mutual friendship state is blocked as well.

  • 4:07

    And this should fail as well,

  • 4:09

    and it does, so let's go ahead and write the code to make that pass.

  • 4:19

    And we can kind of copy this after transition code right here,

  • 4:22

    except we'll change when it does it.

  • 4:24

    So, we'll say after the transition on the block,

  • 4:30

    let's block the mutual friendship.

  • 4:36

    Now, we haven't written that yet, so let's go ahead and write that down here.

  • 5:02

    And what we're doing down here is just updating the mutual friendship state attribute

  • 5:06

    to blocked if a mutual friendship is there,

  • 5:09

    and if not, we won't worry about it.

  • 5:12

    So, let's go ahead and run that again.

  • 5:16

    Okay, and that works as well.

  • 5:19

    Now, let's also make sure that when we go to request a user friendship after it's been blocked,

  • 5:26

    that the user cannot request that same person again

  • 5:31

    because it's already been blocked.

  • 5:32

    So, we'll write another test for that

  • 5:35

    saying that we should not allow new requests once blocked.

  • 5:44

    So, we'll block the user friendship and then try to create another one.

  • 5:52

    Okay, so that's blocked and we know it works because of the tests

  • 5:55

    starting on line 141, and now we'll just create another one.

  • 5:59

    We'll call that UF.

  • 6:13

    And we'll just assert that that can't be saved.

  • 6:19

    Okay, so that test failed like we expected it to.

  • 6:23

    Now, we're going to make this pass by writing another custom validation.

  • 6:30

    So, let's go ahead and go to the top of our model here,

  • 6:34

    and let's say after the state machine declaration

  • 6:39

    we put in our custom validation.

  • 6:42

    So, we'll just go ahead and say not blocked

  • 6:45

    and now we can go ahead and write our not blocked method.

  • 7:00

    And what we'll do is we'll add something to the list of active record errors

  • 7:04

    if a friendship has been blocked.

  • 7:10

    Now, we don't want to reveal too much about the friendship being blocked,

  • 7:14

    so we'll just say the friendship cannot be added.

  • 7:22

    And let's put this inside of an if statement.

  • 7:30

    Now, what we'll do is we'll first look up to see if a user friendship exists,

  • 7:34

    with either the user ID of the user going in or the friend ID that have any blocked state.

  • 8:10

    Okay. Let's go ahead and run this test now and see if it passes.

  • 8:17

    And it looks like we got an error saying that the validation failed

  • 8:21

    and the friendship cannot be added.

  • 8:23

    And this happened in our user friendship test on line 149,

  • 8:27

    and it came from our user friendship model line 28 in request.

  • 8:33

    So, let's go ahead and look at line 149 of our user friendship test.

  • 8:43

    And here we go--that's right here.

  • 8:46

    So, it looks like this is throwing an error.

  • 8:48

    Let's see what's going on.

  • 8:51

    And here is our request method, and it looks like we have the create method

  • 8:56

    throwing an error if for some reason the friendship can't be created.

  • 9:02

    So, what we'll do is, we'll change this right now,

  • 9:04

    and we'll say friendship1.send request e-mail if not friendship1.new record.

  • 9:19

    That way, if the record can't be created, we'll send back the friendship object

  • 9:24

    with the errors intact, and we'll only send the request e-mail if it was created and is valid.

  • 9:32

    So, now let's go ahead and clear our terminal screen and run this again.

  • 9:38

    Okay, and it looks like that all passes.

  • 9:40

    Now, let's go ahead and run all of our tests and see if anything errors out.

  • 9:50

    Okay, it looks like all of our tests pass which is great.

  • 9:53

    Now, the next thing I'm going to do is add a couple of more of these

  • 9:58

    "has many" associations here on the user model

  • 10:02

    for requested friends and blocked friends.

  • 10:10

    We'll go ahead and do that there, and we can just copy and paste this--

  • 10:13

    requested user friendships and requested friends.

  • 10:19

    State is requested. Source is friend. Okay, that looks good.

  • 10:29

    Now, I'll open up my user test.

  • 10:34

    And let's go ahead and say it should have many pending user friendships,

  • 10:43

    pending friends. Let's go ahead and run that and make sure it passes.

  • 10:57

    Okay, that passes.

  • 11:00

    We can go ahead and copy and paste that,

  • 11:02

    and do the same thing with requested.

  • 11:12

    All right. That looks good.

  • 11:13

    And we're going to add more for blocked friends later,

  • 11:16

    we'll do that in a separate video.

  • 11:20

    In our next video, we'll start working on the blocking UI.

Show full transcript


You have to sign up for Treehouse in order to create workspaces.

Sign up


You have to sign up for Treehouse in order to download course videos.

Sign up


  • Jason Seifer

    When not fighting web crime, Jason Seifer is a teacher at Treehouse. He's passionate about the web and programming. You can find Jason on Twitter at @jseifer and on his personal blog at jasonseifer.com.