I am using a Twitter Gem to pull and save Tweets from user's timeline. 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. No matter what I try, I am still seeing duplicated records being saved in the messages
table. Here is what I got:
Controller call:
@messages = Message.pull_tweets(@user)
"pull_tweets" method:
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:
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.
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
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.
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! and rescue the validation exception that will be thrown or switch to create
which returns true/false depending on what happened. In both cases ActiveRecord::RecordNotUnique
will be raised if a duplicate slips past the validation
您还可以根据:scope参数来验证tweet_id是否唯一:
validates_uniqueness_of :tweet_id, scope: :user_id
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.