diff --git a/README.md b/README.md index 7b67a09..36ff066 100644 --- a/README.md +++ b/README.md @@ -149,9 +149,26 @@ Instances with accepted Friendship. @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. + +```ruby +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. +To use callbacks you can add methods described below to your Friendable model. ```ruby def on_friendship_created(friendship) @@ -165,6 +182,10 @@ end def on_friendship_blocked(friendship) ... end + +def on_friendship_destroyed(friendship) + ... +end ``` ## Roadmap diff --git a/lib/has_friendship.rb b/lib/has_friendship.rb index 0b6c8ca..2d4fb78 100644 --- a/lib/has_friendship.rb +++ b/lib/has_friendship.rb @@ -13,4 +13,4 @@ module HasFriendship ActiveSupport.on_load(:active_record) do extend HasFriendship::Friendable -end \ No newline at end of file +end diff --git a/lib/has_friendship/friendable.rb b/lib/has_friendship/friendable.rb index bc0035f..10a1a19 100644 --- a/lib/has_friendship/friendable.rb +++ b/lib/has_friendship/friendable.rb @@ -1,6 +1,5 @@ module HasFriendship module Friendable - def friendable? false end @@ -39,6 +38,18 @@ def self.friendable? end module InstanceMethods + CALLBACK_METHOD_NAMES = %i( + on_friendship_created + on_friendship_accepted + on_friendship_blocked + on_friendship_destroyed + ).freeze + + CALLBACK_METHOD_NAMES.each do |method_name| + define_method(method_name) do |*args| + super(*args) if defined?(super) + end + end def friend_request(friend) unless self == friend || HasFriendship::Friendship.exist?(self, friend) @@ -88,10 +99,6 @@ def friends_with?(friend) HasFriendship::Friendship.find_relation(self, friend, status: 2).any? end - def on_friendship_created(*args); end - def on_friendship_accepted(*args); end - def on_friendship_blocked(*args); end - private def has_blocked(friend) diff --git a/lib/has_friendship/friendship.rb b/lib/has_friendship/friendship.rb index 2f717b5..be83875 100644 --- a/lib/has_friendship/friendship.rb +++ b/lib/has_friendship/friendship.rb @@ -1,8 +1,13 @@ module HasFriendship class Friendship < ActiveRecord::Base + validate :satisfy_custom_conditions - after_create do - friend.on_friendship_created(self) + after_create do |record| + friend.on_friendship_created(record) + end + + after_destroy do |record| + friend.try(:on_friendship_destroyed, record) end enum status: { pending: 0, requested: 1, accepted: 2, blocked: 3 } do @@ -65,5 +70,15 @@ def self.find_blocked_friendship(friendable, friend) def self.find_one_side(one, other) find_by(relation_attributes(one, other)) end + + private + + def satisfy_custom_conditions + return unless friend.respond_to?(:friendship_errors) + + friend.friendship_errors(friendable).to_a.each do |friendship_error| + errors.add(:base, friendship_error) + end + end end end