如何在保存在rails上的ruby之前验证表中的记录

Sur*_*ngh 3 model ruby-on-rails actioncontroller

我是Ruby on Rails的新手我有一个场景,其中我有一个包含一些字段的表单.我需要对具有数据的表进行验证的字段值之一.我想限制用户保存任何数据,除非使用表记录验证该字段.

最初我在控制器中添加了代码以验证它,但我有其他字段需要验证为空,所以它不起作用.

此外,我希望验证错误成为其他错误的一部分.

我在模型文件中尝试了以下代码

before_create :validate_company_id

def validate_company_id
    cp = Company.find_by_company_id(self.company)
    if @cp != nil
       return
     else
        self.status ||= "Invalid"    
     end
end
Run Code Online (Sandbox Code Playgroud)

但它没有验证,你能帮助我如何验证它.

关于Surjan

shi*_*ime 16

这些家伙回答正确,但提供了解决方案的另一种方式.你可以问自己:"为什么我的代码没有被执行?"

首先,您的代码中存在错误 - @cp未定义.另外,我不知道你想要实现什么self.status ||= "Invalid".

您也不必self在调用属性时使用,但在分配新属性值时必须调用它.所以没self.company必要,你可以使用company.

我也注意到你company_idcompanies表中有你的属性.这不是必要的,常见的惯例是仅使用id.如果您不想更改表格,可以id在模型上设置字段,如下所示:

class Company < ActiveRecord::Base
  set_primary_key :company_id

  # ... the rest of your model code ...
end
Run Code Online (Sandbox Code Playgroud)

之后你可以用Company.find而不是Company.find_by_company_id.

好的,假设修复后你有以下代码:

before_create :validate_company_id

def validate_company_id
    cp = Company.find(company)
    if cp != nil
       return
     else
        self.status ||= "Invalid"    
     end
end
Run Code Online (Sandbox Code Playgroud)

首先,我想在这里使用三元运算符

before_create :validate_company_id

def validate_company_id
    Company.find(company) ? return : self.status ||= "Invalid"
end
Run Code Online (Sandbox Code Playgroud)

这不是更干净吗?它完全一样.

现在关于self.status你的.如果您想使对象无效,则ActiveModel必须在errors哈希中设置一些值.如果您认为状态属性为"无效"的模型无效,则您会产生误解.它仍然是Rails中完全有效的模型.

那么你如何宣告无效?

你把一些值放errors入哈希值.您还可以指定消息以及您验证错误所引用的属性.

所以让我们在你的模型上做

before_create :validate_company_id

def validate_company_id
    Company.find(company) ? return : errors.add(:company,"Invalid Company ID")
end
Run Code Online (Sandbox Code Playgroud)

现在,如果您尝试使用无效的company_id保存模型,它仍会传递并保存到数据库中.这是为什么?

这是因为ActiveModel生命周期.你的方法被调用太晚了.

以下是您可以使用的所有回调方法

创建

before_validation
after_validation
before_save
around_save
before_create
around_create
after_create
after_save
Run Code Online (Sandbox Code Playgroud)

更新

before_validation
after_validation
before_save
around_save
before_update
around_update
after_update
after_save
Run Code Online (Sandbox Code Playgroud)

销毁

before_destroy
around_destroy
after_destroy
Run Code Online (Sandbox Code Playgroud)

请注意在验证周期后很长时间内如何调用方法.所以,你不应该使用before_create,但after_validation还是before_validation回调来代替.

在这里,我们使用您的模型的工作验证方法.

after_validation :validate_company_id

def validate_company_id
    Company.find(company) ? return : errors.add(:company,"Invalid Company ID")
end
Run Code Online (Sandbox Code Playgroud)


小智 7

而不是使用before_create.您可以告诉模型使用自定义方法进行验证,如下所示

validate :validate_company_id

def validate_company_id
    cp = Company.find_by_company_id(self.company)
    if cp.nil?
      errors.add(:company, 'Invalid Company ID')
    end
end
Run Code Online (Sandbox Code Playgroud)