2013-08-24 51 views
1

當用戶註冊我的應用程序以查看用戶名是否已存在時,我正在進行ajax驗證。無論何時您對用戶名字段進行解鎖/模糊處理,都會提出請求。本地我使用的是MySQL,在Heroku上是Postgres,所以我假設問題出在那裏,因爲它在我的開發機器上完全在本地運行。MySQL/Postgres之間的區分大小寫問題

註冊的用戶名是馬特例如...

發展:

  • 馬特=採取的是真實的
  • 亞光=採取的是真實的
  • MATT =採取的是真實的
  • MaTt =採取是真的,等等......

生產:

  • 馬特=採取的是真實的
  • 亞光=採取的是假
  • MATT =採取的是假
  • 馬特=採取的是假

這裏是方法(你甚至可以看到我進一步嘗試強制它失敗,再次在本地工作應該如何,但不是在生產中)...

def checkname 

    scrubb = ActionController::Base.helpers.sanitize(params[:username], :tags => '') 
    user = User.find_by_username(scrubb, :conditions => [ "lower(username) = ?", scrubb.downcase ]) 

    if user.blank? 
    render :json => { :isAvailable => true } 
    else 
    render :json => { :isAvailable => false } 
    end 

    return 

end 

**編輯* *

這是生成的MySQL查詢的輸出:

SELECT `users`.* FROM `users` WHERE `users`.`username` = 'MATT' AND (lower(username) = 'matt') LIMIT 1 

因此,它看起來像真正的問題是,與聲明Rails正在生成。我將如何刪除它?

+2

不知道爲什麼強迫爲小寫不工作,但我會建議反對在開發和生產中使用不同的DBMS--無論框架聲稱如何使所有工作保持一致,總是會有差異,並且您不希望在實時環境中第一次遇到它們。 – IMSoP

回答

0

我其實通過對自己的更多研究來解決這個問題,這對我來說更有意義。認爲它可能會幫助其他人。

username = params[:username] 
username.downcase 
@user = User.where(User.arel_table[:username].matches("%#{username}%")).first 

使用Arelmatches將使用ILIKE運營商的Postgres,和LIKE其他一切(source)。然後,撥打first,以便收到用戶的單個對象而不是集合(source)。

在MySQL和Postgres中都應該如何應用。我明白,這是不好的做法,有不同的生產和發展環境... moral of the story。我會盡快解決這個問題。

注:雖然不區分大小寫的話題我也跨越了一個名爲route_downcaser非常有用的寶石,你可能會感興趣來到

1

您正在使用錯誤的方法檢查用戶名。這:

User.find_by_username(scrubb) 

僅僅是一個生產這種SQL方式:

select * from users where username = ... 

然後添加一些:conditions

:conditions => [ "lower(username) = ?", scrubb.downcase ] 

find_by_username只是大頭針那些在WHERE子句,它會通常使用。其結果是:

User.find_by_username(scrubb, :conditions => ...) 

表示:

查找其usernameUserscrubb:conditions是真實的。

在MySQL中,字符串比較:

`users`.`username` = 'MATT' 

顯然是不區分大小寫的配置(我相信默認配置),但是這將是大小寫敏感的PostgreSQL中;如果username'Matt',那麼在PostgreSQL中該條件將失敗,除了區分大小寫的匹配之外,您將找不到其他任何內容。

(如果你想username爲區分大小寫或其他任何東西),使用不使用find_by_usernamewherecount

n = User.where('lower(username) = ?', scrubb.downcase).count 

或更好,whereexists?

taken = User.where('lower(username) = ?', scrubb.downcase).exists? 

將示波器添加到User似乎也是個好主意:

class User < ActiveRecord::Base 
    def self.with_username(username) 
    where('lower(username) = ?', username) 
    end  
end 

,然後你可以說:

how_many = User.with_username(scrubb).count 
taken = User.with_username(scrubb).exists? 

,你會不會擔心這個不區分大小寫的問題,其他地方。

而且,請在開發和生產中使用相同的堆棧,還有各種其他的小差異會導致你的悲傷。