:has_many e lazy loading

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! :slight_smile:

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!