【问题标题】:Rails 4: undefined method `facebook_copy_link' for LinkValidatorRails 4:LinkValidator 的未定义方法“facebook_copy_link”
【发布时间】:2016-03-24 08:50:34
【问题描述】:

在我的 Rails 4 中,我有一个 Post 模型,我需要在其上实现自定义验证。

按照in this questionin the documentation here的建议,我实现了以下代码:

#app/validators/link_validator.rb

class LinkValidator < ActiveModel::Validator
  def validate(record)
    if record.format == "Link"
      unless facebook_copy_link(record.copy)
        record.errors[:copy] << 'Please make sure the copy of this post includes a link.'
      end
    end
  end
end

#post.rb
class Post < ActiveRecord::Base
  [...]
  include ActiveModel::Validations
  validates_with LinkValidator
  [...]
end

————

UPDATEfacebook_copy_link方法定义如下:

class ApplicationController < ActionController::Base
  [...]
  def facebook_copy_link(string)
    require "uri"
    array = URI.extract(string.to_s)
    array.select { |item| item.include? ( "http" || "www") }.first
  end
  [...]
end

————

当我运行应用程序时,我收到以下错误:

NameError at /posts/74/edit
uninitialized constant Post::LinkValidator
validates_with LinkValidator

知道这里有什么问题吗?

————

更新 2:我忘记重新启动服务器。

现在,我收到一个新错误:

NoMethodError at /posts/74
undefined method `facebook_copy_link' for #<LinkValidator:0x007fdbc717ba60 @options={}>
unless facebook_copy_link(record.copy)

有没有办法将此方法包含在验证器中?

【问题讨论】:

    标签: ruby-on-rails validation ruby-on-rails-4 activemodel


    【解决方案1】:

    除了作为 Rails 验证器类之外,LinkValidator 也是一个 Ruby 类。因此,您几乎可以在其上定义任何方法。

    facebook_copy_link 似乎没有使用控制器实例的状态,因此您可以轻松地将方法移动到验证器类中:

    require "uri"
    
    class LinkValidator < ActiveModel::Validator
      def validate(record)
        if record.format == "Link"
          unless facebook_copy_link(record.copy)
            record.errors[:copy] << 'Please make sure the copy of this post includes a link.'
          end
        end
      end
    
      private
    
      def facebook_copy_link(string)
        array = URI.extract(string.to_s)
        array.select { |item| item.include? ( "http" || "www") }.first
      end
    end
    

    注意我是如何将facebook_copy_link 方法设为私有的。这是一个很好的做法,因为其他对象访问的唯一方法是validate

    作为旁注,没有必要将include ActiveModel::Validations 放在 ActiveRecord 子类中。 ActiveRecord 类中已经提供了验证。

    【讨论】:

    • 感谢这个非常有用的答案。如果你不介意的话,有两个快速的问题:1. facebook_copy_link 实际上在 PostsController 中被使用了两次,这就是它当前位于 ApplicationController 中的原因:鉴于这条新信息,你是否仍然建议移动它到验证器类? 2.我看到你把require "uri"代码放在class LinkValidator &lt; ActiveModel::Validator之前:有什么原因吗?
    • 可以将方法移动到模型中,但是需要验证的每个模型都必须定义方法。另一种选择是将其移动到验证器和控制器之外的类中。至于require,为了清楚起见,我更喜欢将所有依赖项列在源文件的顶部。 :)
    猜你喜欢
    • 2015-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-16
    • 1970-01-01
    相关资源
    最近更新 更多