Schienen simple_form Felder, die nicht mit dem Modell zusammenhängen

74

Ich habe ein vorhandenes Formular, das an ein Modell mit dem Namen "Bestellung" gebunden ist, aber ich möchte neue Formularfelder hinzufügen, in denen Kreditkarteninformationen wie Name, CC-Nummer usw. erfasst werden, die auf einem Zahlungsgateway eines Drittanbieters verarbeitet werden sollen.

Da ich aber keine CC-Informationen in unserer Datenbank speichern möchte, gibt es in meiner Bestellungstabelle keine entsprechenden Spalten davon. Und dies gibt mir einen Fehler beim Senden des Formulars, dass diese Kreditkarten-Eingabefelder nicht Teil des Bestellmodells sind.

Zeratool
quelle
Mögliches Duplikat von Simple_form ohne for (
Nichtmodellform
1
Diese Frage ist kein Duplikat der oben verlinkten Frage. Bei diesem handelt es sich um ganze Formen, die nicht mit Modellen verbunden sind. In diesem Fall werden ausgewählte Felder ausgewählt, die nicht mit dem Modell des Formulars verbunden sind.
Marcelo De Polli
2
Dies würde Ihnen alle möglichen Probleme mit der PCI-Konformität bereiten und ist äußerst gefährlich !! Obwohl Sie die CC-Informationen nicht in Ihrer Datenbank speichern, werden alle Details in Ihren Protokollen gespeichert, wenn Sie sie an Ihren Server senden. Wenn jemand Zugriff auf Ihre Protokolle hat, hat er Zugriff auf unverschlüsselte Client-CC-Informationen. Sie sollten diese Daten überhaupt nicht an Ihren Server senden. Wenn Sie es wirklich brauchen, schauen Sie sich die clientseitige Verschlüsselung an ( developer.braintreepayments.com/javascript+ruby/sdk/client/… ). Verwenden Sie andernfalls Direktpostformulare oder Drop-In-Tools von Drittanbietern. Viel Glück!
Jay

Antworten:

43

Sie können attr_accessor verwenden

 class Order < ActiveRecord::Base

   attr_accessor :card_number


 end

Jetzt können Sie Order.first.card_number = '54421542122'es in Ihrem Formular tun oder verwenden oder was auch immer Sie sonst noch tun müssen.

Hier finden Sie Ruby-Dokumente unter http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-attr_accessor und hier eine nützliche Frage zum Stackoverflow. Was ist attr_accessor in Ruby?

Verwechsle es nicht mit attr_accessible! Unterschied zwischen attr_accessor und attr_accessible

Edward
quelle
Ich habe eine Folgefrage, nachdem ich das Formular auf dem Controller gesendet habe. Wie kann ich diese CC-bezogenen Felder beim Aufruf von 'model.save' "deaktivieren", da dies zu Fehlern führen kann?
Zeratool
1
Sie könnten params.except(:card_number)in Ihrem Controller verwenden.
Trung Lê
47

Wenn ich Ihre Antwort richtig verstehe, wird auf der offiziellen Wiki-Seite hier erklärt, was Sie tun möchten: Erstellen Sie eine gefälschte Eingabe, die KEINE Attribute liest . Sie können nach Edwards Vorschlag ein Feld verwenden, das sich nicht auf eine echte Datenbankspalte bezieht. Sie müssen jedoch kein Attribut in Ihrem Modell definieren, wenn das Formularfeld nichts mit dem Modell zu tun hat.

Zusammenfassend lässt sich sagen, dass der auf der Seite erläuterte Trick darin besteht, eine benutzerdefinierte Eingabe mit dem Namen "FakeInput" zu definieren und wie folgt zu verwenden:

<%= simple_form_for @user do |f| %>
  <%= f.input :agreement, as: :fake %>
  ....

Vergessen Sie nicht, Ihren Rails-Server neu zu starten, nachdem Sie eine benutzerdefinierte Eingabe hinzugefügt / geändert haben, wie von Fitter Man kommentiert.

UPDATE: Bitte beachten Sie, dass die offizielle Wiki-Seite aktualisiert wurde und der Beispielcode auf der Wiki-Seite für diejenigen, die ältere Versionen von SimpleForm verwenden, nicht funktioniert. Verwenden Sie stattdessen den folgenden Code, wenn Sie auf einen Fehler wie z undefined method merge_wrapper_options for.... Ich benutze 3.0.1 und dieser Code funktioniert gut.

class FakeInput < SimpleForm::Inputs::StringInput
  # This method only create a basic input without reading any value from object
  def input
    template.text_field_tag(attribute_name, input_options.delete(:value), input_html_options)
  end
end
Baxang
quelle
Nett. Das hatte ich nie bemerkt.
Edward
2
Möglicherweise müssen Sie Ihren Webserver neu starten / neu laden, damit dies erkannt wird.
Fitter Man
Aus irgendeinem Grund funktioniert es nicht mehr. undefined method merge_wrapper_options for #<FakeInput:0x007fbe5e32beb8>
Trein
@Trein Welche Version von Rails / SimpleForm verwenden Sie?
Baxang
@baxang Ich benutze v3.0.2. Funktioniert es auf RC-Versionen? Ich kann die RC-Version für dieses Projekt leider nicht verwenden (Richtlinien ...).
Trein
40

Der beste Weg, um damit umzugehen, ist simple_fields_forwie folgt zu verwenden :

<%= simple_form_for @user do |f| %>
  <%= f.input :first_name %>
  <%= f.input :last_name %>
  <%= f.input :email %>

  <%= simple_fields_for :other do |o| %>
    <%= o.input :change_password, as: :boolean, label: 'I want to change my password' %>
  <% end %>
<% end %>

In diesem Beispiel habe ich ein neues Feld mit dem Namen hinzugefügt, change_passworddas nicht Teil des zugrunde liegenden userModells ist.

Der Grund, warum dies ein guter Ansatz ist, besteht darin, dass Sie alle einfachen Formulareingaben / Wrapper als Felder verwenden können. Die Antwort von @baxang ist mir egal, da Sie damit keine verschiedenen Arten von Eingaben verwenden können. Dies scheint flexibler.

Hinweis obwohl für diese Arbeit, ich hatte passieren :otherzu simple_fields_for. Sie können eine beliebige Zeichenfolge / ein beliebiges Symbol übergeben , solange es kein Modell mit demselben Namen gibt .

Dh leider kann ich nicht bestehen :user, da simple_form versuchen würde, ein Benutzermodell zu instanziieren, und wir würden wieder die gleiche Fehlermeldung erhalten ...

asgeo1
quelle
Die einfachsten Antworten sind die besten. Funktioniert bei mir.
leere Wände
14

Auch wenn Sie nur versuchen, etwas hinzuzufügen und in das zu integrieren params, es aber aus dem Hash des Modells herauslassen, können Sie einfach FormTagHelpers ausführen. http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html

Beispiel:

    <%= simple_form_for resource, :as => resource_name, :url =>   invitation_path(resource_name), :html => {:method => :post} do |f| %>
       <%= devise_error_messages! %>

    <% resource.class.invite_key_fields.each do |field| -%>
       <%= f.input field %>
       <%= hidden_field_tag :object_name, @object.class.name %>
       <%= hidden_field_tag :object_id, @object.id %>
    <% end -%>
Richard Ortega
quelle
5

Ich fand eine sehr einfache (und etwas seltsame) Problemumgehung.

Fügen Sie einfach die input_htmlOption mit einem beliebigen valueSchlüssel hinzu. Z.B:

= simple_form_for @user do |f|
  = f.input :whatever, input_html: {value: ''}

Getestet simple_from Versionen: 3.2.1, 3.5.1

user1201917
quelle