是否可以在几次验证中调用一个方法?
我试图找出它有可能执行一个方法调用,在验证期间改变进入数据库的某些属性的信息。所需的工作流程是:用户提交一个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
你可以写一个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
注意,你可能会得到的title
和image_url
领域验证错误,如果link_url
无效。如果通过将link_url
设置为nil
在before_validation
钩子中,除非它有效,否则您可能可能在此编码。
这听起来像是一个更好的方法,感谢您的帮助: ) – PaygeVii 2014-10-02 11:10:59
除了使用before_save
回调,我建议在自定义二传手做这link_url
,沿着线的东西...
def link_url=(url)
if url =~ VALID_URL_REGEX
super
embedly
end
end
,或者,如果你不叫link_url = ...
在这样做before_validation
回调。
我可以问,在活动记录对象的生命周期的哪个点发生setter?是否在验证之前?无论哪种方式,都会尝试一下,谢谢! – PaygeVii 2014-10-02 11:12:14
您将无法按照您在此处提及的方式进行操作。根据对象的状态,您似乎有不同的验证。
相反,您可以在保存之前运行embedly
,然后验证所有内容。如果您需要使用embedly
方法进行验证,则可以使用form object (example #3)来分离流程的不同步骤。
你也可以使用before_validation
运行embedly
,但它使你需要复制由embedly
所需的字段验证(需要验证之前,测试它在你的方法,然后在模型上的情况下,你需要稍后重新运行该方法)。你可以通过一个名为explicit的自定义验证方法来传递它,但我不是这个的忠实粉丝。
我会重新考虑一下设计。调用像Embedly这样的外部服务最好是作为后台工作完成,因为您永远不知道需要多长时间,并且可能会阻止您的应用程序的其他请求。
但是,您必须允许创建没有标题和image_url的ListLink。您的后台工作人员在运行时会设置这些属性。
当然,您仍然希望验证它们,但这可以使用条件验证来完成。事情是这样的:
validates :title, presence: true, length:{minimum: 4, maximum: 200}, unless: :new_record?
啊好吧,所以你建议保存链接到数据库,然后调用嵌入和插入它返回的值?感谢您的建议:) – PaygeVii 2014-10-02 11:07:43
是的,就是这样。 – 2014-10-02 11:25:58
我不这么认为 - 我认为你必须检查URL的格式在embedly方法 – 2014-10-02 09:16:11