Редактировать с отношением own_to - PullRequest
0 голосов
/ 15 октября 2019

Issue

Я сталкиваюсь с проблемой при редактировании формы с отношением own_to (extra_guest assign_to age_table).

Я могу создать новый extra_guest и назначить его для age_table, но не могу заставить работать редактирование / обновление, поскольку моя функция обновления возвращает falseClass .--> @extra_guest.update(extra_guest_params).errors.full_messages возвращает undefined method `errors' for false:FalseClass

код

модели

class ExtraGuest < ApplicationRecord
  belongs_to :age_table
  validates :age_table, presence: true
end

class AgeTable < ApplicationRecord
  belongs_to :park
  has_many :extra_guests, dependent: :destroy
  validates :name, :age_from, :age_to, presence: true
  validates_associated :extra_guests
end

class Attraction < ApplicationRecord
  belongs_to :park

  has_many :extra_guests, dependent: :destroy
  accepts_nested_attributes_for :extra_guests, allow_destroy: true

  validates :name, presence: true
end

class Park < ApplicationRecord
  has_many :attractions, dependent: :destroy
  has_many :age_tables, dependent: :destroy
  validates :name, :currency, presence: true
end

extra_ghest_controller

def edit
    @extra_guest = ExtraGuest.find(params[:id])
    @age_table = @extra_guest.age_table
    @age_table_list = AgeTable.where(park: @attraction.park)
  end

  def update
    @extra_guest = @attraction.extra_guests.find(params[:id])
    @age_table = AgeTable.find(params[:age_table])
    authorize @extra_guest
    if @extra_guest = @extra_guest.update(extra_guest_params)
      redirect_to root_path
    else
      @attraction = Attraction.find(params[:attraction_id])
      @extra_guest = ExtraGuest.find(params[:id])
      @age_table_list = @attraction.park.age_tables
      render 'edit'
    end
  end

private
  def extra_guest_params
    params.require(:extra_guest).permit(:name, :age_table_id,
      extra_guest_prices_attributes: [:id, :name, :price_type, :start_date, :end_date, :price, :duration, :duration_min, :duration_max, :backend_only, :weekend_extra, :_destroy])
  end

просмотры / дополнительные_гости / форма

<%= simple_form_for [@attraction, @extra_guest] do |f|%>
     <%= f.input :age_table, :as => :select, :selected => @age_table.id, :collection => @age_table_list.map {|u| [u.name, u.id]}, :include_blank => false %>
<% f.button :submit %>

Сообщение об ошибке + params


Couldn't find AgeTable without an ID

{"utf8"=>"✓",
 "_method"=>"patch",
 "authenticity_token"=>"l8HMnVIRybZg==",
 "extra_guest"=>
  {"age_table"=>"104",
   "extra_guest_prices_attributes"=>
    {"0"=>{"price"=>"1.0", "weekend_extra"=>"", "start_date"=>"2019-10-15", "end_date"=>"20-09-2019", "duration"=>"", "duration_min"=>"", "duration_max"=>"", "_destroy"=>"false", "id"=>"42"},
     "1"=>{"price"=>"1.0", "weekend_extra"=>"", "start_date"=>"2019-10-15", "end_date"=>"2019-10-16", "duration"=>"", "duration_min"=>"", "duration_max"=>"", "_destroy"=>"false", "id"=>"43"}}},
 "commit"=>"Save new option",
 "attraction_id"=>"185",
 "id"=>"55"}

Ответы [ 2 ]

1 голос
/ 15 октября 2019

Прежде всего, вы говорите, что у вас есть ошибка с этим кодом @extra_guest.update(extra_guest_params).errors.full_messages, но в показанном вами коде эта строка отсутствует.

Теперь метод update возвращает false, если он не работает https://apidock.com/rails/ActiveRecord/Persistence/update

Эта строка:

@extra_guest = @extra_guest.update(extra_guest_params)

установит для @extra_guest значение false, если произойдет сбой, вам не нужно устанавливать @extra_guest, просто используйте if @extra_guest.update(extra_guest_params)

Используя строку кода, которую вы называете, но не в коде, который вы показали, @extra_guest.update(extra_guest_params).errors.full_messages, если есть ошибки, то @extra_guest.update(extra_guest_params) будет ложным, поэтому метод .errors не найден.

вам придетсяразделите его на две строки:

@extra_guest.update(extra_guest_params) # after this, @extra_guest will have the errors hash set
@extra_guest.errors.full_messages # call it on the object and not on the result value from the update method

РЕДАКТИРОВАТЬ: вы разрешаете age_table_id, но параметр равен age_table, зафиксируйте имя параметра как age_table_id тоже

0 голосов
/ 15 октября 2019

Мне кажется, что вы пытались использовать @attraction перед тем, как определить его. Вы можете исправить это, переместив свое определение @attraction дальше в методе, но я бы переместил его в его собственный метод следующим образом:

private

def attraction
   @attraction ||= Attraction.find(params[:attraction_id])
end 

Затем вы используете имя метода, которое теперь определено длявесь контроллер и вызывается, когда вы его используете (в отличие от переменной экземпляра, которая будет просто 'nil', если вы вызываете его, не определяя его). || = позволяет методу возвращать существующее значение переменной экземпляра, если оно определено, вместо выполнения запроса при каждом вызове метода. Поэтому первая строка вашего действия по обновлению будет

@extra_guest = attraction.extra_guests.find(params[:id])

Я бы сделал нечто подобное для других переменных экземпляра, которые у вас есть (@extra_guest, @age_table и @age_table_list должны быть определеныв приватные методы отдельно). Между прочим, использование множества переменных экземпляра для одного контроллера (у вас их 4 в этом контроллере, что довольно много) считается небольшим запахом кода, но вы должны сначала создать что-то, что работает, а затем выполнить рефакторинг. Ссылка на потом: https://thoughtbot.com/blog/sandi-metz-rules-for-developers

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