2013-01-10 1 views
3

Я уверен, что это распространенная проблема, но она меня озадачила.Рельсы: Has_many через, вложенные флажки и проверка присутствия

У меня есть has_many: через стол на модели 'Шаг':

has_many :questions, :through => :question_step 

Это question_step модели присутствия валидаторы на question_id и step_id поля:

validates_presence_of :question_id, :step_id 

И есть флажки, что определить, какие вопросы относятся к тому, какой этап

td= check_box_tag "step[question_ids][]", question.id, @step.question_ids.include?(question.id) 

Теперь это работает просто отлично, за исключением случаев, когда я хочу добавить вопросы на новый шаг. Поскольку step_id пуст, модель question_step не выполняет проверку. Он отлично работает, если я удаляю аргумент validate_presence_of: step_id в модели question_step, но я на самом деле do хочу убедиться, что существует step_id.

Я уверен, что это распространенная проблема. ...Есть предположения?

+0

Изучите [accepts_nested_attributes_for] (http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html#M002132) и его параметр reject_if. Также проверьте [этот рельс] (http://railscasts.com/episodes/196-nested-model-form-part-1) – weltschmerz

+1

Возможно, вам придется добавить inverse_of к вашим моделям – Swards

ответ

1

Вместо проверки идентификаторов шага и вопроса присутствует, вы можете проверить, если есть вопрос и шаг объект:

validates_presence_of :question, :step 

Если это не работает, вам следует рассмотреть возможность отмены проверок на уровень приложения и добавление базы данных, вам просто нужно добавить ненулевое ограничение в столбцы при миграции:

def up 
    change_column question_steps, :question_id, :integer, :null => false 
    change_column question_steps, :step_id,  :integer, :null => false 
end 
0

У меня была очень похожая проблема. Согласно this question, происходит состояние гонки.

В действии создания моего контроллера я решил создать свою основную модель без ассоциаций сначала с использованием параметров, которые исключают параметры ассоциации. А затем обновите модель с помощью параметров ассоциации.

Так что в вашем случае это может быть

def create 
    @step = Step.create(create_params) 
    @step.update_attributes(association_params) unless @step.errors.any? 
    respond_to do |format| 
    if @step.errors.empty? 
     format.html #etc.. 
    else 
     format.html#...etc.. 
    end 
    end 
end 

private 
def create_params 
    perm_params = step_params 
    perm_params.delete :question_ids 
    perm_params 
end 
def association_params 
    params.require(:step).permit(question_ids: []) 
end 
def step_params 
    params.require(:step).permit(:name, :other_attributes, question_ids: []) 
end 

Таким образом, вы не должны двигаться валидаций к вашей БД. Вы по-прежнему будете использовать обычные шаги step_params в своем методе обновления.

Методы params, возможно, были бы немного взломаны, и мне интересно, почему мне нужно идти на все это, чтобы что-то работало просто в rails 3, но теперь это работает для меня.