Rails simple_form поля, не относящиеся к модели

У меня есть существующая форма, привязанная к модели с именем "Заказ", но я хочу добавить новые поля формы, которые будут захватывать информацию о кредитной карте, такую ​​как имя, номер cc и т.д., которые будут обрабатываться на стороннем платежном шлюзе.

Но так как я не хочу сохранять информацию CC в нашей базе данных, в моей таблице заказов нет соответствующих столбцов. И это дает мне ошибку при отправке формы, что поля ввода кредитной карты не являются "частью" модели заказа.

Ответ 1

Вы можете использовать attr_accessor

 class Order < ActiveRecord::Base

   attr_accessor :card_number


 end

Теперь вы можете сделать Order.first.card_number = '54421542122' или использовать его в своей форме или что-то еще, что вам нужно сделать.

См. здесь для ruby ​​docs http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-attr_accessor и здесь для полезного вопроса stackoverflow Что такое attr_accessor в Ruby?

Не смешивайте его с attr_accessible! Разница между attr_accessor и attr_accessible

Ответ 2

Если я правильно понимаю ваш ответ, то то, что вы хотите сделать, объясняется на официальной странице wiki здесь: Создайте поддельный вход, который НЕ читает атрибуты. Вы можете использовать поле, не относящееся к какому-либо реальному столбцу базы данных предложением Эдварда, однако вам не нужно определять атрибут в вашей модели, если поле формы не имеет ничего общего с моделью.

В целом, трюк, описанный на странице, определяет пользовательский ввод под названием "FakeInput" и использует его следующим образом:

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

Не забудьте перезапустить сервер рельсов после добавления/изменения пользовательского ввода, как комментировал Fitter Man.

ОБНОВЛЕНИЕ: Обратите внимание, что обновленная официальная страница вики и пример кода на вики-странице не работает для тех, кто использует более старые версии SimpleForm. Вместо этого используйте код ниже, если вы столкнулись с ошибкой, например undefined method merge_wrapper_options for.... Я использую 3.0.1, и этот код работает хорошо.

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

Ответ 3

Лучший способ справиться с этим - использовать simple_fields_for следующим образом:

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

В этом примере я добавил новое поле под названием change_password, которое не является частью базовой модели user.

Причина, по которой это хороший подход, заключается в том, что он позволяет использовать любые простые входы/оболочки в качестве полей. Мне не нужен ответ @baxang, потому что он не позволяет вам использовать разные типы входов. Это кажется более гибким.

Обратите внимание, что для этого мне пришлось пройти :other до simple_fields_for. Вы можете передать любую строку/символ , если нет модели с таким же именем.

т.е. к сожалению, я не могу передать :user, поскольку simple_form попытается создать экземпляр модели User, и мы снова получим одно и то же сообщение об ошибке...

Ответ 4

Кроме того, если вы просто пытаетесь что-то добавить и введите его в params, но оставив его вне хэша модели, вы можете просто сделать FormTagHelpers. http://api.rubyonrails.org/classes/ActionView/Helpers/FormTagHelper.html

Пример:

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