#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
и makedog_params
asparams.require(:dog).permit(:name,bone_attribues: [:id,:color,:dog_id])
и so, вызывая justif @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.