Запускаем проверки в действии обновления CRUD с несколькими моделями перед обновлением базы данных

#ruby-on-rails #ruby-on-rails-4

#ruby-on-rails #ruby-on-rails-4

Вопрос:

У меня есть 2 модели — Dog и Bone. У Dog есть одна кость, кость принадлежит_ собаке. У собаки есть имя, у кости есть цвет и dogs_id.

В форме редактирования пользователь может изменить имя собаки и цвет кости. Мне нужно выполнить проверки dog’s и bone перед обновлением базы данных. Вот мой код:

 def update
  @dog = Dog.find(params[:id])
  @bone = @dog.bone

  if @dog.update(dog_params) amp;amp; @bone.update(bone_params)
    redirect_to root_path
  else
    render :edit
  end
end
  

В этом случае, если dog допустим, а bone нет, он сохранит только прогресс dog в db, а затем снова отобразит редактирование. Но я не хочу менять db до того, как все они станут действительными.

Комментарии:

1. Можете ли вы показать нам свои dog_params и bone_params ?

2. @Pavan dog_params и bone_params — это просто хэши, такие как {name: ‘Sam’} и {color: ‘red’}

3. Возможно, вы можете использовать accepets_nested_attributes_for :bone и make dog_params as params.require(:dog).permit(:name,bone_attribues: [:id,:color,:dog_id]) и so, вызывая just if @dog.update(dog_params) , чтобы убедиться, что параметры обновлены, если они действительны.

Ответ №1:

Более осуществимый способ — использовать accepts_nested_attributes_for.

 #app/models/dog.rb
Class Dog < ActiveRecord::Base

has_one :bone
accepts_nested_attributes_for :bone
#your validations

end
  

И update метод как

 def update
  @dog = Dog.find(params[:id])

  if @dog.update(dog_params)
    redirect_to root_path
  else
    render :edit
  end
end 

private

def dog_params
  params.require(:dog).permit(:name,bone_attribues: [:id,:color,:dog_id])
end
  

Это гарантирует, что attributes(both parent and child) будут обновлены, если они действительны.

Ответ №2:

Просто вызовите valid? для каждой модели

 def update
  @dog = Dog.find(params[:id])
  @bone = @dog.bone

  @dog.assign_attributes dog_params
  @bone.assign_attributes bone_params

  if @dog.valid? amp;amp; @bone.valid?
    @dog.save
    @bone.save
    redirect_to root_path
  else
    render :edit
  end
end
  

Комментарии:

1. Спасибо, не знал о #assign_attributes.