2011-07-29 48 views
1

今天,我被implepenting用戶隨機uniq的字符串發生器(可以說像一個被遺忘的密碼令牌)耙正試圖太聰明,甚至觸發代碼

所以我建立發生器之前發現死循環* user_model *

def generate_random_string 
    random_string = CGI::escape(Base64.encode64(Digest::SHA1.digest("#{rand(1<<128)}/#{Time.now.to_f}/#{Process.pid}")))[0..12].downcase #I was required it has to have max 12 chars 
    if User.where('random_token_string = ?', random_string) 
    #if the string exist generate new one 
    self.generate_random_string 
    else 
     self.random_token_string = random_string 
    end 

    return random_string 
    end 

在應用程序控制臺工程100%爲一個或多個用戶

比我建造了一個rake任務也更新現有的用戶

task :generate_random_string_for_existing_users => :environment do 
    User.all.each do |user| 
    unless user.vanity_name 
     user.generate_random_string 
     p "#{user.id} failed to be updated for some reason !!!" unless user.save! 
    end 
    end 
end 

從我的觀點everithing確定

點,但是當我運行耙

RAILS_ENV=development rake generate_random_string_for_existing_users --trace 

我越來越

rake aborted! 
stack level too deep 
/home/tomi/.rvm/gems/[email protected]/gems/activerecord-3.0.1/lib/active_record/connection_adapters/abstract/quoting.rb:10 

......僅此而已無所不及。當我試圖從軌道運行控制檯它傳遞trought seccussfully

現在,當我在* user_model *

#.... 
    if User.where('random_token_string = ?', random_string) 
    #self.generate_random_string 
    else 
    #.... 

COMENT了遞歸...它會通過。所以,如果我正確地理解了RAKE,即使在代碼被觸發之前,它仍然很聰明。 任何人都可以解釋我爲什麼?

+3

在Ruby中,你不應該使用遞歸此。只對具有尾部調用優化的語言的循環使用遞歸,並且僅在寫入遞歸的地方使語言實際上可以將循環轉換爲尾部調用。 – yfeldblum

+0

所以這個故事的寓意是:「不要在紅寶石中使用遞歸(像這樣)」....我理解正確嗎? ...而不是像@Jesse Wolgamott在下面的答案中做的那樣? – equivalent8

回答

1

公正的評論是正確的金錢 - 而不是,只是這樣做:

def build_random_string 
    CGI::escape(Base64.encode64(Digest::SHA1.digest("#{rand(1<<128)}/#{Time.now.to_f}/#{Process.pid}")))[0..12].downcase #I was required it has to have max 12 chars 
end 

def random_string_is_unique?(random_string) 
    User.where(:random_tokent_string => random_string).count == 0 
end 

def generate_random_string 
    # we'll loop until we find a unique code 
    # it will execute build_random_string once before checking the while condition 
    begin 
    self.random_token_string = build_random_string 
    end while random_string_is_unique?(random_token_string) 
end 
+0

這是很好的一個,我自己重構代碼,但這更優雅... – equivalent8

相關問題