我知道验证像“用户名”这样的标准单一字段的唯一性很容易。然而,对于具有无限数量输入的东西,例如,“喜欢的电影”,其中用户可以添加尽可能多的喜欢的电影,这是我无法弄清楚的。
他们可以选择通过构建器添加或删除字段,但如何确保没有两个或多个条目重复?
答案 0 :(得分:7)
我认为完成这样的事情的最简单方法是验证范围内某些事物的唯一性。我不能确定它是如何适合您的场景的,因为您没有描述模型关联,但这里是一个如何在FavoriteMovie模型中工作的示例:
class FavoriteMovie < ActiveRecord::Base
belongs_to :user
validates_uniqueness_of :movie_name, :scope => :user_id
end
这可确保一个特定用户不能有两个相同的电影名称。
答案 1 :(得分:4)
事实证明,使用嵌套属性时,您只能验证数据库中已有的内容,而不是新的重复出现次数。因此,遗憾的是,带有内存验证的验证扩展(下面)是唯一的选择。
#user.rb
class User
has_many :favorite_movies
validate :validate_unique_movies
def validate_unique_movies
validate_uniqueness_of_in_memory(
favorite_movies, [:name, :user_id], 'Duplicate movie.')
end
end
#lib/extensions.rb
module ActiveRecord
class Base
def validate_uniqueness_of_in_memory(collection, attrs, message)
hashes = collection.inject({}) do |hash, record|
key = attrs.map {|a| record.send(a).to_s }.join
if key.blank? || record.marked_for_destruction?
key = record.object_id
end
hash[key] = record unless hash[key]
hash
end
if collection.length > hashes.length
self.errors.add_to_base(message)
end
end
end
end
答案 2 :(得分:2)
解决这个问题的一个非常类似于解决方案的方法是在列上添加一个唯一的键约束,这些列必须是唯一的:
create unique index names_idx on yourtable (id, name);
答案 3 :(得分:0)
你可以轻松地检查它:
params[:user][:favourite_movies].sort.uniq == params[:user][:favourite_movies].sort
或在模型中:
self.favourite_movies.sort.uniq == self.favourite_movies.sort
irb(main):046:0> movies = ['terminator', 'ninja turtles', 'titanic', 'terminator' ].map {|movie| movie.downcase }
=> ["terminator", "ninja turtles", "titanic", "terminator"]
irb(main):047:0> movies.sort.uniq == movies.sort
=> false
答案 4 :(得分:0)
您可以尝试创建虚拟属性并检查其唯一性:
def full_name
[first_name, last_name].joun(' ')
end
def full_name=(name)
split = name.split(' ', 2)
self.first_name = split.first
self.last_name = split.last
end
您可以通过修复迁移来检查数据库级别的唯一性:
CREATE TABLE properties (
namespace CHAR(50),
name CHAR(50),
value VARCHAR(100),
);
execute <<-SQL
ALTER TABLE properties
ADD CONSTRAINT my_constraint UNIQUE (namespace, name)
SQL
答案 5 :(得分:0)
更现代的方法:validates
method
validates :movie_name, :uniqueness => {:scope => : user_id}