我仍然是Rails的新手。到目前为止,我的所有表单元素都直接映射到它们的底层Rails模型对应物。在我目前的情况下,虽然这是不可能的。
我的模型有一个event_duration
字段,以秒为单位存储持续时间(integer
类型)。
在我的表单中,我希望有两个文本字段:hours
和minutes
。提交表单时,我想将这些值转换为秒,并将结果值存储在模型中。
实现这一目标的最佳方法是什么? (先谢谢你)
答案 0 :(得分:2)
您可以创建一个' hook'在您的控制器中,在创建/更新记录之前更新$
:
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]
的输入,那么它将被覆盖。
答案 1 :(得分:1)
您可以在模型中创建虚拟属性:
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
答案 2 :(得分:1)
另一种实现此目的的方法是所谓的表单对象,它本质上是一个“模型”,您可以将其传递给控制器,代替您的模型,然后处理表单呈现和持久性。
这样做的好处是你的控制器中不需要任何逻辑,你可以从你的模型中消除讨厌的回调。在处理多个模型时,它们也能很好地摆脱那些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
如果您不想自己动手,也可以使用Gems来创建表单对象,例如reform。