Siccome nella join table non ho bisogno di gestire nessuna informazione aggiuntiva alle due foreign keys che mettono in relazione molti a molti due tabelle ho preferito usare has_and_belongs_to_many piuttosto che has_many :through. La domanda e': la tabella di join va popolata manualmente oppure esiste un meccanismo automatico che si occupa di popolarla quando vengono inseriti dati nelle due tabelle in relazione?
on 2009-01-27 21:36
on 2009-01-27 21:52
Se crei correttamente i due has_and_belongs_to_many la tabella di join si autopopola :D 2009/1/27 Mauro <mrsanna1@gmail.com>
on 2009-01-27 21:57
Il 27 gennaio 2009 21.35, Mauro <mrsanna1@gmail.com> ha scritto: > Siccome nella join table non ho bisogno di gestire nessuna informazione > aggiuntiva alle due foreign keys che mettono in relazione molti a molti due > tabelle ho preferito usare has_and_belongs_to_many piuttosto che has_many > :through. > La domanda e': la tabella di join va popolata manualmente oppure esiste un > meccanismo automatico che si occupa di popolarla quando vengono inseriti > dati nelle due tabelle in relazione? dai un'occhiata a: http://railscasts.com/episodes/17 http://railscasts.com/episodes/47
on 2009-01-27 22:19
2009/1/27 Sandro Paganotti <sandro.paganotti@gmail.com> > Se crei correttamente i due has_and_belongs_to_many la tabella di join si > autopopola :D Allora ti spiego com'e' la situazione perche' la tabella di join non si e' autopopolata. Dunque i modelli sono class Category < ActiveRecord::Base belongs_to :sector has_and_belongs_to_many :suppliers end Il belongs to sector e' perche' la categoria appartiene ad un settore specifico, ma il mio problema e' tra Category e: class Supplier < ActiveRecord::Base has_and_belongs_to_many :categories end A questo punto ho lanciato script/console e fatto un @category=Categoyt.create(..............) e @supplier=Supplier.create(.................) Le due tabelle categories e suppliers vengono popolate ma la tabella di join no. La migration per la tabella di join e': class CreateCategoriesSuppliersJoin < ActiveRecord::Migration def self.up create_table :categories_suppliers, :id => false do |t| t.references :category, :null => false t.references :supplier, :null => false end def self.down drop_table :categories_suppliers end end end Dove sbaglio? A me sembra tutto giusto.
on 2009-01-27 22:47
Il 27 gennaio 2009 22.19, Mauro <mrsanna1@gmail.com> ha scritto: > A questo punto ho lanciato script/console e fatto un > @category=Categoyt.create(..............) e > @supplier=Supplier.create(.................) > Le due tabelle categories e suppliers vengono popolate ma la tabella di join > no. cosa c'è in quei ...? in particolare, dov'è il dato di quali categorie appartengono a quali supplier? @supplier.categories = Category.find(:all) @supplier.save oppure: @category.suppliers = Supplier.first
on 2009-01-27 22:48
2009/1/27 Pietro Giorgianni <giorgian@gmail.com>:
> @category.suppliers = Supplier.first
scusa:
@category.suppliers = [Supplier.first]
on 2009-01-27 22:51
2009/1/27 Pietro Giorgianni <giorgian@gmail.com> > 2009/1/27 Pietro Giorgianni <giorgian@gmail.com>: > > @category.suppliers = Supplier.first > > scusa: > @category.suppliers = [Supplier.first] > _______________________________________________ > Ml mailing list > Ml@lists.ruby-it.org > http://lists.ruby-it.org/mailman/listinfo/ml > Quindi la tabella di join non viene popolata automaticamente come hai detto, bisogna intevenire col codice o qualcosa mi sfugge?
on 2009-01-27 22:55
2009/1/27 Pietro Giorgianni <giorgian@gmail.com> > Il 27 gennaio 2009 22.19, Mauro <mrsanna1@gmail.com> ha scritto: > > A questo punto ho lanciato script/console e fatto un > > @category=Categoyt.create(..............) e > > @supplier=Supplier.create(.................) > > Le due tabelle categories e suppliers vengono popolate ma la tabella di > join > > no. > > cosa c'è in quei ...? Ci sono i campi valorizzati @category=Categoyt.create(:id => 1, :codice =>'A01', :descrizione => 'prova') @supplier=Supplier.create(:id => 1, :nome => 'pingo', :cognome => 'pongo') > > in particolare, dov'è il dato di quali categorie appartengono a quali > supplier? Dovrebbero essere le foreign keys nella tabella di join no? category_id e supplier_id.
on 2009-01-27 23:26
2009/1/27 Mauro <mrsanna1@gmail.com>: > Dovrebbero essere le foreign keys nella tabella di join no? category_id e > supplier_id. andiamo con ordine. tu hai Supplier e Category, e ogni supplier può appartenere a più categorie e ogni categoria può appartenere a ogni supplier. una volta che hai creato una categoria e un supplier, c'è ancora un dato che manca: questa categoria si applica a questo supplier? se hai tre categorie e tre suppier, il software non può indovinare come sono associate. ci sono diversi modi di procedere, in base a come vuoi che sia l'interfaccia: a) puoi inserire prima tutte le categorie, poi tutti i clienti e infine fare un rettangolo di checkbox in cui spuntare quelle giuste; (crei gli oggetti così come hai fatto finora, poi fai il form (eventualmente parliamo di come si può fare) e fai le varie associazioni; b) puoi inserire prima le categorie; quando poi inserisci ogni supplier, scegli con checkbox o una select multipla le categorie per questo supplier; c) puoi fare una cosa mista, più complessa ma forse più comoda per l'utente: quando inserisci una categoria, fai scegliere tra i supplier già presenti ed eventualmente dei nuovi, e viceversa, quando inserisci un supplier, fai scegliere tra le categorie. quasi tutto il lavoro lo fa activerecords da solo: come ti ho scritto, puoi aggiungere o togliere oggetti direttamente agendo su @supplier.categories, o @category.suppliers come se fossero array (anche se un occhio a quello che poi succede in termini di interazione col database non guasta).
on 2009-02-04 23:31
2009/1/27 Pietro Giorgianni <giorgian@gmail.com>: > se hai tre categorie e tre suppier, il software non può indovinare > > b) puoi inserire prima le categorie; quando poi inserisci ogni > supplier, scegli con checkbox o una select multipla le categorie per > questo supplier; Piano piano comincio a capire grazie anche agli episodi su railscast, veramente utili :-) Ho scelto la soluzione b. Una parte del codice della view per i suppliers e': <p> <%= f.label :aggiudicazioniGare %><br /> <%= f.text_field :aggiudicazioniGare %> </p> <p> <%= f.label :note %><br /> <%= f.text_area :note %> </p> <p> <%= f.label :categorie %><br /> <%= f.collection_select :category_ids, @categories, :id, :descrizione %> </p> Dove quindi ho una select attraverso la quale indicare la categoria associata al fornitore. Ovviamente nel controller fornitore ho: @categories=Category.find(:all). Funziona :-) Pero' mi serve qualcosa di piu': Le categorie fanno parte di diversi settori, cioe' ho un'associazione uno a molti tra settori e categorie. Quando inserisco un nuovo fornitore percio', non voglio assegnarli la categoria di appartenenza scegliendo tra tutte le categorie disponibili, bensi' vorrei prima indicare il settore per poi scegliere tra le categorie appartenenti al settore selezionato. Non so se sono riuscito a spiegarmi. Dovrei capire a fondo i meccanismi che collegano i modelli con i controllers con le views, e infatti li sto capendo piano piano lavorando sul campo, solo che non riesco a trovare la soluzione a questo banale problemino.
on 2009-02-05 13:12
2009/2/4 Mauro <mrsanna1@gmail.com>: > Pero' mi serve qualcosa di piu': > Le categorie fanno parte di diversi settori, cioe' ho un'associazione > uno a molti tra settori e categorie. > Quando inserisco un nuovo fornitore percio', non voglio assegnarli la > categoria di appartenenza scegliendo tra tutte le categorie > disponibili, bensi' vorrei prima indicare il settore per poi scegliere > tra le categorie appartenenti al settore selezionato. chiarissimo. nella mia applicazione ho incontrato questo problema più volte. in un caso, poiché le opzioni possibili erano veramente tante, ho fatto così: una normale select "settore", poi un observe_field che, quando scatta, fa una richiesta ajax a un apposito metodo di un controller, che restituisce la select con le sole categorie per quel settore. relativamente veloce da scrivere, però, ripeto, consigliabile solo se il numero di settori e/o categorie è molto molto alto, perché la richiesta ajax ci impiega un po'. in un altro caso, le opzioni possibili erano pochi, ho usato javascript (in una view: era un file .js.erb): var sections = new Array(); <%- for section in @sections -%> elem = document.createElement('optgroup'); elem.setAttribute('id', '<%= "group#{section.id}" -%>'); elem.appendChild(create_option('', '<%= t(:option_pick_a_user) -%>')); <% for user in section.users -%> elem.appendChild(create_option('<%= user.id -%>', '<%= user.nick -%>')); <% end -%> sections['<%= section.id -%>'] = elem; <% end -%> function create_option(value, text) { o = document.createElement('option'); o.setAttribute('value', value); o.appendChild(document.createTextNode(text)); return o; } function set_users() { section = $('assignment_section_id').value; if (section == "") { $('users').hide(); $('buttons').hide(); } else { sel = $('assignment_user_id'); children = sel.childNodes; for(i = 0; i < children.length; i++) sel.removeChild(children[i]); sel.appendChild(sections[section]); $('users').show(); $('buttons').show(); } } come vedi, ho popolato un array javascript, e poi nella view uso: <%= observe_field "id_della_select", :function => "set_users()" %> forse è possibile creare gli optgroup direttamente da codice erb, senza usare javascript, crearli tutti invisibili e poi mostrare quello giusto, ma non ne sono sicuro.
on 2009-02-05 13:24
2009/2/5 Pietro Giorgianni <giorgian@gmail.com>: > > > <% end -%> > function set_users() { > sel.appendChild(sections[section]); > forse è possibile creare gli optgroup direttamente da codice erb, > senza usare javascript, crearli tutti invisibili e poi mostrare quello > giusto, ma non ne sono sicuro. Ah ecco, piu' complicato del previsto, agli observe non ci sono ancora arrivato :-)
on 2009-02-11 17:42
2009/2/5 Pietro Giorgianni <giorgian@gmail.com>: > > nella mia applicazione ho incontrato questo problema più volte. > > in un caso, poiché le opzioni possibili erano veramente tante, ho fatto così: > > una normale select "settore", poi un observe_field che, quando scatta, > fa una richiesta ajax a un apposito metodo di un controller, che > restituisce la select con le sole categorie per quel settore. Tanto per cominciare mi trovo nella banale situazione di inserire nella view dei fornitori la lista dei settori. Ancora prima di poter selezionare la categoria di appartenenza del fornitore devo scegliere il settore, il problema su come poi visualizzare le categorie relative a quel settore lo risolvo dopo. Nella view del fornitore, new.html.erb, ho inserito <%= f.collection_select :sector_id, @sectors, :id, :descr %> ma ovviamente mi da errore perche' il metodo sector_id non esiste nella classe fornitore. Mi trovo in stand_by per questo banale problema.
on 2009-02-15 00:57
Pietro Giorgianni wrote: > > <%= observe_field "id_della_select", :function => "set_users()" %> > Come mai richiami una funzione javascript e non un'azione del controller?
on 2009-02-15 09:29
2009/2/15 Msan Msan <mrsanna1@gmail.com>: > Pietro Giorgianni wrote: >> >> <%= observe_field "id_della_select", :function => "set_users()" %> >> > Come mai richiami una funzione javascript e non un'azione del > controller? come ti dicevo, non sempre è necessario usare ajax: se i dati tra cui scegliere sono pochi*, si può prendere in considerazione l'idea di caricarli tutti (in questo caso creando un array javascript) per poi mostrare quelli giusti. in questo caso, non si chiama nessun'azione del server. quando invece i dati sono tanti, allora si preferisce fare una richiesta ajax. tra parentesi: su quale sia il modo migliore di gestire le richieste dinamiche ci sono varie scuole. io finora ho usato prototype, ma vedo che sempre più gente utilizza jquery, che sembra carino, anche se non l'ho ancora provato. * cosa vuol dire pochi e molti? non saprei, è difficile stabilirlo, dipende da tanti fattori, come la velocità di connessione. non so se qualcuno, là fuori, ha proposto un limite. pietro
on 2009-02-15 12:23
2009/2/15 Pietro Giorgianni <giorgian@gmail.com>: > caricarli tutti (in questo caso creando un array javascript) per poi > mostrare quelli giusti. in questo caso, non si chiama nessun'azione > del server. > > quando invece i dati sono tanti, allora si preferisce fare una richiesta ajax. > > tra parentesi: su quale sia il modo migliore di gestire le richieste > dinamiche ci sono varie scuole. io finora ho usato prototype, ma vedo > che sempre più gente utilizza jquery, che sembra carino, anche se non > l'ho ancora provato. Ho proprio ieri potuto apprezzare l'utilita' dell'observ_field. Per poter utlizzare ajax ho utilizzato, come indicato nel manuale agile web development with rails, <% javascript_include_tag :defauts %>. Non quindi se viene utilizzato jquery o prototype, c'e' un modo per capirlo? Un'altra domanda. Bene o male nel form di "nuovo fornitore", in cui va riempito il form per la creazione di un nuovo fornitore, sono riuscito ad inserire l'elenco dei settori e, alla scelta di un settore, tramite l'observ_field, vengono presentate le categorie relative. Tutto nella stessa pagina. Se non sbaglio pero' e' impossibile fare tutto con un'unica operazione, nel senso: creare un nuovo fornitore e contemporaneamente assegnargli le categorie di appartenenza. Devo prima avere gia' in tabella l'id del fornitore e solo cosi' posso successivamente assegnare tale fornitore a diverse categorie. Sbaglio?
on 2009-02-15 12:39
2009/2/15 Mauro <mrsanna1@gmail.com>: > Per poter utlizzare ajax ho utilizzato, come indicato nel manuale > agile web development with rails, <% javascript_include_tag :defauts > %>. > Non quindi se viene utilizzato jquery o prototype, c'e' un modo per capirlo? rails di default usa prototype. > Se non sbaglio pero' e' impossibile fare tutto con un'unica > operazione, nel senso: creare un nuovo fornitore e contemporaneamente > assegnargli le categorie di appartenenza. > Devo prima avere gia' in tabella l'id del fornitore e solo cosi' posso > successivamente assegnare tale fornitore a diverse categorie. > Sbaglio? non è ancora possibile farlo automaticamente (cioè senza sgobbare); lo sarà presto: nella 2.3 dovrebbe introdurre i nested form, che servono esattamente a questo. tuttavia c'è un modo per ottenere il risultato che vuoi. in breve: * in Provider, crei un attributo virtuale, che so: categories_wannabe; * nel form di creazione, passi le categorie con questo nome, ad esempio con fields_for :categories_wannabe; * sempre in Provider, metti un after_create o un after_save (a seconda se ti interessa solo il caso creazione o anche il caso modifica) in cui assegni le categorie. trovi un esempio (anche se un po' diverso) qui: http://railscasts.com/episodes/75-complex-forms-part-3 pietro
on 2009-02-15 13:19
2009/2/15 Pietro Giorgianni <giorgian@gmail.com>: > > * in Provider, crei un attributo virtuale, che so: categories_wannabe; > * nel form di creazione, passi le categorie con questo nome, ad > esempio con fields_for :categories_wannabe; > * sempre in Provider, metti un after_create o un after_save (a seconda > se ti interessa solo il caso creazione o anche il caso modifica) in > cui assegni le categorie. > > trovi un esempio (anche se un po' diverso) qui: > http://railscasts.com/episodes/75-complex-forms-part-3 Perfetto grazie mille :-) p.s. che intendi per Provider?
on 2009-02-15 14:32
Il 15 febbraio 2009 13.19, Mauro <mrsanna1@gmail.com> ha scritto: > 2009/2/15 Pietro Giorgianni <giorgian@gmail.com>: > p.s. che intendi per Provider? semplicemente il model del fornitore. supplier? provider?
on 2009-02-15 17:31
2009/2/15 Pietro Giorgianni <giorgian@gmail.com>: > Il 15 febbraio 2009 13.19, Mauro <mrsanna1@gmail.com> ha scritto: >> 2009/2/15 Pietro Giorgianni <giorgian@gmail.com>: >> p.s. che intendi per Provider? > > semplicemente il model del fornitore. supplier? provider? ah ok supplier allora :-)
on 2009-02-15 20:38
2009/2/15 Pietro Giorgianni <giorgian@gmail.com>: >> assegnargli le categorie di appartenenza. > in breve: > > * in Provider, crei un attributo virtuale, che so: categories_wannabe; > * nel form di creazione, passi le categorie con questo nome, ad > esempio con fields_for :categories_wannabe; > * sempre in Provider, metti un after_create o un after_save (a seconda > se ti interessa solo il caso creazione o anche il caso modifica) in > cui assegni le categorie. Ok, perdonami ma sto andando un po in confusione, troppe cose tutte assieme per me :-) Allora: ti spiego dove sono arrivato e dove mi sono arenato. localhost:3000/suppliers/new richiama l'action new del controller supplier. La view dell'action new e': <% form_for(@supplier) do |f| %> <%= f.error_messages %> <%= render :partial => "form", :locals => { :f => f, :label_text => "Crea"} %> <% end %> il partial contiene tutti i campi relativi agli attributi del modello Supplier che devono essere valorizzati per creare un nuovo supplier. All'interno di questo partial ho aggiunto: <%= collection_select "category", :sector_id, @sectors, :id, :name, :prompt => "seleziona il settore" %> <div id="category_container"> </div> <%= observe_field :category_sector_id, :frequency => 1, :update => 'category_container', :url => {:action => 'filter_category_in_sector'}, :with => "'sector_id='+value" %> La collection_select e' per poter selezionare il settore e l'observ_field mi dovrebbe dare le categorie relative al settore selezionato. Per poter far funzionare la collection_select ho aggiunto nell'action new di supplier_controller la variabile @sectors = Sector.find(:all). L'observe_field chiama l'action filter_category_in_sector definita nel controller in questo modo: def filter_category_on_sector @categories = Category.find_all_by_sector_id(params[:sector_id]) render :layout => false end e ovviamente ho creato la vista filter_category_in_sector: <% fields_for @supplier.categories_wannabe do |f| %> <% end %> Questo codice e' solo di prova per iniziare a capire il funzionamento di fields_for e degli attributi virtuali che mi hai suggerito di utilizzare. Si pone pero' il problema che l'oggetto supplier non e' visibile nell'action filter_category_in_ sector.
on 2009-02-16 08:58
2009/2/15 Mauro <mrsanna1@gmail.com>: > [...] > Si pone pero' il problema che l'oggetto supplier non e' visibile > nell'action filter_category_in_ sector. che importa? filter_category_on_sector deve solo mostrare le categorie per un certo settore; sarà poi l'action del form (create, suppongo) a ricevere tutti i dati. l'action dovrà fare qualcosa tipo: @supplier = Supplier.create(params[:supplier]) sta invece al supplier stesso fare la cosa giusta, ovvero prendere, dopo la creazione, i dati dell'attributo virtuale (ovvero gli id delle categorie) e usarli per riempire categories. se hai dubbi, prova semplicemente a loggare il contenuto di params nell'action (logger.debug params.inspect), e dagli un'occhiata: vedrai come vengono resi i campi del fields_for. questa cosa degli attributi virtuali viene usata spesso: ad esempio, molti plugin di autenticazione usano due attributi virtuali sull'oggetto utente, con nomi tipo password e password_confirm, e bloccano invece il mass assignment del vero campo password, così al salvataggio controllano se password e password_confirm sono stati assegnati, e se sì che siano uguali, e infine riempiono il vero campo password (quello che sta sul db).
on 2009-02-16 09:59
2009/2/16 Pietro Giorgianni <giorgian@gmail.com>:
>
mmmmm, allora mi sfugge qualcosa.....l'action
filter_category_on_sector non deve far altro che crearmi una serie di
checkboxes relative alle varie categorie, in questo modo l'utente
dovrebbe poter assegnare una o piu' categorie al nuovo supplier.
La view dell'action filter_category_on_sector la devo ancora
completare, devo vedere come creare le checkboxes, ma, giusto per
vedere se qualcosa funziona, ho messo:
<% fields_for @suppliers.categories_wannabe do |f| %>
<% end %>
e mi da errore dicendomi che viene richiamato un oggetto inesistente
nil.categories_wannabe.
on 2009-02-17 09:23
2009/2/16 Mauro <mrsanna1@gmail.com>: >> @supplier = Supplier.create(params[:supplier]) > <% end %> > > e mi da errore dicendomi che viene richiamato un oggetto inesistente > nil.categories_wannabe. Sono in stanb_by :-( e in stato confusionale :-) Hai tempo per darmi una mano?
Please log in before posting. Registration is free and takes only a minute.
Existing account
(Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
Log in with Google account | Log in with Yahoo account
No account? Register here.