2015-05-11 3 views
1

Я хочу сохранить две модели в одном действии контроллера или не сохранить их и вернуться с ошибками проверки.Сохраните обе модели или нет в контроллере

Есть ли лучший способ, чем это?

def update 
    @job = Job.find(params[:id]) 
    @location = @job.location 

    @job.assign_attributes(job_params) 
    @location.assign_attributes(location_params) 
    @job.save unless @job.valid? # gets validation errors 
    @location.save unless @location.valid? # gets validation errors 

    if @job.valid? && @location.valid? 
     @job.save 
     @location.save 
     flash[:success] = "Changes saved." 
     redirect_to edit_job_path(@job) 
    else 
     render 'edit' 
    end 
    end 

Новая версия:

def update 
    @job = Job.find(params[:id]) 
    @location = @job.location 

    begin 
    Job.transaction do 
     @job.assign_attributes(job_params) 
     @job.save!(job_params) 
     @location.assign_attributes(location_params) 
     @location.save!(location_params) 
    end 
    flash[:success] = "Changes saved." 
    redirect_to edit_job_path(@job) 
    rescue ActiveRecord::RecordInvalid => invalid 
    render 'edit' 
    end 
end 
+0

Почему вы звоните 'save' дважды для каждого экземпляра? – AbM

+0

Если вы не хотите использовать 'nested_attributes', как предлагаемые ответы (что я рекомендую), вы можете использовать транзакцию ActiveRecord # (http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html) и используйте 'save!' внутри этого блока, отмените ошибку «Record not valid» и сделайте правильный просмотр. – MrYoshiji

+0

Спасибо MrYoshiji! Причиной принятия accepts_nested_attributes_for является то, что job принадлежит_определению. –

ответ

1

Посмотрите Active Record Nested Attributes. Используя вложенные атрибуты, вы можете сохранить связанные атрибуты записи через parent.If родительская запись не удалась, связанные записи не будут сохранены.!

+0

Спасибо! Причиной принятия accepts_nested_attributes_for является то, что задание принадлежит определенному местоположению. Я не думаю, что вы можете accepts_nested_attributes_for родителей –

1

первое, что вы хотите сделать, это удалить эти две строки

@job.save unless @job.valid? # gets validation errors 
@location.save unless @location.valid? # gets validation errors 

и только держать #save в, если заявление. потому что, если один из них действителен, а другой - нет, вы все равно сохраните действительный номер в db.
Чтобы ответить на ваш второй вопрос, есть ли лучший способ сделать это? Сначала краснеть, это выглядит как работа для #accepts_nested_attributes_for. Тем не менее, accepts_nested_attributes_for несколько печально известен тем, что ему трудно работать (на самом деле он просто берет плату за проезд), и то, что вы сейчас делаете, должно заставить вас туда, куда вы пытаетесь пойти, так что это зависит от вас.

+0

Спасибо, что заметили это. Причиной принятия accepts_nested_attributes_for является то, что job принадлежит_определению. –

1

Вы можете использовать validates_associated рельсы помощника:

class Model < ActiveRecord::Base 
    has_one :location 
    validates_associated :location 
end 

Тогда:

if @job.save 
    #blah 
else 
    #blah 
end 

достаточно, не возиться с ActiveRecord # Nested_attributes. Это быстрее, но менее чище. Твой выбор.

Ссылка:

http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_associated