10

我正在使用 simple_form 并希望覆盖模型属性的阅读器。

因此以下不起作用

class C < ActiveRecord::Base

  # it has attribute named pack

  def pack
    "Some value"
  end

end

鉴于有以下代码

<%= simple_form_for @c do |f| %>
  <%= f.input :pack %>
<% end %>

因此它应该显示输入框的表单,输入框的值为“某些值”,但它是空白的。为什么不使用 simple_form 覆盖?

4

2 回答 2

13

我想通了,我的评论基本上是正确的,simple_form依赖于 Rails 表单助手,它用于read_attribute从 ActiveRecord 对象中获取值,从而读取数据库中的值而不使用您的方法。耦合持久性/域/表示的症状。解决方法是:

 <%= f.input :pack, :input_html => { :value => @c.pack } %>
 # or
 <%= f.input :pack, :input_html => { :value => f.object.pack } %>

或者,如果您希望这是默认行为,您可以在以下基础上创建自己的表单构建器simple_for

# lib/my_form_builder.rb **

class MyFormBuilder < SimpleForm::FormBuilder                                                                                               
  def input(attribute_name, options={}, &block)                                 
    options[:input_html] ||= {}                                                 
    options[:input_html][:value] = object.send(attribute_name)                  
    super(attribute_name, options, &block)                                                          
  end
end

并以您的形式:

<%= simple_form_for @c, :builder => MyFormBuilder do |f| %>
  <%= f.input :pack %>
<% end %>

** 在 Rails 3 中,我认为lib默认情况下不会将其添加到加载路径中,因此您可能需要添加它并重新启动应用程序将其放入app/models(免责声明不是一个好主意,lib 更好)。

于 2012-08-26T22:50:32.790 回答
5

至少在 Rails 3.2 中,它不再直接使用 read_attribute。但是,如果您使用的是文本字段,它会使用InstanceTag.value_before_type_cast来检索值。这使用:

object.respond_to?(method_name + "_before_type_cast") ?
  object.send(method_name + "_before_type_cast") :
  object.send(method_name)

(其中 method_name 是该上下文中的属性名称)

因此,如果您想确保表单使用您的属性访问器,请添加以下别名:

  alias pack_before_type_cast pack

这对我有用,只要确保在那里返回一个字符串......

于 2013-04-27T06:38:42.010 回答