高度以英寸存储在数据库中.
然而脚和英寸需要以下形式的自己的个人投入:
Height: [_______] feet [_______] inches
所以我使用虚拟属性,并使其工作.这是我的模型的简化版本:
class Client < ActiveRecord::Base attr_accessible :name,:height_feet,:height_inches before_save :combine_height def height_feet height.floor/12 if height end def height_feet=(feet) @feet = feet end def height_inches if height && height%12 != 0 height%12 end end def height_inches=(inches) #on save? @inches = inches end def combine_height self.height = @feet.to_d*12 + @inches.to_d #if @feet.present? end end
而_form部分使用simple_form:
<%= simple_form_for(@client) do |f| %> <ul> <%= f.error_notification %> <%= f.input :name %> <%= f.input :weight %> <li> <%= f.input :height_feet,:label => 'Height',:wrapper => false %> <span>feet</span> <%= f.input :height_inches,:label => false,:wrapper => false %> <span>inches</span> </li> <%= f.error :base %> </ul> <%= f.button :submit %> <% end %>
这个工作.但这不是理想的.
我想DRY这个,并创建一个custom input component,所以我可以添加高度的形式与<%= f.input:height,as::feet_and_inch%> – 因此任何其他输入,遵循相同的模式,as<%= f.input:wingspan,as::feet_and_inch%> ;. 我已经尝试过自定义组件,但是我无法得到两个输入显示,而且我不确定哪里是将“转换”逻辑从英尺和英寸放到英寸的最佳位置(同样从英寸回到英尺和英寸).
解决方法
据我所知,除了渲染到自定义输入之外,你不能移动任何东西.一旦表单被提交,SimpleForm就不会被调用,所以它不能以任何方式真正地干扰这些值.我过去也需要它,我很乐意这样做.无论如何,这里是一个保留模型中的转换逻辑的版本.
自定义SimpleForm输入:
# app/inputs/feet_and_inch_input.rb class FeetAndInchInput < SimpleForm::Inputs::Base def input output = "" label = @options.fetch(:label) { @attribute_name.to_s.capitalize } feet_attribute = "#{attribute_name}_feet".to_sym inches_attribute = "#{attribute_name}_inches".to_sym output << @builder.input(feet_attribute,wrapper: false,label: label) output << template.content_tag(:span," feet ") output << @builder.input(inches_attribute,label: false) output << template.content_tag(:span," inches ") output.html_safe end def label "" end end
表格.请注意,我没有将< li>标签里面的自定义输入,我认为这样更灵活,但随意改变它.
# app/views/clients/_form.html.erb <li> <%= f.input :height,as: :feet_and_inch %> </li>
所有这一切都取决于对于每个height属性,你也有height_feet和height_inches属性.
现在,对于这个模型,我不是诚实地确定这是否可以走,也许有人可能会提出一个更好的解决方案,但是在这里:
class Client < ActiveRecord::Base attr_accessible :name ["height","weight"].each do |attribute| attr_accessible "#{attribute}_feet".to_sym attr_accessible "#{attribute}_inches".to_sym before_save do feet = instance_variable_get("@#{attribute}_feet_ins_var").to_d inches = instance_variable_get("@#{attribute}_inches_ins_var").to_d self.send("#{attribute}=",feet*12 + inches) end define_method "#{attribute}_feet" do value = self.send(attribute) value.floor / 12 if value end define_method "#{attribute}_feet=" do |feet| instance_variable_set("@#{attribute}_feet_ins_var",feet) end define_method "#{attribute}_inches=" do |inches| instance_variable_set("@#{attribute}_inches_ins_var",inches) end define_method "#{attribute}_inches" do value = self.send(attribute) value % 12 if value && value % 12 != 0 end end end
它基本上是一样的,但动态定义方法.您可以在顶部看到一个属性列表,您希望生成这些方法.
请注意,所有这一切都没有经过彻底的测试,可能会杀死你的猫,但希望可以给你一些想法.