简体   繁体   English

在保存到数据库之前检查记录是否存在-Rails,Twitter,ActiveRecord

[英]check if record exists before saving to db - Rails, Twitter, ActiveRecord

I am using a Twitter Gem to pull and save Tweets from user's timeline. 我正在使用Twitter Gem从用户的时间轴中提取并保存Tweets。 Before saving each message , I want to check if this record already exists by comparing the new message's tweet_id to the array of tweet_id 's already saved in the db. 节约每一之前message ,我要检查,如果这个记录已经被新的消息的比较存在tweet_id到的阵列tweet_id的已经保存在数据库中。 No matter what I try, I am still seeing duplicated records being saved in the messages table. 无论我尝试什么,我仍然会看到重复的记录被保存在messages表中。 Here is what I got: 这是我得到的:

Controller call: 控制器调用:

@messages = Message.pull_tweets(@user)

"pull_tweets" method: “ 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" method: “ 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

The most direct cause of your problem is that tweets.each will return the tweets array, which since it is not nil or false has a truthy value: you're not using the result of your validate_uniqueness_of method. 问题的最直接原因是tweets.each将返回tweets数组,由于它不是nil或false,因此具有真实值:您没有使用validate_uniqueness_of方法的结果。

You instead would want to either do something like 相反,您可能想做类似的事情

tweets.all? { |tweet| validate_uniqueness_of(user,tweet) }

which returns true only if all the tweets meet your test, or more likey to be what you want 仅当所有推文都通过您的测试时才返回true,或更可能是您想要的

if tweets
  tweets = tweets.select { |tweet| validate_uniqueness_of(user,tweet) }
  tweets.each { |tweet| user.messages.create!(tweet_id: tweet.id ... } 
end 

This would however be rather non idiomatic code. 但是,这将是相当惯用的代码。 You would usually create a validation on your tweet class and add a unique index on the tweet_id column - a uniqueness validation should always be backed up by a unique index or you run the risk of rice conditions. 通常,您将在tweet类上创建一个验证,并在tweet_id列上添加一个唯一索引-唯一性验证应始终由唯一索引来备份,否则您将面临大米状况的风险。

The validation side of things would look like 验证方面看起来像

class Message < ActiveRecord::Base
  validate_uniqueness_of :tweet_id, scope: :user_id #assuming that message belongs_to :user
end

You can either keep using create! 您可以继续使用create! and rescue the validation exception that will be thrown or switch to create which returns true/false depending on what happened. 并挽救将抛出的验证异常或切换到create该异常,根据发生的情况返回true / false。 In both cases ActiveRecord::RecordNotUnique will be raised if a duplicate slips past the validation 在这两种情况下,如果重复项超出验证范围,则会引发ActiveRecord::RecordNotUnique

您还可以根据:scope参数来验证tweet_id是否唯一:

validates_uniqueness_of :tweet_id, scope: :user_id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM