City: zip_code:string, name:string, commune:references
Commune name:string district:references
District: name:string, province: references
Province name:string
Czy model User powinien wyglądać tak:
User name:string city:references
A w widoku User @user.name @user.city.zip_code @user.city.name @user.city.commune.name @user.city.commune.district.name @user.city.commune.district.province.name
czy model User powinien wyglądać tak:
User name:string, city:references, commune:references, district:references, province:references
To zależy. Zasada Demeter (https://en.wikipedia.org/wiki/Law_of_Demeter) mówi, że wywołanie takie jak @user.city.commune.district.province.name nie powinno mieć miejsca, bo powoduje, że model User posiada wiedzę o wewnętrznej implementacji kilku innych nie bezpośrednio powiązanych obiektów: Commune, District, Province. Zgodnie z tą zasadą możesz wprowadzić coś takiego:
[code]class User
def province_name
city.province_name
end
end
class City
def province_name
commune.province_name
end
end
class Commune
def province_name
district.province_name
end
end
class District
def province_name
district.province.name
end
end[/code]
Będziesz miał też wtedy znormalizowaną bazę danych.
Jednakże w tej sytuacji uzyskanie province_name dla użytkownika jest dosć skomplikowanym zapytaniem do bazy i może być kosztowne. Jeśli wykonujesz to często i nie chcesz z jakichś powodów tego keszować, to zdenormalizowanie bazy danych może być dobrym rozwiązaniem.
Pamiętaj, że denormalizacja bazy danych zwiększa jej stopień skomplikowanie i należy mieć dobry powód, żeby ją wprowadzać. Premature optimization i takie tam.
Sądzę że to nie będzie obciążać bazy danych ponieważ jest to aplikacja lokalna, intranetowa na której w porywach będzie pracowało 20 osób w jednym momencie.
Z punktu widzenia bazy danych, wychodzi na to że pierwsze podejście jest lepsze. Nic nie stoi na przeszkodzie żebyś sobie oddelegował atrybuty do modelu powiązanego, albo zrobił jakiegoś presentera.