[英]Convert hours & minutes to seconds before saving a record
I am still very new to Rails. 我对Rails还是很陌生。 Thus far all of my form elements have mapped directly to their underlying Rails model counterparts. 到目前为止,我所有的表单元素都已直接映射到其基础的Rails模型副本。 In my current situation though that isn't possible. 在目前的情况下,这是不可能的。
My model has an event_duration
field which stores a duration in seconds ( integer
type). 我的模型有一个event_duration
字段,该字段存储以秒为单位的持续时间( integer
类型)。
In my form though I want to have two text fields: hours
and minutes
. 在我的表单中,尽管我想要两个文本字段: hours
和minutes
。 When the form is submitted I want to convert those values into seconds and store the resulting value in the model. 提交表单后,我想将这些值转换为秒并将结果值存储在模型中。
What is the best way to accomplish this? 做到这一点的最佳方法是什么? (Thank you in advance) (先感谢您)
You can create a 'hook' in your controller to update the params
right before the record is created/updated: 您可以在控制器中创建一个“钩子”以在创建/更新记录之前更新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
This code implies that you have an input with name event[:hours]
and another one with event[:minutes]
in your form. 此代码意味着您在表单中输入了一个名称为event[:hours]
的输入,另一个输入是event[:minutes]
。 If you already have an input with name event[:event_duration]
, it will be overwriten. 如果您已经有一个名称为event[:event_duration]
的输入,它将被覆盖。
You can create virtual attributes in your model: 您可以在模型中创建虚拟属性:
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
And in your form: 并以您的形式:
f.hidden_field :use_diff_event_duration_variables, true
f.text_field :hours_event_duration
f.text_field :minutes_event_duration
Another way to accomplish this is what's called a Form Object, which is essentially a "mock model" that you pass to your controller in lieu of your model, which then handles form rendering and persistence. 完成此操作的另一种方法是所谓的“表单对象”,它实际上是一个“模拟模型”,您可以将其传递给控制器以代替模型,然后由模型处理表单渲染和持久性。
The benefits of this is you don't need any logic in your controllers, and you can eliminate pesky callbacks from your models. 这样做的好处是您不需要控制器中的任何逻辑,并且可以从模型中消除讨厌的回调。 They also work exceptionally well for getting rid of those accepts_nested_attributes_for
traps when dealing with multiple models. 当处理多个模型时,它们还可以很好地摆脱那些accepts_nested_attributes_for
陷阱。
It can look something like this: 它看起来可能像这样:
# 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
By including some of the ActiveModel
modules, you can borrow some functionality, like initializing from a Hash
, and validations. 通过包括一些ActiveModel
模块,您可以借用一些功能,例如从Hash
初始化和验证。
And in your controller: 在您的控制器中:
# app/controllers/events_controller.rb
def new
@event = EventForm.new
end
def create
@event = EventForm.new(event_params).save
end
There are also Gems that you can use to create form objects, like reform , if you don't want to roll your own. 如果您不想自己动手,也可以使用Gems来创建表单对象,例如Reform 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.