Asocjacja has_one, kolejność zapisu, dostęp do modelu powiązanego

Powiedzmy że jest takie modele i relacje między nimi.
Z grubsza chodzi o to że w zależności od typu użytkownika jego cechy specyficzne są w osobnych tabelach.

[code=ruby]class User < ActiveRecord::Base

has_one :manager_props
has_one :seller_props
has_one :admin_props

accepts_nested_attributes_for :manager_props, :seller_props, :admin_props

end

class ManagerProps < ActiveRecord::Base

belongs_to :user

end[/code]
Problem jest taki że chciałbym, aby przed zapisem, pewne wartości w modelu user były wyliczane na podstawie danych z :xxxx_props. A do tego na tych wartościach nałożone by były koniecznie validacje.
Domyślnie w railsach najpierw zapisywany bedzie w tym przypadku obiekt user a zaraz po nim xxx_props. Czy da się jakoś dobrać do tych wartości z props before_validation obiektu user, wtedy bym zrobił konieczne wyliczenia ?
Ewentualnie czy można jakoś łatwo odwrócić tą kolejność zapisu modeli ?

A dlaczego nie zrobić albo osobnych modułów dla różnych typów użytkowników i rozszerzać klasę o odpowiedni moduł w momencie tworzenia obiektu? Ewentualnie skorzystać z STI: stworzyć klasy dziedziczące po User, które będą korzystały z tej samej tabeli w bazie danych.

STI odpada z tego względu że pola xxx_props są całkowicie różne (kazda tabela dla nich ma 5-10 kolumn), tabela Users miała by finalnie kilkadziesiąt kolumn i wiele pustych rekordów.
Możesz jakiś przykład z tymi modułami, bo to brzmi ciekawie ?

Z STI miałem na myśli to, że pola xxx_props byłyby w różnych tabelach. Czyli np:

[code=“ruby”] class Admin < User
has_one :admin_props
end

class Seller < User
has_one :seller_props
end[/code]
Rozwiązanie z modułami jest podobne, tylko Seller, Admin itp. nie są klasami tylko modułami:

[code=“ruby”]module Admin
def self.extended(base)
base.instance_eval do
define_method “admin_props” do
AdminProp.find_by_user_id(base.id)
end
end
end
end

class User
def initialize(type)
self.extend(Admin) if type == “admin”
end
end[/code]
Ten powyższy kod pewnie nie do końca zadziała, ale wydaje mi się, że samą ideę wyjaśniłem.

Ale w czym to pomoże w moim przypadku ? Chyba że chodzi o to, zgaduje, że przy takiej konstrukcji walidacja dla wszystkich pól odpali się w jednym momencie i mam w before_validate dostęp do wszystkich pól ?
Dodam że dla pól w XXXX_Props także mam założone validacje niezależnie od walidacji w User

Ok, czyli chcesz takiej konstrukcji? [code=“ruby”]class User

before_validation :calculate_sth_from_props

def calculate_sth_from_props
user_field = xxx_props.field_1 + xxx_props.field_2
end
end[/code]
Czy chodzi o coś innego? Jeżeli ma być tak jak napisałem powyżej, to w momencie gdy tworzysz użytkownika tak:

user = User.new(params[:user])

i w tych paramsach masz parametry dla tego obiektu xxx_props to w before_validation ten obiekt jest dostępny.

Tak, z grubsza o to chodzi. Ale skąd przy zapisie usera Railsy bedą wiedziały co idze do user a co do props ? Chyba że moje accepts_nested_attributes_for zostaje ?

Tak, accepts_nested_attributes_for zostaje (tzn. wydaje mi się, że railsy i tak wiedziałyby co do czego idzie po tym jak byłby zagnieżdżony hash, tylko nie można by tego było zapisać)

wygląda to całkiem sensownie. podejrzewam że kolejność zapisu się nie zmieni, ale to na czym mi zalezy czyli dostęp do tych propsów powinien być. wypróbuje, dzięki :slight_smile: