Rails 4 Обновить вложенные атрибуты

Обновление вложенных атрибутов append вместо обновления внутри имеет много отношений Я пытаюсь использовать Rails 4 Update_attributes

Class Person <ActiveRecord::Base
 has_many :pets
 accepts_nested_attributes_for :pets
end

Class Pet < ActiveRecord::Base
 belongs_to :person
end

В моем контроллере я возвращаю параметры как {id: 23, house_no: '22A', pets: [{name: 'jeffy', type: 'dog'}, {name: 'sharky', type: 'fish'}]}

и мой метод обновления

def update
  @Person = Person.find(params[:id])
  if @Person.update(person_params)
    @Person.save
    render 'persons/create', status 200
  else
    render 'persons/create', status 400
  end
end

private
def person_params
  person_params = params.permit(:house_no)
  person_params.merge! ({pets_attributes: params[:pets]}) if params[:pets].present?
  person_params
end

Теперь, когда я его обновляю и если у человека уже есть домашнее животное затем новые домашние животные добавляются вместо того, чтобы обновляться например, если лицо с идентификатором 1 имеет 1 домашнее животное с именем "Тигр", и я обновляю этого человека с двумя домашними животными по имени "Шаша" и "Монти", тогда в записи человека есть 3 домашних животных (Тигр, Шаша и Монти) вместо того, чтобы обновлять его до 2 (Шаша и Монти).

Ответы

Ответ 1

см. руководство:

http://api.rubyonrails.org/v4.0.1/classes/ActiveRecord/NestedAttributes/ClassMethods.html

вам нужно отправить свои атрибуты, например pets_attributes:[{name:'jeffy', type:'dog'}, {name:'sharky', type:'fish'}]

и он должен работать нормально.

Пожалуйста, прочитайте

Теперь вы можете установить или обновить атрибуты на связанных сообщениях через хэш хэша атрибута для члена: включить ключ: posts_attributes с массивом хэшей почтовых атрибутов в качестве значения. Для каждого хеша, у которого нет ключа id a новая запись будет создана, если хеш также не содержит ключ _destroy, который оценивает значение true.

Ответ 2

Обновите модель Person, как показано ниже:

class Person < ActiveRecord::Base  ## NOTE: class (c lowercase) and NOT Class
 has_many :pets
 accepts_nested_attributes_for :pets, allow_destroy: true  ## Added allow_destroy
end

Чтобы уничтожить связанную модель, то есть Pet через хэш атрибутов, вы должны сначала включить ее, используя параметр :allow_destroy.

Затем, с вашего вида, вам необходимо передать атрибут _destroy для домашних животных, которые вы хотите удалить.

Так как вы не использовали общий код вида. Ниже приведен пример того, как это должно быть реализовано в вашем представлении. Измените его в соответствии с вашими требованиями:

<%= form_for @person do |f| %>
  <%## .. %>  
  <%= f.fields_for :pets do |builder| %>
    <%## .. %>    
    <%= builder.check_box :_destroy %>
    <%= builder.label :_destroy, "Remove Pet" %>
  <% end %>
<% end %>

В приведенном выше коде вам нужно добавить checkbox и label для передачи значения _destroy.

После этого обновите метод person_params в вашем контроллере, как показано ниже:

def person_params
  params.require(:person).permit(:house_no, pets_attributes: [:id, :name, :type, :person_id, :_destroy])
end 

ПРИМЕЧАНИЕ.

Вы не должны определять instance variables с именем с заглавной буквы. Заглавные имена используются для объявления Constants в Ruby.

def update
  @person = Person.find(params[:id])
  if @person.update(person_params)
    @person.save
    render 'persons/create', status 200
  else
    render 'persons/create', status 400
  end
end  

Ответ 3

Можете ли вы попробовать добавить атрибут :id в :pets_attributes массив в person_params?

Вам нужно разрешить атрибут id.

Ответ 4

Вероятно, 1. вы хотите назначить домашних животных отдельно,

@Person.pets = Pets.find(params[:pets])

Или 2. очистите домашних животных до сохранения человека.

@Person.pets.destroy

Ответ 5

Попробуйте изменить person_params как

def person_params
  person_params = params.require(:person).permit(:house_no ,pets_attributes: [:name,:type])
end

И удалите @person.save из метода обновления. Это вам не нужно. И также используйте ! для update

def update
  @Person = Person.find(params[:id])
  if @Person.update!(person_params)
    render 'persons/create', status 200
  else
    render 'persons/create', status 400
  end
end

Обновление

А также, поскольку я вижу, что в Pet нет ассоциации belongs_to :person, добавьте ее в модель

Class Pet < ActiveRecord::Base

belongs_to :person

end

И теперь разрешите атрибут person_id, добавив его в params

def person_params
  person_params = params.require(:person).permit(:house_no,pets_attributes: [:name,:type,:person_id])
end

Ответ 6

Вам нужно изменить параметры с помощью pets_attributes

Также необходимо добавить: id paramter в объекты домашнего животного.