新手问题 [已解决] 想做一个保存前的检查,导致 save 失败,求指点,谢谢!

thanatos · 2015年07月17日 · 最后由 thanatos 回复于 2015年07月21日 · 2815 次阅读

创建了一个 model,对应我现有的硬件资产,如下

create_table "hardwares", force: :cascade do |t|
    t.string   "AssetNum",        null: false
    t.integer  "CPU",             null: false
    t.integer  "Disk",            null: false
    t.integer  "Mem",             null: false
    t.date     "BuyingTime",      null: false
    t.date     "DeployingTime",   null: false
    t.string   "Adapter1IP"
    t.string   "Adapter2IP"
    t.string   "Adapter3IP"
    t.string   "Adapter4IP"
    t.string   "Adapter5IP"
    t.string   "Position",        null: false
    t.string   "ServerType",      null: false
    t.string   "ServerModel",     null: false
    t.boolean  "PCorNot",         null: false
    t.string   "ServiceNum"
    t.string   "QuickServiceNum"
    t.boolean  "Idle"
    t.datetime "created_at",      null: false
    t.datetime "updated_at",      null: false
  end

然后做了个 controller 和对应的新建表单,用来保存数据

class HardwaresController < ApplicationController

  def show
    @hardware = Hardware.find(params[:id])
  end

  def new
  end

  def create
#   render plain: params[:hardware].inspect
    @hardware = Hardware.new(hardware_params)
    @hardware.Adapter1IP=''
    @hardware.Adapter2IP=''
    @hardware.Adapter3IP=''
    @hardware.Adapter4IP=''
    @hardware.Adapter5IP=''
    @hardware.save!
    redirect_to @hardware
  end

  private
    def hardware_params
      params.require(:hardware).permit(:AssetNum, :CPU, :Disk,:Mem,:BuyingTime,:DeployingTime,:Position,:ServerType,:ServerModel,:PCorNot, :ServiceNum, :QuickServiceNum, :Idle)
    end
end

我有一个美好的想法:无论在新建还是以后修改 hardware 记录的时候,保存前都检查一下五块网卡是不是都分配了 IP 地址,如果都没有,那就在这条记录的 Idle 上标注它是空闲,于是有了下面的代码:

class Hardware < ActiveRecord::Base
  attr_accessor :Idle, :Adapter1IP, :Adapter2IP, :Adapter3IP, :Adapter4IP, :Adapter5IP
  before_save { self.idle? }
  validates :AssetNum, presence: true
  validates :CPU, presence: true
  validates :Disk, presence: true
  validates :Mem, presence: true
  validates :BuyingTime, presence: true
  validates :DeployingTime, presence: true
  validates :Position, presence: true
  validates :ServerType, presence: true
  validates :ServerModel, presence: true
  validates :PCorNot, presence: true

  def idle?
    if ( self.Adapter1IP.empty? || self.Adapter2IP.nil? || self.Adapter3IP.nil? || self.Adapter4IP.nil? || self.Adapter5IP.nil? )
      self.Idle = false
    else
      self.Idle = true
    end
  end
end

于是烦人的事情发生,居然不能保存…… Started POST "/hardwares" for 127.0.0.1 at 2015-07-17 19:45:24 +0800 Processing by HardwaresController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"UpMreG5ZvfvQDF5uJp9bX09Uz9nPNW fx9biD+FYnSiilP29uyQ5dN+Ufl3DsoiOBz+L5uU5JzlNk1bDF2YUU6Q==", "hardware"=>{"AssetN um"=>"11", "CPU"=>"11", "Disk"=>"11", "Mem"=>"11", "BuyingTime(1i)"=>"2015", "Buy ingTime(2i)"=>"7", "BuyingTime(3i)"=>"17", "DeployingTime(1i)"=>"2015", "Deployin gTime(2i)"=>"7", "DeployingTime(3i)"=>"17", "Position"=>"11", "ServerType"=>"11", "ServerModel"=>"11", "PCorNot"=>"true", "ServiceNum"=>"11", "QuickServiceNum"=>" 11"}, "commit"=>"创建该硬件资产"} (0.2ms) begin transaction (0.0ms) rollback transaction Completed 422 Unprocessable Entity in 14ms (ActiveRecord: 0.8ms)

ActiveRecord::RecordNotSaved (Failed to save the record): app/controllers/hardwares_controller.rb:18:in `create'

Rendered /home/thanatos/.gem/ruby/gems/actionpack-4.2.3/lib/action_dispatch/mid dleware/templates/rescues/_source.erb (16.5ms) Rendered /home/thanatos/.gem/ruby/gems/actionpack-4.2.3/lib/action_dispatch/mid dleware/templates/rescues/_trace.html.erb (2.2ms) Rendered /home/thanatos/.gem/ruby/gems/actionpack-4.2.3/lib/action_dispatch/mid dleware/templates/rescues/_request_and_response.html.erb (1.0ms) Rendered /home/thanatos/.gem/ruby/gems/actionpack-4.2.3/lib/action_dispatch/mid dleware/templates/rescues/diagnostics.html.erb within rescues/layout (31.2ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/_markup.html.erb (0.3ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/_inner_console_markup.html.erb within layouts/inlined_string (0.4ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/_prompt_box_markup.html.erb within layouts/inlined_string (0.2ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/style.css.erb within layouts/inlined_string (0.3ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/console.js.erb within layouts/javascript (14.2ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/main.js.erb within layouts/javascript (0.2ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/error_page.js.erb within layouts/javascript (0.3ms) Rendered /home/thanatos/.gem/ruby/gems/web-console-2.2.1/lib/web_console/templa tes/index.html.erb (27.1ms)

求指导!非常感谢!

before_save :dle?

before_*回调返回false的时候会终止回调链并撤销事务。 具体内容看一下 rails guides 吧。

可以在保存的时候,设置下断点(用 byebug 或者 binding.pry),save 出错的时候,看下 error 信息。我猜,是不是传入了一些不该有的字段?

def idle?
  if (Adapter1IP.empty? || Adapter2IP.nil? || Adapter3IP.nil? || Adapter4IP.nil? || Adapter5IP.nil? )
    self.Idle = false
  else
    self.Idle = true
  end
  true # always return true
end

另外,在读数据的时候,不需要 self,写的时候才需要。

params.require(:hardware).permit! 这个可以减少几根白发。 考虑一楼建议。另外可以先从简化的逻辑开始。

#5 楼 @chenge 决然还可以这样~真是非常感谢!自从接触 rails 后头发掉完了,所以白发不白发也没关系了。

#3 楼 @googya 通过 debugger 确实发现了问题,谢谢!

#4 楼 @justin 好的,谢谢!

需要 登录 后方可回复, 如果你还没有账号请 注册新账号