2014-10-02 92 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

相关问题