Ruby on Rails has_many через самореферентные отношения следования / подписчика - PullRequest
22 голосов
/ 20 июля 2011

На has_many есть несколько постов и тем: through, но я не нашел ни одной, которая бы описывала конкретно то, что я пытаюсь сделать.

У меня есть модель User и модель Friendship. У пользователя есть много пользователей, которые следуют за ними, а также много подписчиков. Это обычная модель Twitter.

Для данного пользователя я хочу настроить отношения Active Record, которые возвращают реальных пользователей, которые следуют за пользователем, и этот пользователь является последователем.

Это отношения, которые я настроил:

class User < ActiveRecord::Base

  has_many :following, :class_name => 'User', :through => :friendships, :foreign_key => 'user_id'

  has_many :followers, :class_name => 'User', :through => :friendships, :foreign_key => 'friend_id'

end

class Friendship < ActiveRecord::Base

  belongs_to :user
  belongs_to :following, :class_name => 'User', :foreign_key => 'friend_id'
  belongs_to :follower, :class_name => 'User', :foreign_key => 'user_id'

end

Следующие отношения работают - они генерируют следующее соединение:

SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.friend_id WHERE ((`friendships`.user_id = 1))

Все великолепно.

Однако отношения Подписчик не работают. Я попробовал несколько вариантов, но большинство, похоже, возвращает тот же набор результатов, что и ниже.

Мне нужно настроить соединение следующим образом, чтобы получить правильный набор результатов.

SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.user_id WHERE ((`friendships`.friend_id = 1)); 

Куда я иду не так?

Я могу настроить это с помощью опции finder_sql на has_many, но, похоже, должен быть лучший способ.

has_many :followers, :class_name => 'User', :finder_sql => 'SELECT `users`.* FROM `users` INNER JOIN `friendships` ON `users`.id = `friendships`.user_id WHERE ((`friendships`.friend_id = #{ id }))'

Спасибо!


Я немного продвинулся и, наконец, установил отношения, разбив отношения на две части, как было показано в этом ответе: Самостоятельная ссылка has_many: сквозная с настроенным: проблема первичного ключа

# FOLLOWING
has_many :friendships_to, :foreign_key => 'user_id', :class_name => 'Friendship'
has_many :following, :through => :friendships_to, :class_name => 'User'

# FOLLOWERS
has_many :friendships_from, :foreign_key => 'friend_id', :class_name => 'Friendship'
has_many :followers, :through => :friendships_from, :class_name => 'User'

Однако, хотя было возможно иметь однострочную версию отношения для следования

has_many :following, :class_name => 'User', :through => :friendships, :foreign_key => 'user_id'

Я все еще не мог заставить его работать на последователей. Все еще интересуетесь, как это можно сделать?

Ответы [ 2 ]

23 голосов
/ 21 июля 2011

Необходимо убедиться, что ActiveRecord знает, что является исходной ассоциацией для друзей User #, а также указывает последователей и указывает класс и foreign_key для отношений, которые ActiveRecord не может экстраполировать из имен ассоциации.

class Following < ActiveRecord::Base

  belongs_to :user
  belongs_to :followed, :class_name => 'User'

end

class User < ActiveRecord::Base

  has_many :followings
  has_many :friends, :through => :followings, :source => 'followed'

  has_many :followeds, :class_name => 'Following', :foreign_key => 'followed_id'
  has_many :followers, :through => :followeds, :source => :user

end
5 голосов
/ 23 сентября 2013

Я своего рода новичок в процессе обучения, но мне эти модели кажутся чище:

class User < ActiveRecord::Base
  has_many :followings
  has_many :followers, through: :followings
end

class Following < ActiveRecord::Base
  belongs_to :user
  belongs_to :follower, class_name: 'User'
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...