2012-05-18 2 views
0

Я использую datetime для сохранения некоторых встреч в календаре. Таким образом, я могу хранить дату и время без учета двух значений.Datetime select определить диапазон часов

Я хочу, чтобы пользователи могли редактировать назначение и изменять дату и время. Дело в том, что я не могу оставлять пользователя свободным выбирать любой час, но любое назначение должно быть установлено в предопределенном диапазоне часов (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 представляет собой массив, содержащий часы, которые я хочу, чтобы пользователи могли выбирать. При отправке этой формы действие обновления теряет информацию о времени, в результате чего datetime вроде: 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 
+0

Пожалуйста, разместите свой код контроллера, который обрабатывает эту форму. –

ответ

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 

Это должно работать, как вам нужно без исключений , Это то же, что объяснение Дэвида, но непосредственно в модели без необходимости менять ваш контроллер.

Редактировать: определяя геттер и сеттер, вы также можете установить значение по умолчанию для вашего выбора (сеттер в этом случае не нужен, но я все равно его поместил).

+0

Все работает отлично! Но только если я объявляю виртуальный атрибут как 'attr_accessor'. –

+1

Хороший ответ! Определенно улучшение по сравнению с моим :) –

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 параметров (который содержит только дату) с новым объектом Time, в который включены дополнительные часы.

+0

Спасибо за ваш ответ. Я поместил эту строку в свой код, затем создал виртуальный атрибут 'start_at_hours', но при отправке формы я получаю' не могу преобразовать nil в String', который называется 'строка # 63', это строка, которую вы говорите. Я попробовал явно называть '.to_s' на' params [: start_at] ', но затем он говорит:« Нет информации о времени в «" '. –

+0

Что-то странное происходит с вашей формой. Из того, что я могу сказать, должно быть заполнение параметра ': start_at' от выбора даты. –

+0

'start_at' - это массив, потому что каждое значение имеет значение' starts_at (1i) ',' starts_at (2i) ',' starts_at (3i) ', так как' date_field' создает 3 различных выбора. Может быть, это причина? Я должен попробовать присоединиться к значениям ... –

Смежные вопросы