我试图找出它可以在验证期间执行方法调用,该方法调用会改变进入数据库的某些属性的信息。所需的工作流程是:用户提交网址,我验证它,如果它与正则表达式匹配,则调用嵌入。 embedly函数获取title和image_url的信息。我也希望对title和image_url进行验证,但这些都不存在,直到我称之为embedly方法。
有没有办法: 1.验证link_url 2.调用嵌入式方法 3.验证生成的title和image_url属性?
感谢任何帮助:
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; my@email.com)'
#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 :(得分:0)
你可以写一个before_validation
回调来检查你的link_url
以及它是否有效(即如果它与网址匹配),执行你的嵌入式内容。然后,在常规验证期间,您仍然可以将错误消息添加到无效的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; my@email.com)'
#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
,除非它有效,否则您可能会对此进行编码。
答案 1 :(得分:0)
我建议不要使用before_save
回调,而是在link_url
的自定义设置器中执行此操作,这类似于......
def link_url=(url)
if url =~ VALID_URL_REGEX
super
embedly
end
end
或者,如果您没有致电link_url = ...
,请在before_validation
回调中执行此操作。
答案 2 :(得分:0)
你不能像你在这里提到的那样去做。根据对象的状态,您似乎有不同的验证。
相反,您可以在保存之前运行embedly
,然后验证所有内容。如果您需要进行某些验证才能使用embedly
方法,则可以使用form object (example #3)分隔流程的不同步骤。
您还可以使用before_validation
来运行embedly
,但是您需要在embedly
所需的字段上复制验证(您需要在方法中对其进行测试)在验证之前,然后在模型上,以防您以后需要重新运行该方法)。你可以通过一个名为explicitely的自定义验证方法来传递它,但我并不是它的忠实粉丝。
答案 3 :(得分:0)
我会重新考虑一下设计。调用像Embedly这样的外部服务最好是作为后台工作完成,因为你永远不知道要花多长时间,它可以阻止你的应用程序的其他请求。
但是,您必须允许创建ListLink而不使用title和image_url。然后,您的后台工作程序将在运行时设置这些属性。
当然,您仍然希望在此时验证它们,但这可以使用条件验证来完成。像这样:
validates :title, presence: true, length:{minimum: 4, maximum: 200}, unless: :new_record?