Skip to content

Commit

Permalink
Refactor callbacks (#4)
Browse files Browse the repository at this point in the history
* Create accepting follow request functionality

* Update readme

* Refactor callback methods

* Return affected record when callback functions are triggered

* Update readme

* Add myself guard to actions
  • Loading branch information
nejdetkadir authored Oct 15, 2022
1 parent 889787c commit 10e9737
Show file tree
Hide file tree
Showing 5 changed files with 158 additions and 22 deletions.
60 changes: 59 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ Avaiable methods:
@bar.decline_follow_request_of(@foo)
# => true

@bar.accept_follow_request_of(@foo)
# => false

@bar.errors.full_messages
# => [...]

@foo.remove_follow_request_for(@bar)
# => false

Expand All @@ -82,6 +88,7 @@ Avaiable methods:

@foo.errors.full_messages
# => [...]

```

### Blocking actions
Expand Down Expand Up @@ -115,7 +122,7 @@ Avaiable methods:
class User < ActiveRecord::Base
followability

def on_request_sent(record)
def follow_request_removed_by_someone(record)
unless myself?(record)
# Do something
end
Expand Down Expand Up @@ -157,21 +164,72 @@ Avaiable methods:
# => [#<User ...>]
```

### Callback Methods
Available methods:
- follow_request_sent_to_me
- follow_request_sent_to_someone
- follow_request_accepted_by_me
- follow_request_accepted_by_someone
- follow_request_declined_by_me
- follow_request_declined_by_someone
- follow_request_removed_by_me
- follow_request_removed_by_someone
- followable_blocked_by_me
- followable_blocked_by_someone
- followable_unblocked_by_me
- followable_unblocked_by_someone
- followability_triggered

### Usage
```ruby
class User < ActiveRecord::Base
followability

def follow_request_sent_to_me(record)
Notifications::FollowRequestSentToMeJob.perform_later(from_id: record.id)
end
def follow_request_sent_to_someone(record); end
def follow_request_accepted_by_me(record); end
def follow_request_accepted_by_someone(record); end
def follow_request_declined_by_me(record); end
def follow_request_declined_by_someone(record); end
def follow_request_removed_by_me(record); end
def follow_request_removed_by_someone(record); end
def followable_blocked_by_me(record); end
def followable_blocked_by_someone(record); end
def followable_unblocked_by_me(record); end
def followable_unblocked_by_someone(record); end
def followability_triggered(record, callback_name); end
end
```
## I18n
```yml
---
---
en:
followability:
errors:
block:
unblock_to:
myself: 'You can not run this action for yourself'
block_to:
myself: 'You can not run this action for yourself'
blocked_by: 'You can not block to who blocked to you'
already_blocked: '%{klass} already blocked'
not_blocked_for_blocking: 'You can not unblock to %{klass} because was not blocked'
follow:
decline_follow_request_of:
myself: 'You can not run this action for yourself'
empty_relation: 'You can not decline follow request of %{klass} because was not sent'
accept_follow_request_of:
myself: 'You can not run this action for yourself'
empty_relation: 'You can not accept follow request of %{klass} because was not sent'
remove_follow_request_for:
empty_relation: 'You can not remove follow request of %{klass} because was not sent'
myself: 'You can not run this action for yourself'
send_follow_request_to:
myself: 'You can not run this action for yourself'
blocked_by: 'You can not send follow request to who blocked to you'
following: 'You are already following to %{klass}'
already_sent: 'You are already sent follow request'
Expand Down
11 changes: 11 additions & 0 deletions config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,25 @@ en:
followability:
errors:
block:
unblock_to:
myself: 'You can not run this action for yourself'
block_to:
myself: 'You can not run this action for yourself'
blocked_by: 'You can not block to who blocked to you'
already_blocked: '%{klass} already blocked'
not_blocked_for_blocking: 'You can not unblock to %{klass} because was not blocked'
follow:
decline_follow_request_of:
myself: 'You can not run this action for yourself'
empty_relation: 'You can not decline follow request of %{klass} because was not sent'
accept_follow_request_of:
myself: 'You can not run this action for yourself'
empty_relation: 'You can not accept follow request of %{klass} because was not sent'
remove_follow_request_for:
empty_relation: 'You can not remove follow request of %{klass} because was not sent'
myself: 'You can not run this action for yourself'
send_follow_request_to:
myself: 'You can not run this action for yourself'
blocked_by: 'You can not send follow request to who blocked to you'
following: 'You are already following to %{klass}'
already_sent: 'You are already sent follow request'
Expand Down
18 changes: 16 additions & 2 deletions lib/followability/followable/actions/block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ module Block
I18N_SCOPE = 'followability.errors.block'

def block_to(record)
if myself?(record)
errors.add(:base, I18n.t('block_to.myself', scope: I18N_SCOPE, klass: record.class))

return false
end

if blocked_by?(record)
errors.add(:base, I18n.t('block_to.blocked_by', scope: I18N_SCOPE, klass: record.class))

Expand All @@ -23,7 +29,8 @@ def block_to(record)
status: Followability::Relationship.statuses[:blocked])

if relation.save
run_callback(self, callback: :on_followable_blocked)
run_callback(self, affected: record, callback: :followable_blocked_by_me)
run_callback(record, affected: self, callback: :followable_blocked_by_someone)

true
else
Expand All @@ -34,6 +41,12 @@ def block_to(record)
end

def unblock_to(record)
if myself?(record)
errors.add(:base, I18n.t('unblock_to.myself', scope: I18N_SCOPE, klass: record.class))

return false
end

unless blocked?(record)
errors.add(:base, I18n.t(:not_blocked_for_blocking, scope: I18N_SCOPE, klass: record.class))

Expand All @@ -43,7 +56,8 @@ def unblock_to(record)
relation = followerable_relationships.blocked.find_by(followable: record)

if relation.destroy
run_callback(self, callback: :on_followable_unblocked)
run_callback(self, affected: record, callback: :followable_unblocked_by_me)
run_callback(record, affected: self, callback: :followable_unblocked_by_someone)

true
else
Expand Down
59 changes: 54 additions & 5 deletions lib/followability/followable/actions/follow.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,19 @@
# frozen_string_literal: true

# rubocop:disable Metrics/ModuleLength
module Followability
module Followable
module Actions
module Follow
I18N_SCOPE = 'followability.errors.follow'

def decline_follow_request_of(record)
if myself?(record)
errors.add(:base, I18n.t('decline_follow_request_of.myself', scope: I18N_SCOPE, klass: record.class))

return false
end

relation = follow_requests.find_by(followerable_id: record.id, followerable_type: record.class.name)

if relation.blank?
Expand All @@ -15,7 +22,34 @@ def decline_follow_request_of(record)

false
elsif relation.destroy
run_callback(self, callback: :on_request_declined)
run_callback(self, affected: record, callback: :follow_request_declined_by_me)
run_callback(record, affected: self, callback: :follow_request_declined_by_someone)

true
else
errors.add(:base, relation.errors.full_messages.to_sentence)

false
end
end

def accept_follow_request_of(record)
if myself?(record)
errors.add(:base, I18n.t('accept_follow_request_of.myself', scope: I18N_SCOPE, klass: record.class))

return false
end

relation = follow_requests.find_by(followerable_id: record.id, followerable_type: record.class.name)

if relation.blank?
errors.add(:base,
I18n.t('accept_follow_request_of.empty_relation', scope: I18N_SCOPE, klass: record.class.name))

false
elsif relation.update(status: Followability::Relationship.statuses[:following])
run_callback(record, affected: record, callback: :follow_request_accepted_by_someone)
run_callback(self, affected: self, callback: :follow_request_accepted_by_me)

true
else
Expand All @@ -26,6 +60,12 @@ def decline_follow_request_of(record)
end

def remove_follow_request_for(record)
if myself?(record)
errors.add(:base, I18n.t('remove_follow_request_for.myself', scope: I18N_SCOPE, klass: record.class))

return false
end

relation = pending_requests.find_by(followable_id: record.id, followable_type: record.class.name)

if relation.blank?
Expand All @@ -34,7 +74,8 @@ def remove_follow_request_for(record)

false
elsif relation.destroy
run_callback(self, callback: :on_request_removed)
run_callback(self, affected: record, callback: :follow_request_removed_by_me)
run_callback(record, affected: self, callback: :follow_request_removed_by_someone)

true
else
Expand All @@ -44,8 +85,14 @@ def remove_follow_request_for(record)
end
end

# rubocop:disable Metrics/AbcSize
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
def send_follow_request_to(record)
if myself?(record)
errors.add(:base, I18n.t('send_follow_request_to.myself', scope: I18N_SCOPE, klass: record.class))

return false
end

if blocked_by?(record)
errors.add(:base, I18n.t('send_follow_request_to.blocked_by', scope: I18N_SCOPE, klass: record.class.name))

Expand Down Expand Up @@ -77,7 +124,8 @@ def send_follow_request_to(record)
status: Followability::Relationship.statuses[:requested])

if relation.save
run_callback(record, callback: :on_request_sent)
run_callback(self, affected: record, callback: :follow_request_sent_to_someone)
run_callback(record, affected: self, callback: :follow_request_sent_to_me)

true
else
Expand All @@ -86,7 +134,7 @@ def send_follow_request_to(record)
false
end
end
# rubocop:enable Metrics/AbcSize
# rubocop:enable Metrics/AbcSize, Metrics/MethodLength

def following?(record)
following.exists?(id: record.id)
Expand All @@ -103,3 +151,4 @@ def sent_follow_request_to?(record)
end
end
end
# rubocop:enable Metrics/ModuleLength
32 changes: 18 additions & 14 deletions lib/followability/followable/callbacks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,27 @@
module Followability
module Followable
module Callbacks
METHOD_NAMES = %w[
on_request_sent
on_request_accepted
on_request_declined
on_request_removed
on_followable_blocked
on_followable_unblocked
on_relation_changed
METHOD_NAMES = %i[
follow_request_sent_to_someone
follow_request_sent_to_me
follow_request_accepted_by_me
follow_request_accepted_by_someone
follow_request_declined_by_me
follow_request_declined_by_someone
follow_request_removed_by_me
follow_request_removed_by_someone
followable_blocked_by_me
followable_blocked_by_someone
followable_unblocked_by_me
followable_unblocked_by_someone
followability_triggered
].freeze

def run_callback(record, callback:)
if METHOD_NAMES.exclude?(callback.to_s) || callback.eql?(:on_relation_changed) || !callback.is_a?(Symbol)
raise ArgumentError
end
def run_callback(record, callback:, affected:)
raise ArgumentError if METHOD_NAMES.exclude?(callback) || callback.eql?(:followability_triggered)

[callback, :on_relation_changed].each do |cb_name|
record.send(cb_name, record, cb_name) if record.respond_to?(cb_name)
[callback, :followability_triggered].each do |cb_name|
record.send(cb_name, affected, cb_name) if record.respond_to?(cb_name)
end
end
end
Expand Down

0 comments on commit 10e9737

Please sign in to comment.