2014-10-02 95 views
0

我試圖找出它有可能執行一個方法調用,在驗證期間改變進入數據庫的某些屬性的信息。所需的工作流程是:用戶提交一個url,我驗證它,如果它匹配正則表達式,則調用embedly。 embedly函數獲取標題和image_url的信息。我也想對title和image_url進行驗證,但是在我調用embedly方法之前,這些並不存在。是否可以在幾次驗證中調用一個方法?

有沒有一種辦法:1。 驗證LINK_URL 2.呼叫embedly方法 3.驗證所產生的標題和圖片網址屬性?

任何幫助表示讚賞:

class ListLink < ActiveRecord::Base 
    belongs_to :list 
    default_scope -> {order('created_at DESC')} 

    #the REGEX urls are matched against 
    VALID_URL_REGEX = /\A(http:\/\/|https:\/\/|www|)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?\z/i 

    validates :link_url, presence: true, 
    format:{with: VALID_URL_REGEX, message: "Please enter a valid url."} 
    validates :list_id, presence: true 

    #if is a valid url, ping embedly for more information on it 
    before_save :embedly 

    #is it possible to call just these 2 validations after the :embedly method? 
    validates :title, presence: true, length:{minimum: 4, maximum: 200} 
    validates :image_url, presence: true 


    private 
    def embedly 
     embedly_api = Embedly::API.new :key => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 
       :user_agent => 'Mozilla/5.0 (compatible; mytestapp/1.0; [email protected])' 
     #duplicate the url for use in the embedly API 
     url = link_url.dup 
     obj = embedly_api.extract :url => url 
     #extract and save a title and image element to the database 
     self.title = obj[0].title 
     self.image_url = obj[0]["images"][0]["url"] 
    end 
end 
+0

我不這麼認爲 - 我認爲你必須檢查URL的格式在embedly方法 – 2014-10-02 09:16:11

回答

0

你可以寫一個before_validation回調,檢查你的link_url,如果它是有效的(即,如果它的URL匹配),執行你的embedly東西。然後,在定期驗證期間,仍然可以將錯誤消息添加到無效的link_url。這可能是這個樣子:

class ListLink < ActiveRecord::Base 
    before_validation :embedly_if_valid 

    # the REGEX urls are matched against 
    VALID_URL_REGEX = /\A(http:\/\/|https:\/\/|www|)[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(([0-9]{1,5})?\/.*)?\z/i 

    validates :link_url, presence: true, 
    format:{with: VALID_URL_REGEX, message: "Please enter a valid url."} 

    validates :list_id, presence: true 
    validates :title, presence: true, length:{minimum: 4, maximum: 200} 
    validates :image_url, presence: true 

    private 
    def embedly_if_valid 
    embedly if self.link_url =~ VALID_URL_REGEX 
    end 

    def embedly 
    embedly_api = Embedly::API.new :key => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 
      :user_agent => 'Mozilla/5.0 (compatible; mytestapp/1.0; [email protected])' 
    #duplicate the url for use in the embedly API 
    url = link_url.dup 
    obj = embedly_api.extract :url => url 
    #extract and save a title and image element to the database 
    self.title = obj[0].title 
    self.image_url = obj[0]["images"][0]["url"] 
    end  
end 

注意,你可能會得到的titleimage_url領域驗證錯誤,如果link_url無效。如果通過將link_url設置爲nilbefore_validation鉤子中,除非它有效,否則您可能可能在此編碼。

+0

這聽起來像是一個更好的方法,感謝您的幫助: ) – PaygeVii 2014-10-02 11:10:59

0

除了使用before_save回調,我建議在自定義二傳手做這link_url,沿着線的東西...

def link_url=(url) 
    if url =~ VALID_URL_REGEX 
    super 
    embedly 
    end 
end 

,或者,如果你不叫link_url = ...在這樣做before_validation回調。

+0

我可以問,在活動記錄對象的生命週期的哪個點發生setter?是否在驗證之前?無論哪種方式,都會嘗試一下,謝謝! – PaygeVii 2014-10-02 11:12:14

0

您將無法按照您在此處提及的方式進行操作。根據對象的狀態,您似乎有不同的驗證。

相反,您可以在保存之前運行embedly,然後驗證所有內容。如果您需要使用embedly方法進行驗證,則可以使用form object (example #3)來分離流程的不同步驟。

你也可以使用before_validation運行embedly,但它使你需要複製由embedly所需的字段驗證(需要驗證之前,測試它在你的方法,然後在模型上的情況下,你需要稍後重新運行該方法)。你可以通過一個名爲explicit的自定義驗證方法來傳遞它,但我不是這個的忠實粉絲。

0

我會重新考慮一下設計。調用像Embedly這樣的外部服務最好是作爲後臺工作完成,因爲您永遠不知道需要多長時間,並且可能會阻止您的應用程序的其他請求。

但是,您必須允許創建沒有標題和image_url的ListLink。您的後臺工作人員在運行時會設置這些屬性。

當然,您仍然希望驗證它們,但這可以使用條件驗證來完成。事情是這樣的:

validates :title, presence: true, length:{minimum: 4, maximum: 200}, unless: :new_record?

+0

啊好吧,所以你建議保存鏈接到數據庫,然後調用嵌入和插入它返回的值?感謝您的建議:) – PaygeVii 2014-10-02 11:07:43

+0

是的,就是這樣。 – 2014-10-02 11:25:58

相關問題