Chci spojit dvě následující věci:
Moje STI strukturu:
Předpokládejme, že Kolejnice model User
. Existují pouze dva typy uživatelů, a to Admin
a Customer
. STI sloupec je type
tabulka se nazývá users
ale v praxi, jsme nikdy nebude mít a User
objekty kolem, jen Admins
a Customers
.
User
(používá se pro ukládání všech dat a provádění společné funkce, ale nikdy instanciated)Admin
Customer < User
Dynamicky rozšířit modely:
V některých případech, to je užitečné k dynamicky rozšířit model, třída, dočasně mít objekt s více schopnosti provádět konkrétní akce. Převzít můj create
správce akce kontroly pro další pole "Odeslat uvítací e-mail" (která je poskytována new
formě). Atribut je virtuální, můžeme tedy použít v podobě, jako kdyby to byl normální sloupci. To může být realizováno s:
extended_user_class = Class.new(User)
extended_user_class.send(:include, MyAwesomeMixins)
extended_user_class.class_eval do
my_virtual_attribute :send_welcome_mail, default: true
end
model = extended_user_class.new
# send model to the view and it "just works"
Kombinace obou
Bohužel kombinace obou těchto technik nefunguje tak, jak je popsáno výše, protože Kolejnice STI se zdá být zlomené anonymní třídy:
[1] pry(main)> User.where(id: 1).to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`id` = 1"
[2] pry(main)> Class.new(User).where(id: 1).to_sql
=> "SELECT `users`.* FROM `users` WHERE `users`.`type` IS NULL AND `users`.`id` = 1"
UPRAVIT: Chcete reprodukovat výše uvedené, musí být v produkci env.
Druhé tvrzení je nesprávné, protože filtry podle typu. První prohlášení je zamýšlené chování.
Takže, apearently anonymní třídy jsou špatné pro STI. Předefinování konstantní User
jak je popsáno v https://dev.to/factorial/a-trick-with-ruby-anonymous-classes-11pp je pravděpodobné, že zlomit žádosti, - chci, rozšířené třídy, aby být použity pouze při volání explicitně (extended_user_class
) - User
musí být nedotčena.
Toho lze dosáhnout v Ruby 3 / Kolejnice 6?