Подтвердить что ты не робот

Ruby on Rails has_many через самореференциальные следящие/следящие отношения

Есть несколько сообщений и потоков по has_many: through, но я не обнаружил, что это особенно касается того, что я пытаюсь сделать.

У меня есть модель User и модель Friendships. У пользователя есть много пользователей, которые следуют за ними, а также много последователей. Это обычная модель 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))

Все грандиозно.

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

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

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 }))'

Спасибо!


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

# 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'

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

4b9b3361

Ответ 1

Вам нужно убедиться, что ActiveRecord знает, что такое ассоциация источника для друзей пользователя # 1, а также последователей и указать класс и 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

Ответ 2

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

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