簡體   English   中英

使用 belongs_to 關系進行編輯

[英]Edit with a belongs_to relationship

問題

我在編輯具有belongs_to 關系(extra_guest belongs_to age_table)的表單時遇到問題。

我能夠創建一個新的 extra_guest 並將其分配給一個 age_table,但是我無法讓編輯/更新工作,因為我的更新 function 返回一個 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_guests_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 %>

錯誤信息 + 參數


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"}

在我看來,您在定義 @attraction 之前嘗試使用它。 您可以通過在方法中將@attraction 的定義進一步向上移動來解決此問題,但我會將其移動到它自己的方法中,如下所示:

private

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

然后您使用方法名稱,該名稱現在為整個 controller 定義並在您使用它時調用(而不是一個實例變量,如果您在沒有定義它的情況下調用它,它將只是“nil”)。 ||= 允許該方法返回已定義的實例變量的現有值,而不是每次調用該方法時都運行查詢。 所以你更新操作的第一行是

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

我會為那里的其他實例變量做類似的事情(@extra_guest、@age_table 和@age_table_list 應該分別在私有方法中定義)。 順便說一句,為單個 controller 使用大量實例變量(在這個 controller 中有 4 個,這是很多)被認為有點代碼味道,但你應該先做一些工作然后重構的東西。 供以后參考: https://thoughtbot.com/blog/sandi-metz-rules-for-developers

首先,您說此代碼有錯誤@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)將為 false,因此沒有.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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM