【问题标题】:in Ruby on Rails is it possible to call a method in the middle of several validations?在 Ruby on Rails 中,是否可以在多个验证中间调用一个方法?
【发布时间】:2014-10-02 08:50:10
【问题描述】:

我试图找出在验证期间是否可以执行一个方法调用来更改进入数据库的某些属性的信息。所需的工作流程是:用户提交一个 url,我对其进行验证,如果它与正则表达式匹配,则调用 embedly。 embedly 函数获取 title 和 image_url 的信息。我也想对 title 和 image_url 执行验证,但是在我调用 embedly 方法之前这些都不存在。

有没有办法: 1.验证link_url 2.调用embedly方法 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

【问题讨论】:

  • 我不这么认为 - 我认为您必须检查 embedly 方法中 url 的格式

标签: ruby-on-rails ruby regex validation


【解决方案1】:

您可以编写一个before_validation 回调来检查您的link_url,如果它有效(即,如果它与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

请注意,如果link_url 无效,您可能会收到titleimage_url 字段的验证错误。如果不需要,您可以通过在 before_validation 挂钩中将 link_url 设置为 nil 来解决此问题,除非它是有效的。

【讨论】:

  • 这听起来确实是一个更好的方法,感谢您的帮助:)
【解决方案2】:

我建议不要使用before_save 回调,而是在link_url 的自定义设置器中执行此操作,类似于...

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

或者,如果您没有调用 link_url = ...,请在 before_validation 回调中执行此操作。

【讨论】:

  • 请问,setter 发生在活动记录对象生命周期的哪个阶段?是在验证之前吗?无论哪种方式,都会尝试一下,谢谢!
【解决方案3】:

您将无法按照您在此处提到的方式进行操作。根据对象的状态,您似乎有不同的验证。

相反,您可以在保存之前运行embedly,然后验证所有内容。如果您需要一些验证才能使用embedly 方法,您可以使用form object (example #3) 来分隔流程的不同步骤。

您也可以使用before_validation 来运行embedly,但是这使得您需要在embedly 所需的字段上重复验证(您需要在验证之前在您的方法中对其进行测试,然后在模型以防您稍后需要重新运行该方法)。您可以使用一种称为显式的自定义验证方法通过它,但我不是这个的忠实粉丝。

【讨论】:

    【解决方案4】:

    我会重新考虑一下设计。调用像 Embedly 这样的外部服务最好作为后台作业完成,因为您永远不知道它需要多长时间,而且它可能会阻止您的应用程序的其他请求。

    但是,您必须允许在没有标题和 image_url 的情况下创建 ListLink。然后,您的后台工作人员将在运行时设置这些属性。

    当然,此时您仍然希望验证它们,但这可以使用条件验证来完成。像这样的:

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

    【讨论】:

    • 啊,好吧,所以您建议将链接保存到数据库,然后嵌入调用并插入它返回的值?感谢您的建议:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-03
    相关资源
    最近更新 更多