Создать новый объект для каждого элемента массива - PullRequest
0 голосов
/ 03 ноября 2019

Ошибка:

неопределенный метод

'sub_agriculture_sub_agriculture_sub_agriculture_sub_agriculture_sub_agriculture_sub_agricultures_path' для # <#: 0x00007f5ec01b4b50 * 100 </p> 100 *1006* 100 * 100 * 600 * 100 * 100 * 600 * 1001011 *

Я строю систему оценок студентов и в настоящее время испытываю проблемы с ресурсами (я думаю) Отношения определяются следующим образом:

Scorecard.rb
..
 has_one :sub_agriculture

sub_agriculture.rb
..
 belongs_to :scorecard

routes.rb
..
 resources :scorecards
 resources :sub_agricultures

Обычно в sub_agricultures_controller.rb можно использовать;

def new     
  @sub_agriculture =  SubAgriculture.new
end

... потому что это приводит к

#<SubAgriculture id: nil, score: nil, created_at: nil, updated_at: nil, scorecard_id: nil> 

Мне нужно создать несколько из них для их соответствующих карт показателей в одной форме ввода.

Однако выберите только scorecardsиметь sub_agriculture прикрепленный к ним. (не все слушатели берут тему сельское хозяйство). Поэтому я запустил запрос на Scorecard, где я pluck(:id), потому что я не видел его эффективным, используя все отношения active_record. Затем я получаю массив идентификаторов вроде этого;[1, 2, 3, 4, 5, 6]. Это коллекция scorecard_ids из запроса.

Так для каждого Id;Мне нужно создать оценку sub_agriculture для него. Для этого случая;шесть новых экземпляров sub_agriculture. Для этого я сделал это на sub_agricultures_controller.rb

def new    
    sc = Scorecard.scorecard_with_agriculture
  @sub_agriculture =  sc.map { |s|SubAgriculture.new(:scorecard_id => s) }

end

Это выплевывает этот массив;

=>[#<SubAgriculture id: nil, score: nil, created_at: nil, updated_at: nil, scorecard_id: 1>, #<SubAgriculture id: nil, score: nil, created_at: nil
, updated_at: nil, scorecard_id: 2>, #<SubAgriculture id: nil, score: nil, created_at: nil, updated_at: nil, scorecard_id: 3>, #<SubAgriculture id:
 nil, score: nil, created_at: nil, updated_at: nil, scorecard_id: 4>, #<SubAgriculture id: nil, score: nil, created_at: nil, updated_at: nil, score
card_id: 5>, #<SubAgriculture id: nil, score: nil, created_at: nil, updated_at: nil, scorecard_id: 6>]

Что я и имел в виду;действие /sub_agriculture/new поражает меня этой ошибкой

NoMethodError в субагрикулярных культурах # new

неопределенный метод `sub_agriculture_sub_agriculture_sub_agriculture_sub_agriculture_sub_agriculture_sub_agriculture_sub_agricultures * * 10 * 050 * 0505_5f5_5b5_p_0455_5_4_0455_1* С выделением этой конкретной строки в новой форме

<%= form_with(model: sub_agriculture, local: true) do |form| %>

Мне нужно создать шесть sub_agricultures в одной форме. Куда я иду не так?

Ответы [ 3 ]

1 голос
/ 03 ноября 2019

Я не думаю, что вам следует использовать «новое» действие для этого, поскольку вы выходите из соглашений и рельсы исключают некоторые вещи, которые могут произойти. Я бы создал два новых действия: bulk_new и bulk_create

Добавьте маршруты для этих действий:

resources :sub_agricultures do
  collection do
    get :bulk_new
    post :bulk_create
  end
end

Новое, когда вы передаете модель помощнику form_with, он пытаетсявывести url из массива, объединяющего имена ресурсов, и поэтому вы видите этот странный именованный маршрут.

То, что вы делаете, не соответствует соглашениям, поэтому вам, возможно, придется немного побороться с входными данными, так как rails выигралВы не сможете сгенерировать правильные имена с этим массивом, поэтому вам придется сгенерировать префикс входного имени самостоятельно, что-то вроде:

= form_tag bulk_create_sub_categories_path do |form|
  - sub_agricultures.each do |sub_ag|
    - input_name_prefix = "sub_agricultures[#{sub_ag.scorecard_id}]"
    div
      = hidden_field "#{input_name_prefix}[scorecard_id]", sub_ag.scorecard_id
      = label_tag "#{input_name_prefix}[score]", "Score for #{sub_ag.scorecard_id}"
      = number_field_tag "#{input_name_prefix}[score]", sub_ag.score
      # add some errors feedback too

Теперь эта форма должна представить хэш params, подобный этому:

{
  sub_agricultures: [
    1: {scorecard_id: 1, score: XX},
    2: {scorecard_id: 2, score: YY},
    etc...
  ]
}

Итак, в ваших действиях bulk_create вы должны сделать что-то вроде:

def bulk_create
  @sub_agricultures: []

  # loop through the sub_agricultures params array
  params[:sub_agricultures].each do |_, sub_ag_data|
    sub_ag = SubAgriculture.new(scorecard_id: sub_ag_data[:scorecard_id], score: sub_ag_data[:score])
    @sub_agricultures << sub_ag
  end

  # now I guess you want to validate all of them:
  if @sub_agricultures.all?(&:valid?)
    @sub_agricultures.each(&:save)
    flash[:notice] = "sub agricultures created"
    redirect_to somewhere_path
  else
    flash.now[:error] = "sub agricultures have errors"
    render action: :bulk_new
  end
end
0 голосов
/ 03 ноября 2019

Ваше отношение к модели может быть улучшено. Одна оценочная карта (табель успеваемости) будет содержать много предметов. Так что лучше перепроектируйте отношения между этими двумя классами. enter image description here

0 голосов
/ 03 ноября 2019

form_with не предназначен для создания нескольких записей одновременно. Ключевое слово модели передается помощникам по полифирическим URL-адресам, поэтому при передаче массива моделей вы получаете вложенный маршрут:

polymorphic_url([blog, post]) # => "http://example.com/blogs/1/posts/1"

Rails разрешает это до blog_posts_path, вызывая model_name.param_key в экземпляре модели.

Так как у вас есть целая тонна записей, вы получаете этот маршрут насмешек sub_agriculture_sub_agriculture_sub_agriculture_sub_agriculture_sub_agriculture_sub_agricultures_path.

Даже если это сработало, я сомневаюсь, что конструктор форм будет работать, так как он создан для использования с единичными экземплярами записей,Не массив.

Если вы хотите использовать вложенные атрибуты, вам нужна модель, которая оборачивает вложенные атрибуты. Поэтому вам нужно либо переосмыслить моделирование вашего домена (вы, вероятно, можете сделать это намного лучше), либо использовать что-то вроде <%= form_with(url: '/somepath') %> и вручную обрабатывать привязку параметров и все такое.

Обработка массовых вставок таким способом на самом деле довольнонемного более сложным, чем просто цикл по массиву. Вы должны убедиться, что все записи действительны и сохранены (например, транзакции), и обрабатывать передачу записей обратно в форму, если это не так. Я бы действительно постарался избежать этого, если это возможно. Существует причина, по которой он не является частью соглашений Rails.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...