Ruby 重构 rails form 的时间选择器

xiaoxiao · 2017年07月31日 · 最后由 Rei 回复于 2017年08月07日 · 2590 次阅读

实际项目中 form 表单中的时间选择器很常见,rails 提供了默认的时间选择器 date_select 方法具体的使用如下:

<%= form_for(@post, :html => { :role => "form" }) do |f| %>
  <div class="form-group">
    <%= f.label :publish_time, :class => "control-label" %>
    <%= f.date_select :publish_time  %>
  </div>
</div>

然而默认生成的样式比较难看,网上搜索了很多 datetimepick 的插件,最终决定使用 bootstrap+flatpicker 生成时间选择器。

//加入bootstrap和flatpicker到Gemfile
gem 'jquery-rails'
gem 'flatpickr_rails'
gem 'bootstrap-sass', '3.3.7'
//assets中加入bootstrap和flatpicker
app/assets/javascripts/application.js 
//= require jquery
//= require bootstrap
//= require flatpickr
app/assets/stylesheets/application.scss 
 *= require flatpickr
@import "bootstrap-sprockets";
@import "bootstrap";
//创建config/initializers/flatpickr_data_select.rb
module ActionView
  module Helpers
    class FormBuilder 
       def flatpickr_date_select(method, options = {}, html_options = {})
           default_placeholder_hash={:placeholder=>"select data"}
           placeholder_hash=default_placeholder_hash.merge(options)
           existing_date = @object.send(method)
           formatted_date = existing_date.to_time.strftime("%F") if existing_date.present?
           @template.content_tag(:div, :class => "input-group flatpicker_date_select") do
                text_field(method, :value => formatted_date, :class => "form-control flatpickr-input",:data=>{:input=>""}, :placeholder=>placeholder_hash[:placeholder]) +
                @template.content_tag(:span, @template.content_tag(:span, "", :class => "glyphicon glyphicon-calendar", :data=>{:toggle=>"1"} ) ,:class => "input-group-addon")+
                @template.content_tag(:span, @template.content_tag(:span, "", :class => "glyphicon glyphicon-remove", :data=>{:clear=>"1"} ) ,:class => "input-group-addon")
          end
       end
     end
   end
end
//form表单中调用
<div class="form-group">
    <%= f.label :receive_time, :class=>"control-label" %>
    <%= f.flatpickr_date_select :receive_time %>
</div>
<script>
    $('.flatpicker_date_select').flatpickr({wrap:true,"locale":"zh"});
</script>

具体对比效果

让我们将重构进行到底!


        #  默认的值应该取 I18n 值
        #  default_placeholder_hash={:placeholder=>"select data"}
        #  placeholder_hash=default_placeholder_hash.merge(options)
        #  send 方法太过于强大, 现在应该还不需要它
        #  existing_date = @object.send(method)
        #  判断如果为 false 下面的程序找不到 formatted_date 变量
        #  formatted_date = existing_date.to_time.strftime("%F") if existing_date.present?

module ActionView
  module Helpers
    class FormBuilder
       def flatpickr_date_select(field, options = {}, html_options = {})
           raise 'unknown fields' unless @object.attributes.keys.include?(field.to_s)
           i18n_placeholder = I18n.t("activerecord.attributes.#{@object.class.name.underscore}.#{field}")
           placeholder = options.stringify_keys["placeholder"] || i18n_placeholder
           value = @object.attributes[field.to_s].to_s.to_time.strftime("%F") rescue ''

           @template.content_tag(:div, class: "input-group flatpicker_date_select") do
                text_field(field, value: value, class: "form-control flatpickr-input",
                    data: {input: ""}, placeholder: placeholder) +
                @template.content_tag(:span,
                    @template.content_tag(:span, "", class: "glyphicon glyphicon-calendar",
                        data: {toggle: "1"} ), class: "input-group-addon")+
                @template.content_tag(:span,
                    @template.content_tag(:span, "", class: "glyphicon glyphicon-remove",
                        data: {clear: "1"} ) ,class: "input-group-addon")
          end
       end
     end
   end
end
$(".selector").flatpickr(optional_config);

本身 API 就很简单,写那么复杂干什么?

出现了这样的问题。。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号