2017-07-24 128 views
0

我的Rails應用程序有些奇怪的事情發生。每次用戶訪問我之前創建的唯一網址時,都會調用控制器操作並將記錄保存到表中。Rails:同時創建的重複記錄

不幸的是,有時會創建兩個相同的記錄而不是一個。我添加了「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。

enter image description here

+0

你應該把驗證檢查在數據庫級別上,不只是在車型。請參閱[do-rails-need-database-level-constraints](https://stackoverflow.com/questions/2589509/does-rails-need-database-level-constraints) –

回答

1

首先,我相信您的驗證可能需要看起來像(雖然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 

一些重要的事情需要注意:

你要創建一個強制在數據庫級別唯一性索引(如最大pleaner說)。我相信會是這個樣子:

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_count0上創建一個默認值(否則,你就會有一個nil問題,我懷疑)。

而且,你要想想有increment!併發(見docs

+0

謝謝,它可行! – AlphaNico

+0

太棒了!很高興幫助。 – jvillian

0

你需要在你的數據庫表中創建唯一索引。可能有兩個過程共同創造條件。阻止這些重複記錄的唯一方法是在數據庫級別具有唯一性約束。