我有以下型号:
class Man < User
field :surname, type: String, default: ""
field :name, type: String, default: ""
NAME_LENGTH = 1..50
validates :surname, length: {in: NAME_LENGTH}, allow_blank: true
validates :name, length: {in: NAME_LENGTH}, allow_blank: true
validates :father, length: {in: NAME_LENGTH}, allow_blank: true
field :birthday, type: Integer #Timestamp
field :about, type: String
ABOUT_LENGTH = 2000
validates :about, length: {maximum: ABOUT_LENGTH}, allow_blank: true
embeds_many :skills
MAX_SKILLS_COUNT = 10
validates :skills, length: {maximum: MAX_SKILLS_COUNT}
#user got unique skills
index({login: 1, 'skills.caption_to_index': 1}, {unique: true, sparse: true})
end
嵌入式技能模型:
class Skill
include Mongoid::Document
CAPTION_LENGTH = 1..50
CAPTION_FILTER = /[^a-zа-я0-9]/
field :caption, type: String
field :caption_to_index, type: String
field :order, type: Integer
embedded_in :man
validates :caption, length: {in: CAPTION_LENGTH}
validates :order, presence: true
before_save do |document|
document.caption_to_index = document.caption.downcase.gsub(CAPTION_FILTER,'')
end
end
麻烦的是,当我做这样的事情时,mongoid会忽略长度验证:
pry(main)> u = Man.find_by(login:'tester')
pry(main)> s3 = Skill.new(caption:'JavaScript',order:1)
pry(main)> u.skills << s3
我可以无限次重复u.skills << s3
次,并且驱动程序会立即将其保存到数据库中。
另一个问题是唯一索引不起作用:
index({login: 1, 'skills.caption_to_index': 1}, {unique: true, sparse: true})
所有索引都是通过rake:mongoid:create_indexes
驱动程序允许使用相同的标题保存文档,这里是mongo shell中文档的一部分作为证明:
{
"_id" : ObjectId("56a0218167e92c3b8b000000"),
"caption" : "JavaScript",
"order" : 1,
"caption_to_index" : "javascript"
},
{
"_id" : ObjectId("56a0218167e92c3b8b000000"),
"caption" : "JavaScript",
"order" : 1,
"caption_to_index" : "javascript"
},
{
"_id" : ObjectId("56a0218167e92c3b8b000000"),
"caption" : "JavaScript",
"order" : 1,
"caption_to_index" : "javascript"
},
{
"_id" : ObjectId("56a0218167e92c3b8b000000"),
"caption" : "JavaScript",
"order" : 1,
"caption_to_index" : "javascript"
}
唯一性的测试用例也失败了:
require 'rails_helper'
include ApplicationHelper
describe Skill do
before :each do
@attrs = attributes_for :tester_man
@tester = create :tester_man
expect(@tester).to be_valid
expect(@tester.persisted?).to be true
end
it "skill caption is unique" do
#debugger
s1_good = Skill.new(caption:'<<cap Tion ..%#',order:2)
s2_good = Skill.new(caption:'other_caption',order:4)
s3_bad = Skill.new(caption:'CAPTION',order:1)
expect(s1_good).to be_valid
expect(s2_good).to be_valid
@tester.skills = [s1_good,s2_good]
@tester.save
expect(@tester).to be_valid
s3_bad = Skill.new(caption:'CAPTION',order:1)
@tester.skills << s3_bad
expect(@tester).not_to be_valid
end
end
如何让代码按预期运行?