Зачем мне использовать полиморфные отношения, когда я могу сделать простое has_many / own_to? - PullRequest
1 голос
/ 04 июня 2019

Я рассматриваю ассоциации и столкнулся с этой статьей о полиморфных ассоциациях Полиморфные ассоциации . В статье он имеет следующий код:

# Without polymorphism

class Post
  belongs_to :person
  belongs to :group
end


class Person
   has_many :posts
end


class Group
  has_many :posts
end

В статье говорится о коде выше

Обычно, чтобы узнать, кому принадлежит определенный профиль, мы смотрим на столбец, который является Foreign_key. Foreign_key - это идентификатор, используемый для поиска связанного объекта в таблице связанной модели.

Однако наша таблица Posts будет иметь два конкурирующих внешних ключа: group_id и person_id. Это было бы проблематично.

Когда мы пытаемся найти владельца сообщения, мы должны указать проверить оба столбца, чтобы найти правильный Foreign_key, а не опираясь на один. Что произойдет, если мы столкнемся с ситуацией, когда оба столбцы имеют значение?

Я не вижу здесь проблемы. Почему я не могу использовать это, например @post = Post.where(group_id: 1) or Post.where(person_id: 1)

Почему изменение ассоциации на полиморфизм сделает код лучше? Например, has_many: :through создает таблицу с двумя внешними ключами, как показано в направляющих рельсов. Да, три модели в этом примере связаны друг с другом, в то время как приведенный выше код имеет только две модели, соединенные вместе. Я не понимаю, почему я бы выбрал полиморфный вариант.

Учитывая, что полиморфные ассоциации не генерируют внешние ключи и подвержены неверным данным. Почему это будет лучше? Спасибо.

1 Ответ

1 голос
/ 04 июня 2019

Полиморфизм позволяет вам повторно использовать код, что, в свою очередь, делает код вашего приложения масштабируемым.Например, если бы у меня было 10 моделей, которым нужна была адресная запись, я мог бы создать полиморфную ассоциацию, для чего потребовалось бы только два дополнительных столбца.Первый столбец будет adressable_type, а второй - addressable_id.В любой момент я мог получить адрес и найти его родителей с ТОЧНЫМ ЖЕ КОДОМ или создать адрес от любого из родителей с ТОЧНЫМ ЖЕ КОДОМ.Так что я уверен, что вы говорите хорошо, я не могу сделать это в любом случае?Да, вы можете, но если вы не используете полиморфизм, вы должны создать внешний ключ для каждого родителя.Поэтому каждый раз, когда вы хотите связать родительскую модель с дочерним адресом, вы должны создавать новую миграцию с другим внешним ключом, который не позволяет вам повторно использовать ваш код.

Таким образом, захват родителя первого Address будет выглядеть так в рамках полиморфной ассоциации.

parent = Address.first.addressable

Без полиморфизма это выглядело бы примерно так:

def parent_record
    if self.customer_id.present?
        return self.customer
    elsif self.some_other_parent_id.present?
        return self.some_other_parent
    end
end

parent = Address.first.parent_record

Кроме того, вам нужно было бы добавить следующую строку кода для каждой ассоциации.В противном случае вы не сможете создать запись.

 belongs_to :customer, optional: true
 belongs_to :some_other_parent, optional: true

Теперь предположим, что вы на самом деле хотите запустить проверку, чтобы убедиться, что вы случайно не добавили несколько ассоциаций к одной и той же записи (что может привести к поломке).весь ваш процесс, если вы это сделаете, и ваши данные будут недействительными или «бесполезными»).Это будет довольно сложно.С полиморфизмом вам не нужно об этом беспокоиться, потому что есть только один внешний ключ.

Если вы не реализуете полиморфные ассоциации и позже попытаетесь использовать наследование одной таблицы, это сделает вашу логику кода очень трудной для понимания.

Это всего лишь несколько небольших причин, по которым выследует использовать полиморфные ассоциации.Кроме того, это хорошая практика кодирования и имеет логический смысл использовать, когда у вас есть возможность для различных типов родительских моделей для данной модели.Надеюсь, это поможет!

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