在保存到数据库之前检查记录是否存在 - Rails、Twitter、ActiveRecord
check if record exists before saving to db - Rails, Twitter, ActiveRecord
我正在使用 Twitter Gem 从用户的时间线中提取和保存推文。在保存每个 message
之前,我想通过将新消息的 tweet_id
与数据库中已保存的 tweet_id
的数组进行比较来检查此记录是否已存在。无论我尝试什么,我仍然看到重复的记录保存在 messages
table 中。这是我得到的:
控制器调用:
@messages = Message.pull_tweets(@user)
"pull_tweets"方法:
def self.pull_tweets(user)
tweets = $twitter.home_timeline # API call to pull all tweets from the timeline
if tweets && tweets.each { |tweet| validate_uniqueness_of(user,tweet) }
tweets.each { |tweet| user.messages.create!(tweet_id: tweet.id ... }
...
else
...
end
end
"validate_uniqueness_of"方法:
def self.validate_uniqueness_of(user,tweet)
if user.messages.pluck(:tweet_id).exclude?(tweet.id.to_s)
return true
else
return false
end
end
你的问题最直接的原因是 tweets.each
将 return tweets
数组,因为它不是 nil 或 false 有一个真值:你不是使用您的 validate_uniqueness_of
方法的结果。
你反而会想做类似
的事情
tweets.all? { |tweet| validate_uniqueness_of(user,tweet) }
只有当所有推文都符合您的测试,或者更可能是您想要的时,return才是正确的
if tweets
tweets = tweets.select { |tweet| validate_uniqueness_of(user,tweet) }
tweets.each { |tweet| user.messages.create!(tweet_id: tweet.id ... }
end
然而,这将是相当不惯用的代码。您通常会在推文 class 上创建验证并在 tweet_id
列上添加唯一性索引 - 唯一性验证应始终由唯一性索引支持,否则您 运行 的风险大米情况。
事情的验证方面看起来像
class Message < ActiveRecord::Base
validate_uniqueness_of :tweet_id, scope: :user_id #assuming that message belongs_to :user
end
您可以继续使用 create!并拯救将抛出的验证异常或切换到 create
which returns true/false 取决于发生的事情。在这两种情况下,如果重复项通过验证
,则会引发 ActiveRecord::RecordNotUnique
您还可以根据 :scope 参数验证 tweet_id 是否唯一:
validates_uniqueness_of :tweet_id, scope: :user_id
我正在使用 Twitter Gem 从用户的时间线中提取和保存推文。在保存每个 message
之前,我想通过将新消息的 tweet_id
与数据库中已保存的 tweet_id
的数组进行比较来检查此记录是否已存在。无论我尝试什么,我仍然看到重复的记录保存在 messages
table 中。这是我得到的:
控制器调用:
@messages = Message.pull_tweets(@user)
"pull_tweets"方法:
def self.pull_tweets(user)
tweets = $twitter.home_timeline # API call to pull all tweets from the timeline
if tweets && tweets.each { |tweet| validate_uniqueness_of(user,tweet) }
tweets.each { |tweet| user.messages.create!(tweet_id: tweet.id ... }
...
else
...
end
end
"validate_uniqueness_of"方法:
def self.validate_uniqueness_of(user,tweet)
if user.messages.pluck(:tweet_id).exclude?(tweet.id.to_s)
return true
else
return false
end
end
你的问题最直接的原因是 tweets.each
将 return tweets
数组,因为它不是 nil 或 false 有一个真值:你不是使用您的 validate_uniqueness_of
方法的结果。
你反而会想做类似
的事情tweets.all? { |tweet| validate_uniqueness_of(user,tweet) }
只有当所有推文都符合您的测试,或者更可能是您想要的时,return才是正确的
if tweets
tweets = tweets.select { |tweet| validate_uniqueness_of(user,tweet) }
tweets.each { |tweet| user.messages.create!(tweet_id: tweet.id ... }
end
然而,这将是相当不惯用的代码。您通常会在推文 class 上创建验证并在 tweet_id
列上添加唯一性索引 - 唯一性验证应始终由唯一性索引支持,否则您 运行 的风险大米情况。
事情的验证方面看起来像
class Message < ActiveRecord::Base
validate_uniqueness_of :tweet_id, scope: :user_id #assuming that message belongs_to :user
end
您可以继续使用 create!并拯救将抛出的验证异常或切换到 create
which returns true/false 取决于发生的事情。在这两种情况下,如果重复项通过验证
ActiveRecord::RecordNotUnique
您还可以根据 :scope 参数验证 tweet_id 是否唯一:
validates_uniqueness_of :tweet_id, scope: :user_id