PDA

Visualizza la versione completa : problema con gsub nel controller


mlipreri
22-06-2009, 10:15
Ciao,
ho un problema con la funzione gsub, devo sostituire "," cn "','"
Ho provato nella console questo
"1,2".gsub(",","','") and I get "1','2" -> ok
ma nel controller


@photos_ids_to_delete = params[:delete_photo_array].gsub("," , "','")
@record_to_delete = Photo.find(:all, :conditions => { :id => [@photos_ids_to_delete] } )

e nel mio log del server ho


SELECT * FROM 'photos' WHERE ('photos'.'id' IN ('1\',\'2'))

com'è possible?
Grazie

toraz
22-06-2009, 11:32
Per prima cosa non serve chiedersi come sia possibile. Per fare quello che stai cercando di fare, hai scelto un modo orribile, quindi meglio lasciare perdere e ricominciare da capo. :)

Se hai una stringa di id del tipo "1,2,3" e vuoi cancellare gli oggetti che hanno quegli id, un sistema migliore potrebbe essere di ricavare un array di id dalla stringa e poi usare il metodo delete (o destroy a seconda del caso).


photos_id_to_delete = :params[:delete_photos].split(",")
Photo.delete(photos_id_to_delete)

Ancora meglio sarebbe incapsulare questo comportamento all'interno della classe Photo definendo un metodo che accetti come parametro la stringa e faccia quel che deve fare


class Photo < ActiveRecord::Base
...
def self.delete_by_string(string)
ids = string.split(",")
self.class.delete(ids)
end
...
end

Nel controller


Photo.delete_by_string(params[:delete_photos])

mlipreri
22-06-2009, 12:06
grazie delle dritte!
Ho inserito nel modello photo il tuo metodo ma ottendo questo


NoMethodError: undefined method `destroy_by_ids' for #<Class:0x356473c>
from c:/ruby/lib/ruby/gems/1.8/gems/activerecord-2.3.2/lib/active_record
/base.rb:1964:in `method_missing'
from (irb):1

e lo chiamo da console in questo modo


Photo.destroy_by_ids("118,119")

Per essere sicuro di non aver fatto ulteriori casini ecco il modello


require 'mime/types'

class Photo < ActiveRecord::Base
has_attached_file :file,
:styles => {
:thumb => "100x100#"
}
validates_attachment_presence :file
validates_attachment_content_type :file, :content_type => ['image/jpeg', 'image/pjpeg', 'image/jpg']

def self.destroy_by_ids(string)
ids = string.split(",")
self.class.destroy(ids)
end

def swfupload_file=(data)
data.content_type = MIME::Types.type_for(data.original_filename).to_s
self.file = data
end

end

mlipreri
22-06-2009, 12:18
così funzia


def self.destroy_by_ids(string)
ids = string.split(",")
self.destroy(ids)
end

ho eliminato .class .
Un'altra domanda, come faccio a comunicare che l'operazione è andata a buon fine? Cioè che tutti gli elementi sono stati cancellati? Posso farmi ritornare un bool da destroy_by_ids?
Dato che sono alle prime armi, chiedo a voi qual'è il modo migliore.
Grazie

toraz
22-06-2009, 15:43
Originariamente inviato da mlipreri
Un'altra domanda, come faccio a comunicare che l'operazione è andata a buon fine? Cioè che tutti gli elementi sono stati cancellati? Posso farmi ritornare un bool da destroy_by_ids?
Dato che sono alle prime armi, chiedo a voi qual'è il modo migliore.

Forse la cosa migliore che puoi fare, anche se non ci giurerei, è lasciare tutto così e "riutilizzare" il comportamento di destroy.

mlipreri
22-06-2009, 16:17
scusa cosa intendi per "riutilizzare il comportamento di destroy"?

toraz
22-06-2009, 19:20
Intendo che il metodo per come lo hai definito, ritorna gli stessi valori e solleva le stesse eccezioni di destroy.

weppos
22-06-2009, 23:50
Personalmente non condivido l'approccio fin dall'inizio. Non tanto quanto espresso da toraz che ha fornito il miglior supporto possibile, quanto l'idea iniziale di manipolare i dati della form in modo grezzo.
Io avrei fatto così:

1. nella form mi ingegno in modo che i parametri passati siano nella forma


photo_ids[]=2,3,4,5,6

In questo modo i parametri vengono automaticamente tradotti in un array, nel formato

params[:photo_ids] = [2, 3, 4, 5, 6, 7]

2. A questo punto, basta una chiamata a find con conseguente destroy.

Photo.find(params[:photo_ids]).each(&:destroy)

3. Se vuoi avere il risultato del destroy

results = Photo.find(params[:photo_ids]).map(&:destroy)
failed = results.any? { |result| result == false }

failed è false se c'è anche solo un record che non è stato cancellato.

4. Per sapere quale record, etc etc modifica la struttura a tuo piacimento. Questa è la versione semplice e parzialmente incompleta.

5. Io se avessi un comportamento simile procederei diversamente. Farei in modo di creare un metodo destroy! che mi lancia un'eccezione. Inserirei la lista di destroy in una transazione annullabile nel momento in cui anche uno solo dei destroy lancia eccezione.
In questo modo saprei quale ha lanciato eccezione, potrei prendere contromisure e soprattutto non avrei dati cancellati a metà.

mlipreri
23-06-2009, 09:00
grazie a tutti! ;) Ho implementato i punti 1/2/3/4 di weppos ma mi piacerebbe capire come funzionano le transazioni in rails, su google non ho trovato molto, qualcuno ha qualche link con qualche esempio o ha la pazienza di scrivere 2 righe in merito? Grazie

weppos
23-06-2009, 09:01
La documentazione ufficiale è sempre un buon punto di partenza.
http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html

Loading