неопределенный метод с вложенными атрибутами - PullRequest
0 голосов
/ 22 октября 2018

У меня есть пробная модель, которая создает treatment_selection и повторение при создании.

При повторении я пытаюсь сохранить trial_id и treatment_selection_id, которые я пытаюсь сделать с помощью ассоциации: through.

Когда отправляется пробная форма, я получаю следующую ошибку:

undefined method `repetitions' for #<TreatmentSelection:0x007ff76b8c3830>

Пробный контроллер

def create
    @trial = Trial.new(trial_params)
    @trial.treatment_selections.build.repetitions.build
end

private
    def trial_params
        params.require(:trial).permit(:year, :cultivation_id, :region_id, :cooperator_id, :field_id, :property_id, treatment_selections_attributes: [TreatmentSelection.attribute_names.map(&:to_sym).push(:_destroy), repetitions_attributes: [:trial_id, :treatment_selection_id]])
  end

Модели

class Trial < ApplicationRecord
  has_many :treatment_selections, dependent: :destroy

  has_many :repetitions, through: :treatment_selections, source: :treatment

  accepts_nested_attributes_for :repetitions, allow_destroy: true
  accepts_nested_attributes_for :treatment_selections, allow_destroy: true
end

class TreatmentSelection < ApplicationRecord
  belongs_to :trial
  belongs_to :treatment
end

class Repetition < ApplicationRecord
  belongs_to :treatment_selection
end

В модели treatment_selection есть помощник, который пользователь может динамически добавлять. trials_helper

module TrialsHelper
  def link_to_add_row(name, f, association, **args)
    new_object = f.object.send(association).klass.new
    id = new_object.object_id
    fields = f.fields_for(association, new_object, child_index: id) do |builder|
      render(association.to_s.singularize, f: builder)
    end
    link_to(name, '#', class: "add_fields " + args[:class], data: {id: id, fields: fields.gsub("\n", "")})
  end
end

Схема

 create_table "repetitions", force: :cascade do |t|
    t.integer "trial_id"
    t.integer "treatment_selection_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

Журнал

Started POST "/trials" for 127.0.0.1 at 2018-10-22 14:45:57 +1000
Processing by TrialsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"I2QheHAPOuhnv61Ghs0UoVgXcbYvX73AA7+nI/JTvRU4lTRYJbOdCstuTt/i7/4H2dV6wv4Vdt6zcQ7oo1id6w==", "trial"=>{"year(2i)"=>"1", "year(3i)"=>"1", "year(1i)"=>"2018", "region_id"=>"3", "cooperator_id"=>"1", "property_id"=>"1", "field_id"=>"5", "cultivation_id"=>"1", "treatment_selections_attributes"=>{"0"=>{"treatment_id"=>"3", "ambassador"=>"0", "_destroy"=>"false"}, "1"=>{"treatment_id"=>"", "ambassador"=>"0", "_destroy"=>"false"}, "2"=>{"treatment_id"=>"", "ambassador"=>"0", "_destroy"=>"false"}}}, "commit"=>"Submit"}
Completed 500 Internal Server Error in 65ms (ActiveRecord: 11.6ms)


NoMethodError (undefined method `repetitions' for #<TreatmentSelection:0x007ff76b8c3830>):

app/controllers/trials_controller.rb:48:in `block in create'
app/controllers/trials_controller.rb:47:in `times'
app/controllers/trials_controller.rb:47:in `create'

Пробная форма

<%= form_with(model: trial, local: true) do |f| %>
    <%= f.date_select :year, {order: [:year] %>
    ... Other Trial fields...
    <%= f.fields_for :treatment_selections do |builder| %>
        <%= render 'treatment_selection', f: builder %>
    <% end %>

    <%= f.submit 'Submit' %>
<% end %>

Выбор лечения частичный

<%= f.collection_select :treatment_id, Treatment.order('name'), :id, :name %>
  <%= f.check_box :ambassador %>
  <%= f.hidden_field :_destroy, as: :hidden %>
  <%= link_to 'Delete', '#', class: "remove_treatment" %>

Ответы [ 3 ]

0 голосов
/ 22 октября 2018

вы строите объект повторений в модели TreatmentSelection, в которой не указана взаимосвязь между TreatmentSelection и моделью Repetition, вам нужно добавить has_many: repetitions в модель TreatmentSelection, чтобы это работало.

0 голосов
/ 22 октября 2018

Ваши связи не совсем верны.

Чтобы присоединиться к Trial to Repetition, вам нужно настроить ассоциацию в TreatmentSelection, чтобы пройти:

class TreatmentSelection < ApplicationRecord
  belongs_to :trial
  belongs_to :treatment
  has_many :repetitions, dependent: :destroy
end

Это позволяет вам правильно пройтиэта связь:

class Trial < ApplicationRecord
  has_many :treatment_selections, dependent: :destroy
  has_many :repetitions, through: :treatment_selections
end

Вы также неправильно используете опцию source.Используется, когда нужно указать ActiveRecord, какая ассоциация в модели соединения соответствует требуемой модели (когда имена не совпадают).

Вам также следует удалить столбец repetions.trial_id, так как это создает нежелательное дублирование.

Вам также необходимо добавить ассоциации к повторениям, которые возвращаются по цепочке:

class Repetition < ApplicationRecord
  belongs_to :treatment_selection
  has_one :treatment, through: :treatment_selection
  has_one :trial, through: :treatment_selection
end

Вам также следует настроить вложенные атрибуты следующим образом:

class Trial < ApplicationRecord
  # ...
  accepts_nested_attributes_for :treatment_selections, allow_destroy: true
end 

class TreatmentSelection < ApplicationRecord
  # ...
  accepts_nested_attributes_for :repetitions, allow_destroy: true
end

Это очень важно, поскольку атрибуты должны быть вложены в два уровня.

{ 
   trial: {
     treatment_selection_attributes: [
        {
          treatment_id: 1,   
          repetition_attributes: [
            { foo: 'bar' }
          ]
        },
        {
          treatment_id: 1,   
          repetition_attributes: [
            { foo: 'bar' }
          ]
        }
     ]
   }
}

ActiveRecord не понимает, что вложенные атрибуты проходят через другую ассоциацию.

Вы также должны вкладывать вызовы fields_for.

<%= form_with(model: trial, local: true) do |f| %>
  <%= f.fields_for :treatment_selections do |tsf| %>
    <%= tsf.fields_for :repetitions do |rf| %>
    <% end %>
  <% end %>
<% end %>
0 голосов
/ 22 октября 2018

Ваш код в create action @trial.treatment_selections.build вернет объект TreatmentSelection, который не имеет определения для repetitions, как определено в его модели.

Возможно, вы имеете в виду:

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