2012-05-15 4 views
1

Я работаю над приложением, которое обрабатывает временные карточки сотрудников, и я пытаюсь создать форму, которая позволяет сотрудникам редактировать все свои удары в заданном блоке время. Я использовал this RailsCast в качестве основы для формы, и был в состоянии получить вещи и работает без проблем:Rails 3 - Проверка нескольких экземпляров модели друг против друга

class BlocksController < ApplicationController 

def update 
    @block = Block.find_by_id(params[:id]) 
    @punches = @block.punches 

    keys = params[:punches].keys 
    values = keys.map { |k| params[:punches][k] } 
    @punches = Punch.update(keys, values).reject { |p| p.errors.empty? } 
    if @punches.empty? 
     flash[:notice] = "Punches updated" 
     redirect_to employee_timecard_path(current_user, @block.timecard) 
    else 
     render :action => "edit" 
    end 
    end 

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

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

Единственный другой подход, о котором я мог думать, состоял в том, чтобы пропустить params[:punches], отправляемый методу обновления в контроллере, но это, похоже, противоречит соглашению «толстая модель, тощий контроллер».

Есть ли способ, которым я могу иметь свой торт и съесть его тоже? Любые предложения будут высоко ценится.

+0

Я все еще думаю, что вы как бы застреваете в пуансонах в блочном контроллере. Контроллерам должно быть позволено расти, если это уместно. В вашем случае я думаю, что это так. Единственное, что я мог подумать об уменьшении кода контроллера, было неэффективным, без необходимости называть уровень ActiveModel просто для того, чтобы держать контроллер тонким, не похоже на хороший компромисс, вроде как курить сигареты, чтобы оставаться тонким! – RadBrad

+0

Не могли бы вы использовать фильтр после или вокруг? Самое худшее, что вы могли бы сделать, это сохранить все в базе данных, проверить его после фильтра, а затем как-то его отменить. Я не очень хорошо разбираюсь в фильтрах, но из того, что я собираю, вы можете проверить обновления как группу до их сохранения и прервать сохранение, если ваши проверки не удались. См. Http://guides.rubyonrails.org/action_controller_overview.html # filters –

+0

Насколько я знаю, вы можете настроить метод класса для Punches, который проверяет весь набор (или некоторое подмножество подмножества) записей (возможно, возвращает список идентификаторов для записей, которые не работают, например). –

ответ

0

я борюсь с подобной проблемой:

  1. Графики имеют начальную и конечную дату
  2. Расписания не должны пересекаться друг с другом

Вот что я пришел к выводу:

Там два вида действия происходит здесь:

  1. Действительность отдельных моделей (например, существует дата начала?)
  2. Действительности коллекции моделей (например, делать какие-либо пары случаев пересекаются?)

Я чувствую, как только первый тип на самом деле ответственность отдельных моделей. Но второй тип тоже не является обязанностью контроллера.

В случае OP я не уверен, было бы лучше определить валидатор в классе Punch или создать новый объект с ответственностью за проверку всего списка ударов, но так или иначе быть каким-то объектом, который знает всю коллекцию и может решить, действительно ли это или нет.

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