简体   繁体   English

使用 belongs_to 关系进行编辑

[英]Edit with a belongs_to relationship

Issue问题

I'm encountering a problem when editing a form with a belongs_to relationship (extra_guest belongs_to age_table).我在编辑具有belongs_to 关系(extra_guest belongs_to age_table)的表单时遇到问题。

I am able to create a new extra_guest and assign it to an age_table, but I cannot get the edit/update to work as my update function returns a falseClass.--> @extra_guest.update(extra_guest_params).errors.full_messages returns undefined method `errors' for false:FalseClass我能够创建一个新的 extra_guest 并将其分配给一个 age_table,但是我无法让编辑/更新工作,因为我的更新 function 返回一个 falseClass。--> @extra_guest.update(extra_guest_params).errors.full_messages返回undefined method `errors' for false:FalseClass

Code代码

models楷模

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

views/extra_guests/form意见/额外的客人/表格

<%= 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 %>

Error message + 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"}

It looks to me like you tried to use @attraction before defining it.在我看来,您在定义 @attraction 之前尝试使用它。 You could fix this by moving your definition of @attraction further up in the method, but I would move it into its own method like so:您可以通过在方法中将@attraction 的定义进一步向上移动来解决此问题,但我会将其移动到它自己的方法中,如下所示:

private

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

Then you use the method name, which is now defined for the whole controller and invoked when you use it (as opposed to an instance variable which will just be 'nil' if you invoke it without defining it).然后您使用方法名称,该名称现在为整个 controller 定义并在您使用它时调用(而不是一个实例变量,如果您在没有定义它的情况下调用它,它将只是“nil”)。 The ||= allows the method to return the existing value of the instance variable if it is defined, rather than running the query every time the method is called. ||= 允许该方法返回已定义的实例变量的现有值,而不是每次调用该方法时都运行查询。 So first line of your update action would be所以你更新操作的第一行是

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

I would do something similar for the other instance variables you have there (@extra_guest, @age_table, and @age_table_list should be defined in private methods separately).我会为那里的其他实例变量做类似的事情(@extra_guest、@age_table 和@age_table_list 应该分别在私有方法中定义)。 Incidentally, using a lot of instance variables for a single controller (you have 4 in this controller, which is a lot) is considered a bit of a code smell, but you should make something that works first and then refactor.顺便说一句,为单个 controller 使用大量实例变量(在这个 controller 中有 4 个,这是很多)被认为有点代码味道,但你应该先做一些工作然后重构的东西。 Reference for later: https://thoughtbot.com/blog/sandi-metz-rules-for-developers供以后参考: https://thoughtbot.com/blog/sandi-metz-rules-for-developers

First of all, you say you have an error with this code @extra_guest.update(extra_guest_params).errors.full_messages but the code you show does not have that line.首先,您说此代码有错误@extra_guest.update(extra_guest_params).errors.full_messages但您显示的代码没有该行。

Now, the update method returns false if it fails https://apidock.com/rails/ActiveRecord/Persistence/update现在,如果更新方法失败,则update方法返回 false https://apidock.com/rails/ActiveRecord/Persistence/update

This line:这一行:

@extra_guest = @extra_guest.update(extra_guest_params)

will set @extra_guest to false if it fails, you don't need to set @extra_guest, just use if @extra_guest.update(extra_guest_params)如果失败,会将@extra_guest 设置为false,您不需要设置@extra_guest,只需使用if @extra_guest.update(extra_guest_params)

Using the line of code you name but it's not on the code you showed, @extra_guest.update(extra_guest_params).errors.full_messages , if there are errors then @extra_guest.update(extra_guest_params) will be false, so no .errors method is found.使用您命名但不在您显示的代码上的代码行@extra_guest.update(extra_guest_params).errors.full_messages ,如果有错误,则@extra_guest.update(extra_guest_params)将为 false,因此没有.errors方法成立。

you have to split it in two lines:你必须把它分成两行:

@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

EDIT: you are permitting age_table_id but the parameter is age_table , fix the name of the parameter to be age_table_id too编辑:您允许age_table_id但参数是age_table ,将参数的名称也固定为age_table_id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM