【问题标题】:Convert hours & minutes to seconds before saving a record在保存记录之前将小时和分钟转换为秒
【发布时间】:2015-10-21 13:03:33
【问题描述】:

我对 Rails 还是很陌生。到目前为止,我所有的表单元素都直接映射到它们底层的 Rails 模型对应物。在我目前的情况下,这是不可能的。

我的模型有一个 event_duration 字段,它以秒为单位存储持续时间(integer 类型)。

在我的表单中,虽然我想要两个文本字段:hoursminutes。提交表单后,我想将这些值转换为秒并将结果值存储在模型中。

完成此任务的最佳方法是什么? (提前谢谢)

【问题讨论】:

    标签: ruby-on-rails forms model


    【解决方案1】:

    您可以在控制器中创建一个“挂钩”以在创建/更新记录之前更新params

    class EventsController < ApplicationController
      before_filter :sanitize_durations_in_params, only: [:create, :update]
    
      # ...
    
      def sanitize_durations_in_params
        hours = params[:event].delete(:hours).to_i
        minutes = params[:event].delete(:minutes).to_i
        minutes = minutes + hours * 60
        seconds = minutes * 60
        params[:event][:event_duration] = seconds
      end
    end
    

    此代码意味着您的表单中有一个名称为 event[:hours] 的输入和另一个名称为 event[:minutes] 的输入。如果您已经有一个名称为 event[:event_duration] 的输入,它将被覆盖。

    【讨论】:

      【解决方案2】:

      您可以在模型中创建虚拟属性:

      class Model < ActiveRecord::Base
        attr_reader :hours_event_duration, :minutes_event_duration, :use_diff_event_duration_variables
        before_save :correct_save_event_duration
      
        def initialize(*args)
          @hours_event_duration = @minutes_event_duration = 0
          @use_diff_event_duration_variables = false
          super
        end
      
        ... 
      
        protected
      
        def correct_save_event_duration
          self.event_duration = @hours_event_duration * 1.hour + @minutes_event_duration * 1.minute if @use_diff_event_duration_variables
        end
      end
      

      并以您的形式:

      f.hidden_field :use_diff_event_duration_variables, true
      f.text_field :hours_event_duration
      f.text_field :minutes_event_duration
      

      【讨论】:

        【解决方案3】:

        实现此目的的另一种方法是所谓的表单对象,它本质上是一个“模拟模型”,您可以将其传递给控制器​​以代替模型,然后由控制器处理表单呈现和持久性。

        这样做的好处是您的控制器中不需要任何逻辑,并且您可以消除模型中令人讨厌的回调。在处理多个模型时,它们在摆脱accepts_nested_attributes_for 陷阱方面也非常出色。

        它可能看起来像这样:

        # app/forms/event_form.rb
        class EventForm
          include ActiveModel::Model
          include ActiveModel::Validations
        
          attr_accessor :duration_hours, :duration_minutes, ... # Event parameters
        
          validates ... # Your validations
        
          def save
            if valid?
              persist!
            else
              false
            end
          end
        
          private
        
          def persist!
            event = Event.new(...) # Event parameters
            event.event_duration = ((duration_hours * 60) + duration_minutes) * 60
            event.save
          end
        end
        

        通过包含一些ActiveModel 模块,您可以借用一些功能,例如从Hash 初始化和验证。

        在你的控制器中:

        # app/controllers/events_controller.rb
        def new
          @event = EventForm.new
        end
        
        def create
          @event = EventForm.new(event_params).save
        end
        

        如果您不想自己滚动,还可以使用 Gem 来创建表单对象,例如 reform

        【讨论】:

          猜你喜欢
          • 2015-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多