客户等级
class Client < ApplicationRecord
validates_presence_of :name, :email
validates_email_format_of :email, :message => 'is not looking good'
validates_uniqueness_of :email
has_many :projects
end
项目类
class Project < ApplicationRecord
belongs_to :client, optional: false
validates_presence_of :name
end
我的表的架构
create_table "clients", force: :cascade do |t|
t.string "name"
t.string "email"
t.string "phone"
t.string "address"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "projects", force: :cascade do |t|
t.string "name"
t.integer "client_id"
t.string "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
有时我想在没有指定客户端的情况下创建Project。所以我添加了选项:选项false。所以现在我可以在不指定任何客户端ID的情况下创建项目。但是,当我尝试使用client_id创建项目时,它接受client_id的任何值,即如果输入8并且如果此id在客户端中不存在,那么它也被接受。我希望在这种情况下它不应该保存这个项目。
我该如何实现这种行为?
我有rails版本5.1.4
答案 0 :(得分:1)
我会编写您自己的自定义验证,以确保在持久化项目记录之前,客户端的ID实际存在于您的数据库中:
class Project < ApplicationRecord
belongs_to :client, optional: false
validates_presence_of :name
validate :validate_client_id, if: :client_id?
private
def validate_client_id
errors.add(:client_id, "is invalid") unless Client.exists?(self.client_id)
end
end
仅当字段不为空时才会运行验证。这很方便,因为client_id
在您的情况下是可选的。
答案 1 :(得分:1)
首先是一些更改,是可选的:true,可选:false是默认行为,并且希望每次都获得一个关联的记录,据说,你可以这样做:
class Project < ApplicationRecord
belongs_to :client, optional: true
# Sorry, small bug, client_id? with value zero would return always false and it becomes zero when you input strings or false
# validates_presence_of :client, if: client_id?
validates_presence_of :client, unless: Proc.new{ |d| d.client_id.blank? }
end
这将在client_id存在时验证客户端记录
p = Project.new # => #<Project id: nil, client_id: nil, ...
p.valid? # => true
p.client = Client.first # => #Client id: 1, ...
p.valid? # => true
p.client = nil # => nil
p.valid? # => true
#Non-existent id 10
p.client_id = 10 # => 10
p.valid? # => false
p.errors.full_messages # => ["Client can't be blank"]
p.client_id = 1 # => 1
p.client # => #Client id: 1, ...
p.valid? # => true
您甚至可以使用自定义消息
validates_presence_of :client, message: 'invalid client', if: :client_id?
最后,只是一个建议,使用t.references进行迁移,以便能够使用外键并将此字段编入索引
t.references :client, foreign_key: true