Skip to content

Commit

Permalink
✨ create Follow model
Browse files Browse the repository at this point in the history
  • Loading branch information
karinevieira committed Jul 6, 2024
1 parent 02e2d3c commit 9d4a21e
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 3 deletions.
18 changes: 18 additions & 0 deletions app/models/follow.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# frozen_string_literal: true

class Follow < ApplicationRecord
belongs_to :follower, class_name: "User", inverse_of: :follower_follows
belongs_to :followed, class_name: "User", inverse_of: :followed_follows

validates :follower, uniqueness: { scope: :followed_id }

validate :follower_and_followed_cannot_be_the_same

private

def follower_and_followed_cannot_be_the_same
return unless follower_id == followed_id

errors.add(:base, :follower_and_followed_cannot_be_the_same)
end
end
6 changes: 6 additions & 0 deletions app/models/user.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ class User < ApplicationRecord

has_one :profile, class_name: "UserProfile", dependent: :destroy

has_many :follower_follows, class_name: "Follow", inverse_of: :follower, dependent: :destroy,
foreign_key: "follower_id"
has_many :following, through: :follower_follows, source: :followed
has_many :followed_follows, class_name: "Follow", inverse_of: :followed, dependent: :destroy,
foreign_key: "followed_id"
has_many :followers, through: :followed_follows, source: :follower
has_many :likes, dependent: :destroy
has_many :posts, dependent: :destroy

Expand Down
10 changes: 10 additions & 0 deletions config/locales/pt-BR/models/core.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
pt-BR:
activerecord:
models:
follow: Seguir
like: Curtida
post: Publicação
user_profile: Perfil
user: Usuário

attributes:
follow:
follower: Seguidor
followed: Seguido

like:
post: Publicação
user: Usuário
Expand All @@ -26,3 +31,8 @@ pt-BR:
user:
email: E-mail
password: Senha

errors:
models:
follow:
follower_and_followed_cannot_be_the_same: Não é possível seguir a si mesmo
14 changes: 14 additions & 0 deletions db/migrate/20240706163329_create_follows.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

class CreateFollows < ActiveRecord::Migration[7.0]
def change
create_table :follows, id: :uuid do |t|
t.references :follower, null: false, foreign_key: { to_table: :users }, type: :uuid
t.references :followed, null: false, foreign_key: { to_table: :users }, type: :uuid

t.timestamps
end

add_index :follows, %i[follower_id followed_id], unique: true
end
end
14 changes: 13 additions & 1 deletion db/schema.rb

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions spec/factories/follows_factories.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# frozen_string_literal: true

FactoryBot.define do
factory :follow do
association :follower, factory: :user, strategy: :create
association :followed, factory: :user, strategy: :create
end
end
40 changes: 40 additions & 0 deletions spec/models/follow_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# frozen_string_literal: true

require "rails_helper"

RSpec.describe Follow do
describe "associations" do
it { is_expected.to belong_to(:follower).class_name("User").inverse_of(:follower_follows) }
it { is_expected.to belong_to(:followed).class_name("User").inverse_of(:followed_follows) }
end

describe "validations" do
it "validates uniqueness of the pair follower_id and followed_id" do
follow = create(:follow)

expect(follow).to validate_uniqueness_of(:follower).scoped_to(:followed_id)
end

context "when follower and followed are the same" do
it "adds an error message to :base" do
user = create(:user)
follow = described_class.new(follower: user, followed: user)
follow.valid?

error_message = I18n.t("activerecord.errors.models.follow.follower_and_followed_cannot_be_the_same")

expect(follow.errors[:base]).to include(error_message)
end
end

context "when follower and followed aren't the same" do
it "doesn't add an error message to :base" do
follow = create(:follow)

error_message = I18n.t("activerecord.errors.models.follow.follower_and_followed_cannot_be_the_same")

expect(follow.errors[:base]).not_to include(error_message)
end
end
end
end
17 changes: 15 additions & 2 deletions spec/models/user_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,23 @@

RSpec.describe User do
describe "associations" do
it { is_expected.to have_many(:likes) }

it { is_expected.to have_one(:profile) }

it do
expect(described_class.new).to have_many(:follower_follows).class_name("Follow").inverse_of(:follower)
.dependent(:destroy).with_foreign_key("follower_id")
end

it do
expect(described_class.new).to have_many(:followed_follows).class_name("Follow").inverse_of(:followed)
.dependent(:destroy).with_foreign_key("followed_id")
end

it { is_expected.to have_many(:following).through(:follower_follows).source(:followed) }
it { is_expected.to have_many(:followers).through(:followed_follows).source(:follower) }
it { is_expected.to have_many(:likes) }
it { is_expected.to have_many(:posts) }

it { is_expected.to accept_nested_attributes_for(:profile) }
end

Expand Down

0 comments on commit 9d4a21e

Please sign in to comment.