验证失败后返回对象

时间:2010-01-31 01:53:29

标签: ruby-on-rails activerecord model

是否存在保存对象的方法,但如果对象未通过给定字段的validation_uniqueness_of,则返回该对象?例如,我有以下内容:

class User
  has_many :words
...
end

class Word
  belongs_to :user
  validates_uniqueness_of :title
...
end  

我有一种情况,如果用户已经保存了这个单词,我想要返回Word对象,或者返回新保存的单词对象。我发现自己通过自己的搜索检查单词对象是否存在,然后执行保存,如果不是:

existing_word = find_by_word_and_user_id(word, user)
!existing_word.nil? ? existing_word : user.words.create({:word => word})

但我觉得如果用户没有保存单词,rails会在我的检查后执行标题唯一性验证的冗余搜索,我想知道我是否可以执行保存并返回已存在的对象rails找到验证。

2 个答案:

答案 0 :(得分:1)

你可以通过以下方式稍微干掉那句话:

find_by_word_and_user(word, user) || user.words.create(:word => word)
但这不是一个好主意,因为创建可能会失败的原因还有其他原因,因此无法保证它是唯一性问题。

你不会在第一时间看到明显的性能损失,我会坚持下去。您唯一的其他选择是删除验证本身,并使用上面的语句。但是,你必须确保在你创建单词的任何地方,你都在检查它的唯一性。

答案 1 :(得分:1)

您可能对#find_or_create_by_word_and_user感兴趣,这是ActiveRecord的另一种神奇方法:

obj = Word.find_or_create_by_word_and_user(word, user)

# Preferred way
obj = user.words.find_or_create_by_word(word)

无论如何,这将做2个数据库请求:没有办法解决这个问题。此外,如果您的Word实例有更多验证,那么创建将失败,因为#find_or_create_by不允许传递更多属性。

有关动态查找程序方法的所有详细信息,请在http://api.rubyonrails.org/classes/ActiveRecord/Base.html上搜索“基于动态属性的查找程序”。