Проблема дизайна Rails STI

Я работаю над побочным проектом, в котором у пользователя может быть несколько клиентов. Эти клиенты могут быть типа Person или Business.

Я склонялся к идее использования STI, но я не уверен, что это правильный путь, поскольку мои модели не будут иметь одни и те же атрибуты.

Например, у бизнеса есть юридическая_форма, а у человека может быть семейное_статус.

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


person makabde    schedule 20.09.2015    source источник


Ответы (2)


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

Немного более продвинутый вариант ассоциаций — полиморфная ассоциация. С полиморфными ассоциациями модель может принадлежать более чем одной другой модели в одной ассоциации. Например, у вас может быть модель изображения, которая принадлежит либо модели сотрудника, либо модели продукта. Вот как это можно объявить:

class Picture < ActiveRecord::Base
  belongs_to :imageable, polymorphic: true
end

class Employee < ActiveRecord::Base
  has_many :pictures, as: :imageable
end

class Product < ActiveRecord::Base
  has_many :pictures, as: :imageable
end

введите здесь описание изображения

Мне не очень нравится STI, и я рекомендую вам попробовать использовать полиморфные ассоциации.

Распространенная проблема с ИППП

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

person Arsen    schedule 20.09.2015
comment
Я рассматривал возможность использования полиморфных ассоциаций, но не знаю, как мне это организовать. Я уже создал 3 модели (с 3 таблицами) Client, Business и Person. Моей конечной целью было бы иметь контроллер клиентов, из которого я мог бы запросить список всех клиентов, независимо от того, являются ли они бизнесом или физическим лицом. - person makabde; 20.09.2015
comment
@makabde да, в чем проблема? :) - person Arsen; 20.09.2015

Если предположить, что я выберу полиморфную ассоциацию, будет ли это правильно?

class Client < ActiveRecord::Base
  belongs_to :cliental, polymorphic: true
end

class Business < ActionRecord::Base
  # Here I am using has_one because I do not want to have duplicates
  has_one :client, as: :cliental
end

 class Person < ActionRecord::Base
  # Here I am using has_one because I do not want to have duplicates
  has_one :client, as: :cliental
end

И позже я хотел бы сделать следующее

class User < ActiveRecord::Base
  has_many clients
  has_many businesses, through: :client
  has_many people, through: :client
end
person makabde    schedule 20.09.2015