Projekt bazy danych

Hej,
Potrzebuję zaimplementować funkcjonalność ‘customowych’ pól powiązanych z

  1. Jednym lub kilkoma modelami,
  2. Jednym lub kilkoma rekordami danego modelu
  3. 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?

1 Like

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

Alternatywnym rozwiązaniem jest uzycie kolumny JSON: http://www.postgresql.org/docs/9.3/static/datatype-json.html

Plusy:

  • Nie trzeba modyfikować bazy żeby dodać/usunąć pole.
  • Można robić na niej łatwo zapytania
  • Przechowuje wszystkie typy jakie JSON pozwala
  • Można indeksować

Minusy:

  • Wyszukiwanie jest wolniejsze
  • Dodatkowy czas potrzebny na serializację/deserializację (milisekundy co prawda ale)
  • Przechowuje tylko typy które JSON ma (a nie ma np. daty)

Stosować gdy:

  • Dużo różnorodnych pół
  • Duża fragmentacja (np. każdy użytkownik może zdefiniować własne dodatkowe pola)
1 Like

Dane z ‘customowych’ pól możesz też zapisywać jako OpenStruct.