Ciao a tutti,
ho un problemino su un modello in Rails 3.1.
Nel modello user, su cui attivato devise, ho questa associazione:
has_many :groups,
:through => :roles,
:conditions => [‘roles.role IN (?)’, RoleType.all.collect{|role_type|
role_type.name}]
Questo crea un errore al momento della migrazione dato che devise in
config/routes.rb “vede” di essere associato al modello User e lo carica,
ma questa associazione effettua una query al db prima che ci siano le
tabelle. Gli autori di Devise mi hanno suggerito di effettuare un lazy
loading in questa associazione, cosa che per non so fare.
Ad occhio direi che il problema sta sul .collect, giusto?
sapreste aiutarmi?
Il senso dell’associazione che l’utente ha un ruolo in un gruppo e
viene salvato come stringa in roles.role con valori presi da
role_types.name. Ho voluto fare questo tipo di associazione “strana”
perch se in un futuro un ruolo venisse eliminato o modificato nella
tabella role_types, il valore associato ad un utente rimanga. C’ un
modo pi intelligente per farlo?
grazie
Ora non riesco ad entrare nella funzionalità della questione, ti posso
consigliare di usare arel che di suo segue il concetto del “lazy
loading” che in sostanza è il caricamento degli elementi nel momento del
bisogno e che potrebbe risolverti il problema. Prova così:
has_many :groups,
:through => :roles,
:conditions => {:roles => {:role => RoleType.all.map(&:name)}}
purtroppo non sono riuscito a provarlo per cui se non funziona controlla
qualche parentesi o prendilo come idea
Il 18/01/12 10:50, Marco M. ha scritto:
has_many :groups,
:through => :roles,
:conditions => {:roles => {:role => RoleType.all.map(&:name)}}
Questa versione non funziona lo stesso, ma grazie al suggerimento l’ho
fatto funzionare cos:
has_many :groups,
:through => :roles,
:conditions => { :roles => { :role => RoleType.select(:name) } }
Grazie!
Non è la stessa cosa, sei sicuro che funzioni? Controlla l’sql generato
Il 18/01/12 17:45, Marco M. ha scritto:
Non la stessa cosa, sei sicuro che funzioni? Controlla l’sql generato
No infatti, non sono la stessa cosa, ma cambia proprio quello che mi
serve, ovvero nella tua versione la query :
SELECT groups
.* FROM groups
INNER JOIN roles
ON groups
.id
=
roles
.group_id
WHERE roles
.user_id
= 1 AND (roles
.role
IN
(‘CG’, ‘CU’, ‘VCU’))
Mentre con la mia versione modificata diventa:
SELECT groups
.* FROM groups
INNER JOIN roles
ON groups
.id
=
roles
.group_id
WHERE roles
.user_id
= 1 AND (roles
.role
IN
(SELECT name FROM role_types
))
Quindi nel secondo caso c’ proprio il lazy loading che mi serviva!
Hai ragione, RoleType.all non usa arel, in realta la mia idea era una
via di mezzo:
RoleType.select(:name).map(&:name)
Ossia un array di valori restituito al momento del bisogno. Non so se
funziona proverò ma la tua soluzione è anche migliore, bravo!