我正在使用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 %>
因此它应该显示具有值“Some value”的输入框的形式,但它是空白的。为什么不覆盖使用simple_form?
答案 0 :(得分:12)
我认为这一点,我的评论基本上是正确的,simple_form
倾向于使用read_attribute
从Rails表单帮助程序获取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 或将其放入{{ 1}}(免责声明不是一个好主意,lib更好)。
答案 1 :(得分: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
这对我有用,只要确保在那里返回一个字符串......