ruby-on-rails - rails : Custom validations using ActiveModel

标签 ruby-on-rails ruby validation activemodel chronic

我目前正在尝试使用日期输入进行自定义验证,但不幸的是,它似乎不起作用。

应用程序中有两个页面,索引页面和搜索页面。索引页内有一个输入日期的文本字段。我正在使用Chronic gem它将文本解析为日期。如果日期无效,Chronic 将返回 nil。如果有效,它将重定向到搜索页面并显示日期。

到目前为止我编写的代码似乎无法正常工作,但我想要实现的是..

1) 验证 Chronic 不会返回 nil

2) 验证该日期大于今天的日期

请注意,我没有使用数据库,我只是希望能够在没有 ActiveRecord 的情况下验证输入的日期。如果有人可以帮助我解决这个问题,我将不胜感激。

views/main/index.html.erb

<%= form_tag({controller: "main", action: "search"}, method: "get") do %>
    <%= label_tag(:q, "Enter Date:") %>
    <%= text_field_tag(:q) %>
    <%= submit_tag "Explore", name: nil %>
<% end %>

views/main/search.html.erb

<%= @show_date %>

ma​​in_controller.rb

def search

    passed_info = Main.new

    if passed_info.valid_date?
        @show_date = passed_info
    else
        flash[:error] = "Please enter correct date!"
        render :index => 'new'
    end

end

models/main.rb

class Main

  include ActiveModel::Validations
  include ActiveModel::Conversion
  extend  ActiveModel::Naming

  attr_accessor :q

  validates_presence_of :q

  def initialize(params={})
    params.each do |attr, value|
    self.public_send("#{attr}=", value)
    end if params
  end

  def persisted?
    false
  end

  def valid_date?
    require 'chronic'
    if Chronic.parse(q).nil? || Chronic.parse(q) < Time.today
        errors.add(:q, "is missing or invalid")
    end
  end

end

编辑:

这就是问题所在......

本地主机:3000

enter image description here

然后它重定向到..

localhost:3000/main/search?utf8=%E2%9C%93&q=invalid+date+test

enter image description here

没有验证,没有日期,什么都没有..

最佳答案

问题

对返回值要更加小心。当您尝试使用 if valid_date? 保护 Controller 时,您所做的就是检查 valid_date? 是否返回 false。如果解析失败,返回值是errors.add的输出,而errors.add的输出又是Array#<<的输出。 。相应地,输出不是 nilfalse,因此它的计算结果为 true,因此 if 子句通过并且您继续前进。

潜在的解决方案

您可能想让Rails Validation Framework为你做更多的工作。不要将 valid_date? 视为 Controller 调用的公共(public)方法,而是调用由 ActiveModel::Validations 添加的 valid? 方法。 valid? 返回一个 bool 值,基于是否所有模型验证都通过。因此,您将像 Rails Way 一样,在 Controller 中调用 if model_instance.valid?

这让您只需在模型中编写验证器方法来表达您要编写的逻辑。现在,您在一个方法中拥有日期的所有验证逻辑,并带有一条错误消息。相反,您可以放置​​两个方法,这会添加更多描述性的单独错误方法。

class YourClass
  include ActiveModel::Validations

  validate :date_is_valid
  validate :date_not_before_today

  private
  def date_is_valid
    if Chronic.parse(q).nil?
      errors.add(:q, "Date is invalid")
    end
  end
  def date_not_before_today
    if Chronic.parse(q) < Date.today
      errors.add(:q, "Date cannot be before today")
    end
  end
end

关于ruby-on-rails - rails : Custom validations using ActiveModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31011248/

相关文章:

html - rails 4 : Change 'name' attribute of Simple Form input

javascript - 如何在文本字段中输入日期选择器的值

ruby-on-rails - Rails 源代码 - 为什么将类包装在类中?

jquery - 如何使用现有的 jQuery 代码将文本区域验证添加到表单中

java - 在 Java 中根据 XSD 1.1 验证 XML 时出错

html - Rails - 使用 h() 转义 HTML 并排除特定标签

Ruby - 将字符串首字母转换为小写的简单方法

ruby-on-rails - 根据 ActiveRecord 中的连接选择基于孙子属性的对象

jquery - 使用 jQuery 验证插件自定义日期格式

ruby-on-rails - Ruby on Rails上的多种类型的用户