覆盖模型属性读取器不会影响simple_form输入字段

时间:2012-05-26 16:13:09

标签: ruby-on-rails ruby-on-rails-3

我正在使用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?

2 个答案:

答案 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

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