web-dev-qa-db-fra.com

rails champs simple_form non liés au modèle

J'ai un formulaire existant lié à un modèle nommé `` Commande '', mais je souhaite ajouter de nouveaux champs de formulaire qui captureront les informations de carte de crédit telles que le nom, le numéro cc, etc. à traiter sur une passerelle de paiement tierce.

Mais comme je ne veux pas enregistrer les informations CC dans notre base de données, il n'y a pas de colonnes correspondantes dans ma table de commande. Et cela me donne une erreur lors de la soumission du formulaire que ces champs de saisie de carte de crédit ne font pas partie du modèle de commande.

70
zeratool

Vous pouvez utiliser attr_accessor

 class Order < ActiveRecord::Base

   attr_accessor :card_number


 end

Vous pouvez maintenant faire Order.first.card_number = '54421542122' ou utilisez-le dans votre formulaire ou tout ce que vous devez faire.

Voir ici pour Ruby docs http://www.Ruby-doc.org/core-1.9.3/Module.html#method-i-attr_accessor et ici pour une question utile de stackoverflow Qu'est-ce que attr_accessor dans Ruby?

Ne le mélangez pas avec attr_accessible! Différence entre attr_accessor et attr_accessible

40
Edward

Si je comprends bien votre réponse, ce que vous voulez faire est expliqué sur la page wiki officielle ici: Créez une fausse entrée qui ne lit PAS les attributs . Vous pouvez utiliser un champ qui n'est lié à aucune colonne de base de données réelle par la suggestion d'Edward, mais vous n'avez pas besoin de définir un attribut dans votre modèle si le champ de formulaire n'a rien à voir avec le modèle.

En résumé, l'astuce expliquée dans la page consiste à définir une entrée personnalisée appelée "FakeInput" et à l'utiliser comme ceci:

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

N'oubliez pas de redémarrer votre Rails serveur après avoir ajouté/modifié une entrée personnalisée comme l'a commenté Fitter Man.

MISE À JOUR: Veuillez noter que la page wiki officielle a été mise à jour et l'exemple de code sur la page wiki ne fonctionne pas pour ceux qui utiliser des versions plus anciennes de SimpleForm. Utilisez le code ci-dessous à la place si vous rencontrez une erreur comme undefined method merge_wrapper_options for.... J'utilise 3.0.1 et ce code fonctionne bien.

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
47
baxang

La meilleure façon de gérer cela est d'utiliser simple_fields_for ainsi:

<%= 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 %>

Dans cet exemple, j'ai ajouté un nouveau champ appelé change_password qui ne fait pas partie du modèle user sous-jacent.

La raison pour laquelle il s'agit d'une bonne approche, c'est qu'elle vous permet d'utiliser n'importe laquelle des entrées/enveloppes de formulaire simples comme champs. Je ne me soucie pas de la réponse de @baxang, car elle ne vous permet pas d'utiliser différents types d'entrées. Cela semble plus flexible.

Remarquez que pour que cela fonctionne, j'ai dû passer :other à simple_fields_for. Vous pouvez passer n'importe quelle chaîne/symbole tant qu'il n'y a pas de modèle du même nom.

C'est à dire. malheureusement je ne peux pas passer :user, car simple_form tenterait d'instancier un modèle utilisateur, et nous obtiendrions à nouveau le même message d'erreur ...

37
asgeo1

De plus, si vous essayez simplement d'ajouter quelque chose et de le mettre dans le params, mais en le laissant hors du hachage du modèle, vous pouvez simplement faire FormTagHelpers. http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html

Exemple:

    <%= 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 -%>
13
Richard Ortega

J'ai trouvé une solution de contournement très simple (et quelque peu étrange).

Ajoutez simplement le input_html option avec n'importe quelle touche value à l'intérieur. Par exemple:

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

Versions testées simple_from: 3.2.1, 3.5.1

1
user1201917