0.13
No release in over 3 years
Low commit activity in last 3 years
Add social network friendship features to your Active Record models.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies
 Project Readme

HasFriendship spec

Add friendship features to your ActiveRecord models.

HasFriendship allows ActiveRecord objects to send, accept, and decline friend requests using self-refernetial polymorphic association.

Getting started

Setup

To start using HasFriendship in an ActiveRecord Model, simply add has_friendship to the model file:

gem 'has_friendship'

When HasFriendship is bundled into your application, a new Rake task called has_friendship_engine:install:migrations will be added. Use this Rake task to generate the database migration, and then apply it to your project:

$ rails has_friendship_engine:install:migrations
$ # (inspect the migration files, and change if necessary)
$ rails db:migrate

By default, the friendship table uses integer as the friend_id datatype. If your project requires a different datatype, like a UUID, then you'll need to edit the migration file before running the migration.

Gem upgrades

After this gem is updated, there may be new migrations that are needed. If so, you will be prompted to rerun rails has_friendship_engine:install:migrations and apply the latest changes. (The rake task won't do anything if no new migrations are needed.)

Usage

Simply drop in has_friendship to a model:

class User < ActiveRecord::Base
  has_friendship
end

Managing friendship

Now, instances of User can send, accept, and decline friend requests:

@mac = User.create(name: "Mac")
@dee = User.create(name: "Dee")

# @mac sends a friend request to @dee
@mac.friend_request(@dee)

# @dee can accept the friend request
@dee.accept_request(@mac)

# @dee can also decline the friend request
@dee.decline_request(@mac)

A friendship can also be removed:

# @dee removes @mac from its friends
@dee.remove_friend(@mac)

Blocking a friendable

A friendable can be blocked. When blocked, the friendable cannot request or remove friendship to the one that initially blocked it.

@dee.request_friend(@mac)

# @mac blocks @dee from making any more friendship actions
@mac.block_friend(@dee)

# @mac unblocks @dee
# Only @mac can perform this action
@mac.unblock_friend(@dee)

Checking friendship

# Check if there is an accepted friendship between @mac and @dee
@mac.friends_with?(@dee)

Type of friends

There are four types of friends:

  • requested_friends
  • pending_friends
  • blocked_friends
  • friends

Each type returns an array of friends, which should be looped through to access specific friends. They can be accessed using association.

requested_friends

Instances that sent friend request that has not been accepted.

@mac.friend_request(@dee)

@dee.requested_friends # => [@mac]

pending_friends

Instances that received but has not accepted the friend request.

@mac.friend_request(@dee)

@mac.pending_friends # => [@dee]

blocked_friends

Instances that are blocked from taking any friendship actions

@dee.friend_request(@mac)
@mac.block_friend(@dee)

@mac.blocked_friends # => [@dee]

friends

Instances with accepted Friendship.

@mac.friend_request(@dee)
@dee.accept_request(@mac)

@mac.friends # => [@dee]
@dee.friends # => [@mac]

Custom validations

You can provide custom validations for the friendship by implementing friendship_errors method on your Friendable model.

Returning an array with any elements will result in the friendship not being established.

def friendship_errors(wannabe_friend)
  return if can_become_friends_with?(wannabe_friend)

  [
    "Cannot become friends with #{wannabe_friend.email}",
  ]
end

Callbacks

To use callbacks you can add methods described below to your Friendable model.

def on_friendship_created(friendship)
  ...
end

def on_friendship_accepted(friendship)
  ...
end

def on_friendship_blocked(friendship)
  ...
end

def on_friendship_destroyed(friendship)
  ...
end

How To Build

Clone the repo, go into the top directory, and run bundle install. Then, run bundle exec rake spec to run all the RSpec test cases. Finally, run bundle exec rake build to actually build the Gem.

Note that there is a small instance of Rails in the spec/ environment. If you need to make changes to Rails environment, and want to run the Rails commands, you should:

  1. cd spec/internal/
  2. bundle exec --gemfile ../../Gemfile -- ${your_command}

How to test

You can run the RSpec tests in your development environment by running bundle exec rake spec.

Or, if you wish to run the compatibility tests on different versions of Rails, you can run the Appraisals-based tests by running bundle exec appraisal rake spec.