关于简单形式:rails simple_form字段与模型无关

rails simple_form fields not related to the model

我有一个现有的表单绑定到一个名为"order"的模型,但我想添加新的表单字段,该字段将捕获信用卡信息,如名称、抄送号码等,这些信息将在第三方支付网关上处理。

但由于我不想在数据库中保存CC信息,所以在我的ORDER表中没有相应的列。这在提交表单时给了我一个错误,即这些信用卡输入字段不是订单模型的"一部分"。


如果我正确理解了你的答案,你想做的就是在官方的wiki页面上解释:创建一个不读取属性的假输入。根据Edward的建议,可以使用与任何实际数据库列无关的字段,但是如果表单字段与模型无关,则不需要在模型中定义属性。

总之,页面中介绍的技巧是定义一个名为"fakeinput"的自定义输入,并按如下方式使用:

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

在添加/修改一个自定义输入之后,不要忘记重新启动Rails服务器,正如装配工所评论的那样。

更新:请注意,官方wiki页面已更新,wiki页面上的示例代码不适用于使用旧版本simpleform的用户。如果遇到类似undefined method merge_wrapper_options for...的错误,请使用下面的代码。我使用的是3.0.1,这个代码工作得很好。

1
2
3
4
5
6
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


您可以使用attr_访问器

1
2
3
4
5
6
 class Order < ActiveRecord::Base

   attr_accessor :card_number


 end

现在您可以执行Order.first.card_number = '54421542122',或者以您的形式使用它,或者您需要执行的任何其他操作。

有关ruby文档,请参见http://www.ruby-doc.org/core-1.9.3/module.html method-i-attr_accessor这里有一个有用的stackoverflow问题,ruby中的attr_访问器是什么?

别把它和ATTR混淆了!attr_访问器和attr_访问器之间的区别


处理这一问题的最佳方法是像这样使用simple_fields_for

1
2
3
4
5
6
7
8
9
<%= 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,因为简单的表单会试图实例化一个用户模型,我们会再次收到相同的错误消息…


另外,如果您只是想添加一些东西并将其放入params,但不考虑模型的散列值,您可以只做formtaghelpers。http://api.rubyonrails.org/classes/actionview/helpers/formtaghelper.html

例子:

1
2
3
4
5
6
7
8
    <%= 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 -%>


我发现了一个非常简单(有些奇怪)的解决方法。

只需将input_html选项添加到任何value键中即可。例如:

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

测试简单版本:3.2.1、3.5.1