The situation is this: there is a table of friendships , where connections between users are entered. user_id and friend_id . The current user ( current_user ) can be entered in the table and as user_id and friend_id , it all depends on whether I added the user as a friend or he me. Ie, if I add it as a friend, then the connection conditionally looks like this:

 user_id = current_user, friend_id = another_user 

if he adds me, then:

 user_id = another_user, friend_id = current_user 

If the table under user_id = current_user , then deleting friends passes without problems, but as soon as we are faced with the removal of the link of the form user_id = another_user, friend_id = current_user - nothing happens.

Here is how I tried to solve the problem in the controller: friendships_controller.rb :

 def remove_from_friend if friend = current_user.friendships.find_by_friend_id(params[:id]) friend.destroy flash[:notice] = "Removed friendship." redirect_to root_path else friend = current_user.friendships.find_by_user_id(params[:id]) friend.destroy flash[:notice] = "Removed friendship." redirect_to root_path end end 

Model user.rb :

  class User < ActiveRecord::Base # Include default devise modules. Others available are: # :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable has_many :posts, foreign_key: :user_id has_many :recipient_posts, class_name: 'Post', foreign_key: :recipient_id has_many :comments has_many :messages has_many :recipient_messages, class_name: 'Message', foreign_key: :recipient_id has_many :friendships, dependent: :destroy has_many :friends, through: :friendships validates :first_name, :last_name, :email, presence: true has_many :feeds mount_uploader :avatar, AvatarUploader acts_as_liker 

model friendship.rb :

 class Friendship < ActiveRecord::Base belongs_to :user belongs_to :friend, class_name: 'User', foreign_key: :friend_id scope :friends, ->(user_id) do user_requests_ids = Friendship.select(:friend_id).where('user_id = ? AND status="accepted"', user_id).to_sql friend_requests_ids = Friendship.select(:user_id).where('friend_id = ? AND status="accepted"', user_id).to_sql User.where("users.id IN (#{user_requests_ids}) OR users.id IN (#{friend_requests_ids})") end scope :requests, ->(user_id)do requests_friend = Friendship.select(:user_id).where('friend_id = ? AND status="request"', user_id).to_sql User.where("users.id IN (#{requests_friend})") end 
  • one
    Algorithm (a) is unequivocally erroneous; it may choose a wrong record, (b) not DRY, both branches end in the same way. Attach the definition of friendships from User . - D-side
  • one
    What kind of error? From the title and the mention that ничего не выходит is not very clear. Although I guess that there is nil in a friend . I propose to start with the analysis of the request, at the same time carefully look at the form and understand what comes in as an id . - anoam
  • If it's not difficult to show the models Friendship and User - cheops
  • introduced the model into question - holden

1 answer 1

You need to organize two has_many-connections: friends of friends (you already have one) and subscribers subscribers — you don't have it yet. Then you can at any time delete either friends or subscribers without constructing complex conditions in your code. In order to organize a many-to-many connection through the friendships intermediate table, which would work in both directions, you will not need just one intermediate association.

To do this, you will have to build two intermediate connections, friendships_to and friendships_from , which will then be used in the final has_many associations. The following is an example of a User model.

 class User < ActiveRecord::Base has_many :friendships_to, foreign_key: 'user_id', class_name: 'Friendship', dependent: :destroy has_many :friendships_from, foreign_key: 'friend_id', class_name: 'Friendship', dependent: :destroy has_many :friends, through: :friendships_to, source: :friend has_many :subscribers, through: :friendships_from, source: :user end 

Friendship model remains unchanged. So you get the opportunity to extract friends (who you subscribe to) and subscribers (who follow you) and work with them using the usual ActiveRecord tools - search, filter, delete.

 usr = User.find_by(name: 'User1') # Друзья usr.frinds # Подписчики usr.subscribers