2016-06-29 9 views
0

Grundsätzlich ich jede Tabellenspalte für ein Modell in Rails 5.aktualisieren Jedes Array-Objektwert in Rails

str = "abc---def" 

str.split('---').map do |a| 
Foo.where(product_id:1).update_all(bar: a) 
end 

Alte Objekt wie wäre aktualisieren möchten:

[ 
[0] { product_id: 1, 
     ..., 
     bar: "xxx", 
     ... 
    }, 
[1] { product_id: 1, 
     ..., 
     bar: "xxx", 
     ... 
    } 

] 

New sollte wie sein:

[ 
[0] { product_id: 1, 
     ..., 
     bar: "abc", 
     ... 
    }, 
[1] { product_id: 1, 
     ..., 
     bar: "def", 
     ... 
    } 

] 

Aber was ich habe, ist bar: "def" für jeden. Gibt es eine saubere Methode in Schienen, um zu erreichen, was ich will? update_attributes gibt einen Fehler.

Ist der Titelname korrekt?

+0

Zunächst ist Ihre Frage nicht so erklärend. Wie können Sie bei der Abfrage von ID (Primärschlüssel) mehrere Datensätze zurückgeben? –

+1

Lassen Sie mich Ihnen sagen, was ich von Ihrer Frage verstanden habe. Sie sagen also, Sie haben ein Array von Werten (nach String-Splitting) Und Sie haben mehrere Model-Objekte (nach der Abfrage) und Sie möchten, dass jeder Wert für das Modell in der gleichen Reihenfolge gesetzt werden, richtig? –

+0

@QaisarNadeem Danke dafür. Beitrag aktualisiert. – Sylar

Antwort

1

Als erstes lassen Sie uns von einigen Grundlagen beginnen.

Sie möchten mehrere Zeilen aktualisieren und möchten für jede Zeile einen anderen Wert festlegen. Es kann also nicht in einer einzigen Abfrage ausgeführt werden, wie Sie es tun. Sie müssen also die Objekte Foo durchschleifen und jedes einzeln einstellen.

ist so

str = "abc---def---ghi---jkl" 
tokens = str.split('---') 
foos_to_update = Foo.where(product_id: 1) #Let's assume it will return 4 or lesser records. (otherwise you need to tell what do you wanna do if it returns more then `tokens`) 
foos_to_update.each_with_index {|foo,i| foo.update(bar: tokens[i])} 

Die letzte Zeile durch zurückgegebenen Objekte ist Looping und Einstellen des bar Wert für jedes Objekt übernehmen lassen.

1

Zunächst kann die Verwendung von Foo.where(id:1).update_all, um einen einzelnen Datensatz zu aktualisieren, funktionieren, ist aber nicht idiomatisch. Es ist besser, Foo.find_by(id: 1).update zu verwenden. Um einzelne Datensätze zu erhalten, verwende ich lieber find_by anstelle von find, weil es nil zurückgibt, anstatt NotFound-Fehler zu erhöhen, aber das ist eine persönliche Vorliebe.

Zweitens gibt Ihnen die Art, wie Sie update_all(bar: a) verwenden, unerwartete Ergebnisse. In einem map Block wird der zurückgegebene Wert Teil des resultierenden Arrays. update_all gibt den Datensatz, der geändert wurde, nicht zurück. Es gibt eine ganze Zahl zurück, die die Anzahl der Datensätze anzeigt, die geändert wurden. In ähnlicher Weise gibt update den Datensatz nicht zurück. Er gibt true oder false zurück, je nachdem, ob die Validierungen bestanden wurden.

diese Konzepte Binden zusammen, kann der folgende Code geschrieben werden:

str = "abc---def"  
str.split('---').map do |a| 
foo = Foo.find_by(id:1) 
foo&.update(bar: a) 
foo 
end 

# note that you could instead write `foo.update(bar: a)` if you 
# don't want to use the safe navigation operator 

Oder eine andere Art und Weise, es zu schreiben, das macht das Gleiche:

str = "abc---def" 
str.split('---').map do |a| 
Foo.find_by(id:1)&.tap { |foo| foo.update(bar: a) } 
end 

Beachten Sie, dass ich in diesen Beispielen bin Verwenden Sie die safe navigation operator, die in Ruby-Versionen neuer als 2.3 ist. Es hilft NoMethodError auf keine Objekte zu verhindern, ist aber nicht wirklich notwendig.

+0

Was ist '& .tap'? Schienen 5 Methode? – Sylar

+0

[tap] (http://ruby-doc.org/core-2.3.1/Object.html#method-i-tap) ist im Ruby-Kern seit 1.9. Es ist keine wesentliche Methode zu verwenden. Ich denke, dass es hauptsächlich stilistisch ist und die Lesbarkeit verbessert. Das '& .' ist der sichere Navigationsoperator, mit dem ich verbunden bin. –

+0

Ich musste Qaisars Antwort akzeptieren, da es mir klarer ist. Jedoch. keiner von euch hat geantwortet. Ich habe es schon oft versucht. Der letzte Code hat die Tabellenspalte nie aktualisiert. Zuerst bekam ich einen Syntaxfehler: 'foo & .update (Dateiname: a)' – Sylar

Verwandte Themen