Kiel fari ŝanĝojn al modelo ope

Kelkfoje ni volas fari arajn operaciojn por modelon en Rails. La unua ebleco estas uzi simplan iteracion kaj po unu post unu fari la operacio, sed foje tio povas esti kosteme efikece. ActiveRecord donas al ni multaj eblecoj fari simplan agon al la tuta datumaro kaj foje eĉ pli rapide, sed kun iom da flankkazoj. Sube mi klarigas ilin.

Legado

Vi povas peti por ĉiu rikordo el la datumbazo kaj fari ion kun ĝi per Modelo.all.each { |a| a.funkcio } sed kio okazas se vi havas 1,000,000 Modeloj. Ĝi ŝarĝas ĉion en memoron, kiu verŝajne ne estas kion vi volas. Por helpi en ĉi tiu kazo ActiveRecord havas find_each. find_each liveras ĉiun rikordon sed ope (antaŭagordita al milope). Ekzemple:

Modelo.find_each { |a| a.funkcio }

Iteracias la tutan sed nur ŝarĝas memoren milope.

Modelo.where(aktiva: true).find_each { |a| a.funkcio }

Iteracias nur ties kies aktivo estas vera kaj ŝarĝas milope.

Modelo.find_each(batch_size: 100) { |a| a.funkcio }

Iteracias la tutan sed nur ŝarĝas memoren centope.

Ŝanĝado

Ni diru ke ni havas aro de Artikolo kiuj estas ActiveRecord::Base objektoj kaj ni volas tuj publikigi ĉiujn. Ni havas du eblecojn, la unua estas vidu ĉiujn kaj ŝanĝi ilin unuope.

Artikolo.each do |artikolo|
  artikolo.update_attribute!(:aktiva, true)
end

kiel en la legado sekcio supren por ne ŝarĝe ĉion memoren

Artikolo.find_each do |artikolo|
  artikolo.update_attribute!(:aktiva, true)
end

La avantaĝo estas ke ĝi plenumos la referencovokatajn funkciojn definita en la modelo, do se vi havis after_save funkcion ĝi vokiĝu.

Se vi ne bezonas la referencovokatajn funkciojn vi povas uzi update_column. Ĝi ŝanĝos la datumbazon ne per ActiveRecord sed per SQL update komando. Do ĝi kontrolos nek la datumkontrolojn nek la referencovokatajn funkciojn sed ĝi estas multe pli rapida ĉar ĝi estas unu datumbaza komando kaj ne bezonas ŝarĝi la objektojn en memoron.

Artikolo.all.update_column(:aktiva, true)

Aŭ se vi nur volas ŝanĝi subaro de la datumon, vi povas aldoni where frazon.

Artikolo.where(videbla: 'neto').update_column(:aktiva, true)

Forigado

Kiel por la ŝanĝado ni havas du eblecojn por forigado aŭ kun referencovokataj funkcioj aŭ sen ili. destroy_all forigos la dependajn modelojn kaj vokos la referencovokatojn funkciojn. Alie delete_all sendos komandon delete al la datumbazon kiu eble ne bonas se vi utiligas datumintegrecon.

Ŝarĝas ĉion en memoro kaj forigos dependajn modelojn:

Artikolo.destroy_all

Artikolo.where(aktiva: true).destroy_all

Samas kiel delete from artikoloj; sendita al la datumbazo:

Artikolo.delete_all
Aldone

Ĉiuj ĉi metodoj (legado, ŝanĝado, forigiado) ankaŭ funkcias kun asociaĵojn.

Se ni havas Libronn kun multoj Ĉapitrojn ni povas fari:

la_fundamento = Libro.where(name: "La Fundamento").first

la_fundamento.ĉapitroj.destroy_all

la_fundamento.ĉapitroj.find_each { |ĉ| ĉ.update_attribute(:aktiva, true) }
Fino

La ope metodoj similas al la map kaj each funkcioj de la Enumerable modulo sed por ActiveRecord::Base-ajn modelojn. Do venontfoje kiam vi bezonas fari ion al ĉiu modela aĵo, espereble ĉi artikolo povas helpi vin.