我的Rails应用程序发生了一些奇怪的事情。每次用户访问我以前创建的唯一url时,都会调用控制器操作并将记录保存到表中。
不幸的是,有时会创建两个相同的记录,而不是只创建一个。我添加了一个"validates_uniqueness_of“,但它不起作用。
我的控制器代码:
class ShorturlController < ApplicationController
def show
@shorturl = ShortUrl.find_by_token(params[:id])
@card = Card.find(@shorturl.card_id)
@subscriber = BotUser.find_by_sender_id(params['u'])
@letter_campaign = Letter.find(@card.letter_id).campaign_name.downcase
if AnalyticClic.where(card_id: @card.id, short_url_id: @shorturl.id, bot_user_id: @subscriber.id).length != 0
@object = AnalyticClic.where(card_id: @card.id, short_url_id: @shorturl.id, bot_user_id: @subscriber.id)
@ccount = @object[0].clicks_count
@object.update(updated_at: Time.now, clicks_count: @ccount += 1)
else
AnalyticClic.create(card_id: @card.id, short_url_id: @shorturl.id, bot_user_id: @subscriber.id, clicks_count: "1".to_i)
end
@final_url = @card.cta_button_url
redirect_to @final_url, :status => 301
end
end而模型:
class AnalyticClic < ApplicationRecord
validates_uniqueness_of :bot_user_id, scope: :card_id
end知道为什么有时我会复制唱片吗?if应该和validates_uniqueness_of一样防止这种情况发生。

发布于 2017-07-24 22:25:49
首先,我认为您的验证可能需要类似的内容(尽管,TBH,您的语法可能很好):
class AnalyticClic < ApplicationRecord
validates :bot_user_id, uniqueness: { scope: :card_id }
end那么,我认为你应该清理一下你的控制器。类似于:
class ShorturlController < ApplicationController
def show
@shorturl = ShortUrl.find_by_token(params[:id])
@card = Card.find(@shorturl.card_id)
@subscriber = BotUser.find_by_sender_id(params['u'])
@letter_campaign = Letter.find(@card.letter_id).campaign_name.downcase
analytic_clic.increment!(:click_count, by = 1)
@final_url = @card.cta_button_url
redirect_to @final_url, :status => 301
end
private
def analytic_clic
@analytic_clic ||= AnalyticClic.find_or_create_by(
card_id: @card.id,
short_url_id: @shorturl.id,
bot_user_id: @subscriber.id
)
end
end 有几件重要的事情要注意:
您将希望创建一个在数据库级别强制执行唯一性的索引(正如max所说)。我相信这看起来会像:
class AddIndexToAnalyticClic < ActiveRecord::Migration
def change
add_index :analytic_clics [:bot_user_id, :card_id], unique: true, name: :index_bot_user_card_id
end
end您将希望创建一个迁移,将:click_count设置为create上0的默认值(否则,您将遇到nil问题,我怀疑)。
而且,您需要考虑与increment!的并发性(参见文档)。
发布于 2017-07-24 22:21:42
您需要在数据库表中创建唯一的索引。可能有两个进程一起创建条件。停止这些重复记录的唯一方法是在DB级别上具有唯一性约束。
https://stackoverflow.com/questions/45290644
复制相似问题