0

我正在使用日期时间在日历中保存一些约会。通过这种方式,我可以将日期和时间存储在一起,而不会使这两个值不同。

我想要的是允许用户编辑约会和更改日期/时间。事实上,我不能让用户自由选择任何时间,但任何约会都必须设置在预定义的时间范围内(24 小时格式:10、12、14、16、18、20)。

由于在文档中我找不到任何自定义方法,datetime_select因此我实际上使用的是以下表单:

.control-group
  = f.label :start_at, :class => 'control-label'
  .controls
    = f.date_select :start_at, :value => f.object.start_at, :class => "datetimefield"
.control-group
  = f.label :start_at, :class => 'control-label'
  .controls
    = f.select :start_at, :value => Event::ALLOWED_HOURS, :class => 'number_field'

Event::ALLOWED_HOURS是一个数组,其中包含我想让用户从中选择的时间。提交此表单时,更新操作会丢失时间信息,从而导致日期时间如下:2012-05-18 00:00:00而不是使用我的选择中定义的小时。

我该怎么做才能根据需要完成这项工作?

这是控制器,请注意这是一个嵌套资源EventCalendar

class EventsController < ApplicationController
  before_filter :authenticate_user!
  load_and_authorize_resource

  # GET /events
  # GET /events.json
  def index
    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @events }
    end
  end

  # GET /events/1
  # GET /events/1.json
  def show
    @event_calendar = EventCalendar.find(params[:event_calendar_id])
    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @event }
    end
  end

  # GET /events/new
  # GET /events/new.json
  def new
    @event_calendar = EventCalendar.find(params[:event_calendar_id])
    @start_at = Time.parse("#{params[:day]} #{params[:hour]}")
    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @event }
    end
  end

  # GET /events/1/edit
  def edit
    @event_calendar = EventCalendar.find(params[:event_calendar_id])
  end

  # POST /events
  # POST /events.json
  def create
    @event_calendar = EventCalendar.find(params[:event_calendar_id])
    @start_at = params[:start_at]

    respond_to do |format|
      if @event.save
        format.html { redirect_to root_path, notice: 'Appuntamento creato con successo.' }
        format.json { render json: @event = EventCalendar.find(params[:event_calendar_id]), status: :created, location: @event }
      else
        format.html { render action: "new" }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end

  # PUT /events/1
  # PUT /events/1.json
  def update
    @event_calendar = EventCalendar.find(params[:event_calendar_id])
    respond_to do |format|
      if @event.update_attributes(params[:event])
        format.html { redirect_to root_path, notice: 'Appuntamento aggiornato con successo.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /events/1
  # DELETE /events/1.json
  def destroy
    @event_calendar = EventCalendar.find(params[:event_calendar_id])
    @event.destroy

    respond_to do |format|
      format.html { redirect_to root_url, notice: 'Appuntamento cancellato con successo.'}
      format.json { head :no_content }
    end
  end
end
4

2 回答 2

2

根据大卫的建议,我将创建一个虚拟属性start_at_hours,而不是将线放在控制器内,只需编辑模型,将回调Event定义为:before_update

# inside your model
before_update :set_hour

def start_at_hours
  if !self.start_at.blank?
    self.start_at.hour
  end
end

def start_at_hours=(value)
end

# model code ...
private
def set_hour
  self.start_at = Time.parse(self.start_at.to_s) + self.start_at_hours.to_i.hours
end

这应该可以根据您的需要正常工作,没有例外。它与 David 的解释做同样的事情,但是直接在模型中而不需要改变你的控制器。

编辑:通过定义一个getter和一个setter,您还可以为您的选择设置默认值(在这种情况下不需要setter,但我还是把它放了)。

于 2012-05-18T14:31:54.073 回答
0

问题出在:您的创建(和更新)方法在创建@start_at变量时没有查看小时字段。尝试以下,它应该工作:

.control-group
  = f.label :start_at, :class => 'control-label'
  .controls
    = f.date_select :start_at, :value => f.object.start_at, :class => "datetimefield"
.control-group
  = f.label :start_at, :class => 'control-label'
  .controls
    = f.select "start_at_hours", :value => Event::ALLOWED_HOURS, :class => 'number_field'

在控制器上的更新方法中:

# PUT /events/1
# PUT /events/1.json
  def update
    @event_calendar = EventCalendar.find(params[:event_calendar_id])
    respond_to do |format|
      params[:start_at] = Time.parse(params[:start_at]) + params[:start_at_hours].to_i.hours
      if @event.update_attributes(params[:event])
        format.html { redirect_to root_path, notice: 'Appuntamento aggiornato con successo.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @event.errors, status: :unprocessable_entity }
      end
    end
  end

关键是这一行:

params[:start_at] = Time.parse(params[:start_at]) + params[:start_at_hours].to_i.hours

它将start_at参数(仅包含日期)替换为包含额外时间的新时间对象。

于 2012-05-18T14:01:55.823 回答