如何为 rails 中的嵌套形式声明 objects 4
How to declare objects for nested form in rails 4
我已经接近使用 rails 的第 2 周了,我的应用程序结构几乎已经完成(我 think/hope)。我正在为一家慈善机构建立一个员工网站,作为他们工作的一部分,他们收集并擦除计算机(在将它们送到非洲学校之前!)。
我已经将我的应用程序设置为具有员工、计算机和擦除模型/类,并将擦除详细信息的表单嵌套在计算机详细信息的表单中。当我创建一台新计算机时,我可以毫无问题地输入擦除详细信息,如果我编辑现有计算机的擦除详细信息已经有擦除详细信息,它也很好用。但是当我向现有计算机添加擦除详细信息时 而没有擦除详细信息 我收到以下错误:
undefined method `staff=' for nil:NilClass
Extracted source (around line #49):
如何正确设置 computer.wipe.staff = 给当前用户。请注意,要编辑或提交擦除详细信息,用户必须登录。
我的模型如下(忽略不相关的验证等):
class Staff < ActiveRecord::Base
has_many :wipes
before_save { self.staff_email = staff_email.downcase }
validates :staff_name, presence: true, length: { minimum: 5, maximum: 50}
has_secure_password
end
class Computer < ActiveRecord::Base
has_one :wipe, dependent: :destroy
accepts_nested_attributes_for :wipe
end
class Wipe < ActiveRecord::Base
belongs_to :computer#, dependent: destroy
belongs_to :staff
validates :staff_id, presence: true
#validates :computer_id, presence: true
validates :action_taken, presence: true, length: { minimum: 2, maximum: 250 }
end
我的电脑控制器如下:
class ComputersController < ApplicationController
before_action :set_computer, only: [:edit, :update, :show]
before_action :require_user, except: [:new, :create]
layout :new_layout, only: [:new, :update]
def new
@computer = Computer.new
@computer.build_wipe
end
def create
@computer = Computer.new(computer_params)
if logged_in?
@computer.wipe.staff = current_user
end
if @computer.save
flash[:success] = "You're computer's details have been submitted successfully!"
redirect_to computers_path
else
render :new, layout: new_layout
end
end
def edit
unless @computer.wipe
@computer.build_wipe
end
end
def update
@computer.wipe.staff = current_user #This is the line not working, yet seems to work correctly in the create action
if @computer.update(computer_params)
flash[:success] = "The computer's details have been updated successfully!"
redirect_to computer_path(@computer)
else
render :edit
end
end
private
#Whitelisting variables
def computer_params
params.require(:computer).permit(:manufacturer, :computer_type, :specification, :donor, :model_no, :serial_no, :product_key, :turingtrack, :picture, wipe_attributes: [:id, :action_taken, :staff_id])
end
def set_computer
@computer = Computer.find(params[:id])
end
end
我的看法是:
<div class="row">
<div class="well col-md-8 col-md-offset-2">
<%= form_for(@computer, html: { multipart: true }) do |f| %>
<%= f.label :manufacturer %>
<%= f.text_field :manufacturer, :placeholder => "Toshiba" %>
<%= f.label :computer_type, "Computer Type" %>
<%= f.text_field :computer_type, :placeholder => "Laptop"%>
<% if logged_in? %>
<br><strong>Wiping Details:<br><br></strong>
<%= f.fields_for :wipe do |wipe_form| %>
<%= wipe_form.label :action_taken %>
<%= wipe_form.text_field :action_taken %>
<% end %>
<% end %>
<%= f.submit(@computer.new_record? ? "Submit Details" : "Submit Edited Details", class: "btn btn-success") %>
<% end %>
</div>
</div>
此外,目前我没有设置 computer_id
在计算机表单中使用嵌套擦除表单时,它似乎会自动分配它(例如,如果我创建了一个新的 computer/edit 并输入擦除详细信息,该擦除的 computer_id
也是计算机的 created/edited)。这个假设是否正确?我在某处读到无法验证 parent 的外键,但它太简短了,无法真正理解。当我尝试在擦除模型中验证 computer_id
时会抛出错误,因此验证被注释掉了。为什么会这样,这样放着行不行?
谢谢大家
基于错误:
undefined method `staff=' for nil:NilClass.
这表明 @computer.wipe 为零。因此,虽然您的 set_computer 方法根据提供的 ID 正确地找到了一台计算机,但 @computer 没有关联的 擦.
编辑: 这可能与您的 build_wipe 方法中的问题有关,无法正确设置擦除。
我似乎已经解决了我的问题,虽然我不太明白它为什么有效。
我在编辑和更新操作中都构建了一个擦除对象。第一个在表单中创建输入字段,第二个是分配员工时使用的实例。请注意,当我检查控制台以查看是否已创建两个擦除对象时,根据需要只有一个。
def edit
unless @computer.wipe
@computer.build_wipe
end
end
def update
if @computer.wipe
else
@computer.build_wipe
end
@computer.wipe.staff = current_user
if @computer.update(computer_params)
flash[:success] = "The computer's details have been updated successfully!"
redirect_to computer_path(@computer)
else
render :edit
end
end
我已经接近使用 rails 的第 2 周了,我的应用程序结构几乎已经完成(我 think/hope)。我正在为一家慈善机构建立一个员工网站,作为他们工作的一部分,他们收集并擦除计算机(在将它们送到非洲学校之前!)。
我已经将我的应用程序设置为具有员工、计算机和擦除模型/类,并将擦除详细信息的表单嵌套在计算机详细信息的表单中。当我创建一台新计算机时,我可以毫无问题地输入擦除详细信息,如果我编辑现有计算机的擦除详细信息已经有擦除详细信息,它也很好用。但是当我向现有计算机添加擦除详细信息时 而没有擦除详细信息 我收到以下错误:
undefined method `staff=' for nil:NilClass
Extracted source (around line #49):
如何正确设置 computer.wipe.staff = 给当前用户。请注意,要编辑或提交擦除详细信息,用户必须登录。
我的模型如下(忽略不相关的验证等):
class Staff < ActiveRecord::Base
has_many :wipes
before_save { self.staff_email = staff_email.downcase }
validates :staff_name, presence: true, length: { minimum: 5, maximum: 50}
has_secure_password
end
class Computer < ActiveRecord::Base
has_one :wipe, dependent: :destroy
accepts_nested_attributes_for :wipe
end
class Wipe < ActiveRecord::Base
belongs_to :computer#, dependent: destroy
belongs_to :staff
validates :staff_id, presence: true
#validates :computer_id, presence: true
validates :action_taken, presence: true, length: { minimum: 2, maximum: 250 }
end
我的电脑控制器如下:
class ComputersController < ApplicationController
before_action :set_computer, only: [:edit, :update, :show]
before_action :require_user, except: [:new, :create]
layout :new_layout, only: [:new, :update]
def new
@computer = Computer.new
@computer.build_wipe
end
def create
@computer = Computer.new(computer_params)
if logged_in?
@computer.wipe.staff = current_user
end
if @computer.save
flash[:success] = "You're computer's details have been submitted successfully!"
redirect_to computers_path
else
render :new, layout: new_layout
end
end
def edit
unless @computer.wipe
@computer.build_wipe
end
end
def update
@computer.wipe.staff = current_user #This is the line not working, yet seems to work correctly in the create action
if @computer.update(computer_params)
flash[:success] = "The computer's details have been updated successfully!"
redirect_to computer_path(@computer)
else
render :edit
end
end
private
#Whitelisting variables
def computer_params
params.require(:computer).permit(:manufacturer, :computer_type, :specification, :donor, :model_no, :serial_no, :product_key, :turingtrack, :picture, wipe_attributes: [:id, :action_taken, :staff_id])
end
def set_computer
@computer = Computer.find(params[:id])
end
end
我的看法是:
<div class="row">
<div class="well col-md-8 col-md-offset-2">
<%= form_for(@computer, html: { multipart: true }) do |f| %>
<%= f.label :manufacturer %>
<%= f.text_field :manufacturer, :placeholder => "Toshiba" %>
<%= f.label :computer_type, "Computer Type" %>
<%= f.text_field :computer_type, :placeholder => "Laptop"%>
<% if logged_in? %>
<br><strong>Wiping Details:<br><br></strong>
<%= f.fields_for :wipe do |wipe_form| %>
<%= wipe_form.label :action_taken %>
<%= wipe_form.text_field :action_taken %>
<% end %>
<% end %>
<%= f.submit(@computer.new_record? ? "Submit Details" : "Submit Edited Details", class: "btn btn-success") %>
<% end %>
</div>
</div>
此外,目前我没有设置 computer_id
在计算机表单中使用嵌套擦除表单时,它似乎会自动分配它(例如,如果我创建了一个新的 computer/edit 并输入擦除详细信息,该擦除的 computer_id
也是计算机的 created/edited)。这个假设是否正确?我在某处读到无法验证 parent 的外键,但它太简短了,无法真正理解。当我尝试在擦除模型中验证 computer_id
时会抛出错误,因此验证被注释掉了。为什么会这样,这样放着行不行?
谢谢大家
基于错误:
undefined method `staff=' for nil:NilClass.
这表明 @computer.wipe 为零。因此,虽然您的 set_computer 方法根据提供的 ID 正确地找到了一台计算机,但 @computer 没有关联的 擦.
编辑: 这可能与您的 build_wipe 方法中的问题有关,无法正确设置擦除。
我似乎已经解决了我的问题,虽然我不太明白它为什么有效。 我在编辑和更新操作中都构建了一个擦除对象。第一个在表单中创建输入字段,第二个是分配员工时使用的实例。请注意,当我检查控制台以查看是否已创建两个擦除对象时,根据需要只有一个。
def edit
unless @computer.wipe
@computer.build_wipe
end
end
def update
if @computer.wipe
else
@computer.build_wipe
end
@computer.wipe.staff = current_user
if @computer.update(computer_params)
flash[:success] = "The computer's details have been updated successfully!"
redirect_to computer_path(@computer)
else
render :edit
end
end