diff --git a/app/models/comment.rb b/app/models/comment.rb index 0141c1ffa..5cfe5a2bd 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -11,6 +11,8 @@ class Comment < ActiveRecord::Base belongs_to :commentable, polymorphic: true belongs_to :user + has_many :inappropiate_flags, :as => :flaggable + default_scope { includes(:user) } scope :recent, -> { order(id: :desc) } diff --git a/app/models/debate.rb b/app/models/debate.rb index bd7936e73..4040ba6db 100644 --- a/app/models/debate.rb +++ b/app/models/debate.rb @@ -12,6 +12,7 @@ class Debate < ActiveRecord::Base acts_as_paranoid column: :hidden_at belongs_to :author, class_name: 'User', foreign_key: 'author_id' + has_many :inappropiate_flags, :as => :flaggable validates :title, presence: true validates :description, presence: true diff --git a/app/models/inappropiate_flag.rb b/app/models/inappropiate_flag.rb new file mode 100644 index 000000000..10c7efc17 --- /dev/null +++ b/app/models/inappropiate_flag.rb @@ -0,0 +1,41 @@ +class InappropiateFlag < ActiveRecord::Base + + belongs_to :user + belongs_to :flaggable, polymorphic: true, counter_cache: true, touch: :flagged_as_inappropiate_at + + scope(:by_user_and_flaggable, lambda do |user, flaggable| + where(user_id: user.id, + flaggable_type: flaggable.class.to_s, + flaggable_id: flaggable.id) + end) + + + class AlreadyFlaggedError < StandardError + def initialize + super "The flaggable was already flagged as inappropiate by this user" + end + end + + class NotFlaggedError < StandardError + def initialize + super "The flaggable was not flagged as inappropiate by this user" + end + end + + + def self.flag!(user, flaggable) + raise AlreadyFlaggedError if flagged?(user, flaggable) + create(user: user, flaggable: flaggable) + end + + def self.unflag!(user, flaggable) + flags = by_user_and_flaggable(user, flaggable) + raise NotFlaggedError if flags.empty? + flags.destroy_all + end + + def self.flagged?(user, flaggable) + by_user_and_flaggable(user, flaggable).exists? + end + +end diff --git a/app/models/user.rb b/app/models/user.rb index b6374f518..134f315fc 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -8,6 +8,7 @@ class User < ActiveRecord::Base has_one :administrator has_one :moderator has_one :organization + has_many :inappropiate_flags validates :first_name, presence: true, if: :use_first_name? validates :last_name, presence: true, if: :use_last_name? diff --git a/spec/models/inappropiate_flag_spec.rb b/spec/models/inappropiate_flag_spec.rb new file mode 100644 index 000000000..0ae831ee0 --- /dev/null +++ b/spec/models/inappropiate_flag_spec.rb @@ -0,0 +1,64 @@ +require 'rails_helper' + +describe InappropiateFlag do + + let(:user) { create(:user) } + let(:comment) { create(:comment) } + + describe '.flag!' do + + it 'creates a flag when there is none' do + expect { described_class.flag!(user, comment) }.to change{ InappropiateFlag.count }.by(1) + expect(InappropiateFlag.last.user).to eq(user) + expect(InappropiateFlag.last.flaggable).to eq(comment) + end + + it 'raises an error if the flag has already been created' do + described_class.flag!(user, comment) + expect { described_class.flag!(user, comment) }.to raise_error(InappropiateFlag::AlreadyFlaggedError) + end + + it 'increases the flag count' do + expect { described_class.flag!(user, comment) }.to change{ comment.reload.inappropiate_flags_count }.by(1) + end + + it 'updates the flagged_as date' do + expect { described_class.flag!(user, comment) }.to change{ comment.reload.flagged_as_inappropiate_at } + end + end + + describe '.unflag!' do + it 'raises an error if the flag does not exist' do + expect { described_class.unflag!(user, comment) }.to raise_error(InappropiateFlag::NotFlaggedError) + end + + describe 'when the flag already exists' do + before(:each) { described_class.flag!(user, comment) } + + it 'removes an existing flag' do + expect { described_class.unflag!(user, comment) }.to change{ InappropiateFlag.count }.by(-1) + end + + it 'decreases the flag count' do + expect { described_class.unflag!(user, comment) }.to change{ comment.reload.inappropiate_flags_count }.by(-1) + end + + it 'does not update the flagged_as date' do + expect { described_class.unflag!(user, comment) }.to_not change{ comment.flagged_as_inappropiate_at } + end + end + + end + + describe '.flagged?' do + it 'returns false when the user has not flagged the comment' do + expect(described_class.flagged?(user, comment)).to_not be + end + + it 'returns true when the user has flagged the comment' do + described_class.flag!(user, comment) + expect(described_class.flagged?(user, comment)).to be + end + end + +end