2016-05-31 8 views
1

Grundsätzlich möchte ich eine Option in meinem Formular erstellen, die Kontrollkästchen akzeptiert (0 bis alle Werte akzeptiert).Wie kann ich mehrere Checkboxed-Werte mit SimpleForm ordnungsgemäß speichern?

Ich liebe die Struktur von enums, weil ich die Leistungsgeschwindigkeit der Speicherung der Ganzzahl in der DB, aber ich kann das Symbol in meinem Code verweisen. Ich bezweifle jedoch, dass ich Enum verwenden kann, wenn ich mehrere Werte wie ein Kontrollkästchen speichere.

So stelle ich mir vor, dass es am besten funktioniert, wenn man es einfach als String speichert, der auch ein Array ist. So etwas wie folgt aus:

# refactor_rule   :string   default([]), is an Array 

Dann meine Form wie folgt aussieht:

<%= f.input :refactor_rule, collection: ["dry", "concise", "performant"], as: :check_boxes, class: "form-control" %> 

Das Problem bei diesem Ansatz ist, wenn ich speichern nur 1 oder 2 der Optionen (dh nicht alle), ist dies was das Attribut wie folgt aussieht:

q.refactor_rule 
=> ["", "dry", "concise"] 

was ich hasse, wegen der leeren Wert bei [0].

So sind meine Fragen wie folgt:

  1. Was ist die performante Art und Weise, dies zu erreichen? Beachten Sie, dass die Optionen in meinem Kontrollkästchen statisch sind, aber das Feld muss mehrere nicht 1 akzeptieren?
  2. Wie speichere ich nur die geprüften Werte und nicht leere Werte?
  3. Gibt es eine Möglichkeit, die integrierte Enum-Funktionalität von Rails zu nutzen, obwohl ich mehrere Werte speichere?

Antwort

1

Sie können immer so etwas wie dieses, um Ihre Attribute „reinigen“:

q.refactor_rule.reject!(&:empty?) 

Welche gonna alle leeren Elemente von Ihnen Array ablehnen. Beachten Sie die !. reject! ersetzt es ohne die leeren Elemente, reject gibt es einfach zurück. Ihr Anruf !

Wenn Sie wirklich ein Array in der Datenbank speichern müssen, können Sie es wie so tun, in der Migration:

create_table :products do |t| 
    t.text :tags, array: true, default: [] 
end 

(Dies ist von this blog post von Plataformatec)

+0

Wenn ich kein 'Array' in der DB verwende, wie kann ich es speichern? Ein Faden? Ich habe es bereits als ein Array in der Datenbank eingerichtet. – marcamillion

+0

Sie möchten dies nicht als String speichern, da Sie es jedes Mal dekodieren müssen, wenn Sie dies lesen/aktualisieren möchten. Wenn es für Sie Sinn macht, machen Sie ein anderes Modell ("RefactorRule" genannt) mit einer Beziehung "has_many: refactor_rules". Auf diese Weise können Sie die Kraft der Assoziation nutzen und Rails mit voller Geschwindigkeit nutzen :) – Stan

2

Statt einer Enum (performant, aber nur ein einzelner Wert gespeichert werden kann) oder ein serialisiertes Array (verlangsamt und Speicherplatzbedarf). Sie sollten in Betracht ziehen, die booleschen Werte als ein Bitfeld zu speichern. Dieser Ansatz konvertiert mehrere boolesche Werte (Flags) in eine einzelne Integer-Spalte, in der jedes Flag seine eigene Bitposition in der Ganzzahl hat. Dies wirkt sich natürlich massiv positiv auf die Performance aus - Sie können mit der & operator (in MySQL) nach einer beliebigen Kombination von Flags suchen, anstatt nach Teilstrings in einer Textspalte zu suchen.

Werfen Sie einen Blick auf die flag_shih_tzu oder die bitfields Edelsteine. Beide Edelsteine ​​erweitern Active Record, so dass alle Flags als separate "virtuelle" Attribute eines Modellobjekts fungieren und sie bequeme Methoden zum Durchsuchen solcher Attribute bieten.Damit dies funktioniert, müssten Sie wahrscheinlich das simple_form-Formular neu schreiben, um 3 separate Kontrollkästchen anstelle eines einzigen zu verwenden.

+0

Interessant ... Danke, dass Sie mir diese Option gegeben haben. Ich werde wahrscheinlich nicht diese Route gehen, aber es ist interessant zu erkunden. – marcamillion

Verwandte Themen