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

ami*_*amb 10 ruby-on-rails ruby-on-rails-3

我正在使用simple_form并希望覆盖读者的模型属性.

因此,以下不起作用

class C < ActiveRecord::Base

  # it has attribute named pack

  def pack
    "Some value"
  end

end
Run Code Online (Sandbox Code Playgroud)

在视图中有以下代码

<%= simple_form_for @c do |f| %>
  <%= f.input :pack %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

因此它应该显示带有值"Some value"的输入框的形式,但它是空白的.为什么不覆盖simple_form的工作?

Kri*_*ris 12

我想出来了,我的评论基本上是正确的,simple_form倾向于Rails表单助手,用于read_attribute从ActiveRecord对象获取值,从而读取数据库中的值而不使用您的方法.耦合持久性/域/表示的症状.解决这个问题的方法是:

 <%= f.input :pack, :input_html => { :value => @c.pack } %>
 # or
 <%= f.input :pack, :input_html => { :value => f.object.pack } %>
Run Code Online (Sandbox Code Playgroud)

或者,如果您希望这是默认行为,您可以创建自己的表单构建器,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
Run Code Online (Sandbox Code Playgroud)

并以您的形式:

<%= simple_form_for @c, :builder => MyFormBuilder do |f| %>
  <%= f.input :pack %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

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


Mic*_*sch 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)
Run Code Online (Sandbox Code Playgroud)

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

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

  alias pack_before_type_cast pack
Run Code Online (Sandbox Code Playgroud)

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