Hej,
Potrzebuję zaimplementować funkcjonalność ‘customowych’ pól powiązanych z
Jednym lub kilkoma modelami,
Jednym lub kilkoma rekordami danego modelu
Po templatce przypisanej do każdego rekordu modelu (osoba tabela)
Obecnie myślę, aby rozwiązać to poprzez utworzenie modeli: Fields, FieldsGroups oraz np. modele do których można byłoby przypisać FieldsGroups: Pages, Products. Prosta wizualizacja poniżej:
Na chwilę obecną nie mam pojęcia jak połączyć FieldsGroups tak, aby spełniły się moje założenia, a przy tym łatwe byłoby rozbudowanie funkcjonalności o nowe warunki. Składniam się ku utworzeniu polimorficznego has_many throught:, jednakże jak wtedy rozwiązać problem uzupełniania istniejących np Pages o nowo dodane pola do grupy powiązanej z Pages?
Nie wiem jakie masz dokłądnie wymagania, ale jeżeli dodatkowych kolumn nie będzie strasznie wiele to takie rozwiązanie jest bardzo fajne:
class Model < ActiveRecord::Base
has_one :model_extra
scope :with_extra_fields, ->(fields){
joins(:model_extra).
select("#{table_name}.*").
select(fields.map{|f| "model_extras.#{connection.quote_column_name(f}"})
}
end
class ModelExtra < ActiveRecord::Base
belongs_to :model
def self.add(field, type)
ActiveRecord::Migraiton.add_column table_name, field, type
end
def self.remove(field)
ActiveRecord::Migraiton.remove_column table_name, field
end
end
Plusy:
Szybkie zapytania
Bardzo proste zapytania
Łatwe agregaty etc.
typowane (liczby jako liczby etc.)
Można indeksować
postgresql ładnie optymalizuje columny z nullami więc o ile nie planujesz tysięcy custom fieldów i milionów rekordów jest to naprawdę fajne rozwiązanie.
Można ustawić wartości domyślne, zabronić nulli itd.
Łatwo można dodać dynamiczne walidacje.
Minusy:
Dodawanie/Usuwanie kolumn z tabeli nie jest lekką operacją.
Większa ilość miejsca w bazie w porównaniu z uzyciem pola JSON
Stosować gdy:
Jest ograniczona liczba dodatkowych kolumn i może być potrzebne wyszukiwanie po nich i indeksowanie