Дизайн модели: Пользователи имеют друзей, которые пользователи

Обновить

December 2018

Просмотры

1.8k раз

4

Я ищу , чтобы убедиться , что мои методы правильны прежде чем продолжить эту ассоциацию. Реализация кажется слишком сложной, поэтому я думаю , что должно быть что - то не так с моим планом. Я использую структурированное (SQL) для хранения данных, в соответствии с конвенциями рельсы хранения. Что у меня есть модель пользователя, то есть адрес электронной почты, password_digestи имя в схеме.

class User < ActiveRecord::Base
  has_many :posts
end

Я хотел бы осуществить has_manyобъединение в коллекцию друзей, так что пользователи могут belong_toпользователи (как друзья). Я надеюсь иметь возможность User.last.friends.lastвернуть объект пользователя , когда должным образом построены и заселены.

Я считаю, что я могу создать модель для этой ассоциации, как:

Class Friend < ActiveRecord::Base
  belongs_to :user
  belongs_to :friendlies, class: 'User'
end
Class User < ActiveRecord::Base
  has_many :posts
  has_many :friends
  has_many :friendly, class: 'Friend'
end

Но я думаю , что потребуется мне добавить, чтобы модели и запрос с использованием User.last.friends.last.user Так что я думал , это это has_and_belongs_to_manyотношение. Могу ли я уйти следующее (или нечто подобное):

class User < ActiveRecord::Base
  has_and_belongs_to_many :friends, class: 'User'
end

Я нашел это :

class User < ActiveRecord::Base
  has_many :user_friendships
  has_many :friends, through: :user_friendships


class UserFriendship < ActiveRecord::Base
  belongs_to :user
  belongs_to :friend, class_name: 'User', foreign_key: 'friend_id'

И это (самопровозглашенный «стандарт»):

has_many :friendships, :dependent => :destroy
has_many :friends, :through => :friendships, :dependent => :destroy
has_many :inverse_friendships, :class_name => "Friendship", :foreign_key => "friend_id", :dependent => :destroy
has_many :inverse_friends, :through => :inverse_friendships, :source => :user, :dependent => :destroy

Что я предполагаю , что требуется Friendshipмодель. Я не чувствую , что я нужна модель дружбы. Я думаю , что class UserFriendshipметод выглядит правильно, но это требует дополнительной модели. Теперь на вопросы:

  1. Могу ли я сделать has_and_belongs_to_manyотношения с таблицей , которая относится к друзьям пользователя , которые являются пользователями, не подвергаясь дополнительная модель , чтобы сделать это?

  2. Является ли это разумно иметь дополнительную модель «в случае» дополнительные требования всплывают позже?

3 ответы

7

То , что вы ищете, что - то называется self referential join, что означает , что вы можете ссылаться на то же самое modelс другой ассоциации:

#app/models/user.rb
class User < ActiveRecord::Base
   has_and_belongs_to_many :friendships,
      class_name: "User", 
      join_table:  :friendships, 
      foreign_key: :user_id, 
      association_foreign_key: :friend_user_id
end

Вы должны были бы создать habtmтаблицы объединения иметь ссылку:

$ rails g migration CreateFriendshipsTable

#db/migrate/create_friendships_table____.rb
class CreateFriendShipsTable < ActiveRecord::Migration
   def change
      create_table :friendships, id: false do |t|
        t.integer :user_id
        t.integer :friend_user_id
      end

      add_index(:friendships, [:user_id, :friend_user_id], :unique => true)
      add_index(:friendships, [:friend_user_id, :user_id], :unique => true)
   end
end

$ rake db:migrate

Существует большая ссылка здесь: Рельсы: автообъединение схемы с has_and_belongs_to_many?


Является ли это разумно иметь дополнительную модель «в случае» дополнительные требования всплывают позже?

Только если вы знаете , вы будете иметь дополнительные атрибуты. Если нет, то вы можете уйти с habtmтех пор , как вы хотите.

1

Ответ Рича был отличным ресурсом. Мне удалось сорвать несколько шагов, следуя этой конвенции:

# app/model/user.rb
has_and_belongs_to_many :friends,
  class_name: "User", 
  join_table: :friends_users, 
  foreign_key: :user_id, 
  association_foreign_key: :friend_id

Эта миграция была достаточной (без изменения результирующего кода):

rails g migration CreateFriendlyJoinTable users friends

JoinTable синтаксис был найден с помощью rails generate migration -h

4

Вы можете попробовать это

--friendship.rb

class Friendship < ApplicationRecord
  belongs_to :user
  belongs_to :friend, :class_name => 'User'
end

--user.rb

class User < ApplicationRecord
  has_many :friendships
  has_many :friends, through: :friendships
end

--db мигрировать xxxx_create_friendship.rb

class CreateFriendships < ActiveRecord::Migration[5.0]
  def change
    create_table :friendships do |t|
      t.belongs_to :user
      t.belongs_to :friend, class: 'User'
      t.timestamps
    end
  end
end

Связанные вопросы