2015-08-26 35 views
1

調用模型的地方(...)方法比方說,我有兩個型號:客戶端和產品如何從ApplicationController中

的「用戶名」和客戶端的「電子郵件」應爲「唯一索引」,作爲「序列號「的產品

當用戶在唯一索引的表單字段上鍵入時,我有一個onblur函數,它向控制器發送具有屬性名稱和屬性值的請求。如果存在值,則立即通知用戶。

在ClientController中,我編寫了一個函數來檢查它是否唯一,並返回-2表示錯誤,-1表示不存在,或者表示存在正數(id)。

def unique 
    if params[:attrName].blank? or params[:attrValue].blank? 
    id = "-2" 
    else 
    cli = Client.where("#{params[:attrName]} = '#{params[:attrValue]}'").first 
    if cli != nil 
     id = cli["id"] 
    else 
     id = "-1" 
    end 
    end 

    render :json => { 
    :id => id 
    } 
end 

這是不好的原因有很多(SQL注入漏洞,違反乾的,因爲每個控制器將具有基本相同的方法。

我想寫內ApplicationController中「獨一無二」的功能,但正如你在上面看到的那樣,如果它是一個客戶端,我應該能夠調用「Client.where」,或者如果它是一個產品,我應該能夠調用「Product.where」。我怎樣才能以最「一般」的方式構建這個功能, ?我正在考慮原始SQL,但我認爲這是一種天真的方法。

+0

這是你的目標嗎?創建產品時,將「用戶名」和「電子郵件」組合成產品表中保存的「序列號」類型唯一索引。您的願望是確保如果同一用戶試圖創建另一個產品,任何產品,他們將被停止,因爲該用戶名和電子郵件已被用於創建產品。而且你沒有使用模型主動記錄關係來完成這個邏輯。是這樣嗎? – Elvn

+0

號碼「用戶名」和「電子郵件」與「產品」無關。它們是「獨特索引」屬性的例子。這就像您在創建電子郵件帳戶時一樣,並且在您輸入所需的電子郵件時,您會立即得到有關其可用性的反饋。這是因爲當你鍵入時,電子郵件字符串被髮送到服務器,並檢查它是否已經存在於數據庫中。請閱讀@yez答案,因爲它顯示我正在努力完成的任務 – Aleksandrus

+0

好的。謝謝。我只是想知道。 – Elvn

回答

3

避免原始SQL是明智的做法。

這項工作?

class ApplicationController < ActionController::Base 
    def unique 
    id = if params[:attrName].blank? || params[:attrValue].blank? 
     -2 
    elsif found = model_name.where(params[:attrName] => params[:attrValue]).take 
     found.id 
    else 
     -1 
    end 

    render json: { id: id } 
    end 
end 

你可以把在application_controller.rb然後在這兩個你ClientsControllerProductsController你會定義model_name方法:

class ClientsController < ApplicationController 
    def model_name 
    Client 
    end 
end 

class ProductsController < ApplicationController 
    def model_name 
    Product 
    end 
end 

這是可行的,但可能不是很理想。您可能希望讓Rails通過使用find來提高模型是否存在以及strong params用於驗證您需要的參數是否存在,從而完成更多工作。

+1

您可以通過從控制器名稱中搜集模型名稱來進一步優化 - 請參閱http://stackoverflow.com/questions/4869917/rails-how-to-get-the-model-class-name-based-on-the -controller-class-name(ie'controller_name.classify.constantize') – Troy

+0

不錯!我不知道一種方法可以簡單地返回一個模型,就像你在「def model_name ...」中所做的那樣。 – Aleksandrus

1

您可以將其移至某個模塊,並使其返回ActiveRecord關係。其優點是以後你可以鏈這與其他ActiveRecord relations如果你想,像(並注意我在SQL條件下使用?,而不是指導給帕拉姆)

#module 
module UniqueRecord 
    module ClassMethods 
    def unique(params) 
     where(params) 
    end 
    end 

    def self.included(receiver) 
    receiver.extend   ClassMethods 
    end 
end 

,並在課堂上使用它

#client.rb 
class Client < ActiveRecord::Base 
    include UniqueRecord 
end 

#product.rb 
class Product < ActiveRecord::Base 
    include UniqueRecord 
end 

所以,現在你的兩個類都有方法unique可用。

您可以創建密鑰的哈希值和值來獲得,例如:你可以動態地創建一個哈希來搜索電子郵件一樣

hash = {email: '[email protected]email.com'} 

,然後調用方法

Client.unique(hash) 

,如果你想,你可以通過班級名稱來叫它字符串

'Client'.constantize.unique(hash) 

還有一件事,最好是返回一個對象數組(如果找到)或空數組(如果找不到),而不是-1,-2。這將使你的API保持一致。像

Client.unique(hash).to_json

+0

我沒有完全理解。那麼,通過這種方法,我怎麼能檢查客戶的屬性「email」是否有像「[email protected]」這樣的值?會是這樣嗎? 「def unique(attrName,attrValue)... end」並使用它像''Client.constantize.unique('email','[email protected]'「? – Aleksandrus

+1

@Aleksandrus,我更新了我的答案 – sameera207

+0

好!我也會試試這個 – Aleksandrus

相關問題