Skip to content

Metabook is a clone of Facebook and has the functionality for profiles, newsfeeds, posts, comments, and likes.

Notifications You must be signed in to change notification settings

jzhou45/Metabook

Repository files navigation

Metabook

Brief Overview

Metabook is a clone of Facebook and has the functionality for profiles, newsfeeds, posts, comments, and likes.

Technologies Used

  • Ruby
  • Ruby on Rails
  • JavaScript
  • jQuery
  • React
  • Redux
  • npm/webpack/babel
  • AWS S3/IAM
  • Heroku

Splash

image

Newsfeed

metabook_newsfeed_AdobeExpress (2)

Posts

make_posts_AdobeExpress

Comments and Replies

comments_and_replies_AdobeExpress

Likes

likes_AdobeExpress

Profile

profile_AdobeExpress

Search

Screen_Recording_2022-09-16_at_7_52_24_PM_AdobeExpress

Code Snippets

To use comments with multiple foreign tables including itself, a polymorphic association had to be setup in the models and migration to reduce the need for having numerous foreign keys:

#app/models/comment.rb
class Comment < ApplicationRecord
    belongs_to :commentable,
        polymorphic: true

    has_many :comments,
        as: :commentable,
        class_name: :Comment,
        dependent: :destroy
end

#app/models/post.rb
class Post < ApplicationRecord
    has_many :comments,
        as: :commentable,
        dependent: :destroy 
end

A filter will then be set up to separate the two types of comments for posts, as it contains both parent comments and replies, whilst the comments only contain replies, hence not requiring a filter:

//frontend/components/newsfeed/post_item.jsx
{state.comments.map((comment, i) => {
    if (comment.commentable_type === "Post"){
        return(
            <Comment 
                key={i}
            />
        );
    };
})}

//frontend/components/newsfeed/comment_item.jsx
{(state.comments.map((reply, i) => {
    return(
        <Reply 
            key={i} 
        />
    );
}))}

Likes also had a similiar polymorphic setup, with the exception of having a uniquness validation to a user_id and the associated liked object, ridding the need for a filter on the frontend:

#app/models/like.rb
class Like < ApplicationRecord
    validates :user_id, uniqueness: { scope: [:likeable_id, :likeable_type]}
    
    belongs_to :likeable,
        polymorphic: true
end

#app/models/post.rb
class Post < ApplicationRecord
    has_many :likes,
        as: :likeable,
        dependent: :destroy
end

#app/models/comment.rb
class Comment < ApplicationRecord
    has_many :likes,
        as: :likeable,
        dependent: :destroy
end

For comments and replies, in order to perform multiple asynchronous fetch requests at once to set the state of a component, an async/await helper function was used to wait for promises before setting the state:

//frontend/components/newsfeed/comment_item.jsx
const fetchData = async () => {
    const userData = await fetchUser(comment.user_id);
    const commentData = await fetchComment(comment.id);

    setState({
        ...state,
        profilePhoto: userData.user.profilePhoto,
        firstName: userData.user.first_name,
        lastName: userData.user.last_name,
        comments: commentData.comment.comments,
        likes: commentData.comment.likes
    });
};

useEffect(() => {
    fetchData();
}, []);

Releases

No releases published

Packages

No packages published