Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/66.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails日期\u选择帮助程序和验证_Ruby On Rails_Activerecord - Fatal编程技术网

Ruby on rails Rails日期\u选择帮助程序和验证

Ruby on rails Rails日期\u选择帮助程序和验证,ruby-on-rails,activerecord,Ruby On Rails,Activerecord,我在Rails应用程序中的模型支持表单中有一个日期字段: <%= f.date_select :birthday, {:start_year => Time.now.year, :end_year => 1900, :use_short_month => true, :order => [:month, :day, :year], :prompt => {:month => 'Month', :day => 'Day', :ye

我在Rails应用程序中的模型支持表单中有一个日期字段:

<%= f.date_select :birthday,
  {:start_year => Time.now.year,
  :end_year => 1900,
  :use_short_month => true,
  :order => [:month, :day, :year],
  :prompt => {:month => 'Month', :day => 'Day', :year => 'Year'}},
  {:class => 'year',
  :id => 'user_birthday'}
%>
不幸的是,如果用户输入部分值,例如仅输入年份,则表单提交时仍然没有错误。相反,一个时髦的日期值被写入数据库。如何使这三个字段都成为必填字段

我想为此编写一个自定义验证,但我不知道如何正确访问生日元素的各个部分。我该怎么做

谢谢!
Moe

您可以覆盖创建时的
验证方法,如下所示:

class MyModel < ActiveRecord::Base
  def validate_on_create
    Date.parse(birthday)
  rescue
    errors.add_to_base("Wrong date format")
  end
end
classmymodel
我认为您必须在控制器本身中创建验证

日期部分被传递到
生日(1i)
生日(2i)
生日(3i)
。这里的问题是,在传递属性时,即在进行任何验证之前,会立即分配这些属性

您也可以覆盖
attributes=
方法来创建您自己的验证,但我不建议您这样做

请记住,如果您进行验证,那么针对任何错误的日期进行验证也可能是一件好事。(例如,2月31日,如果通过,将产生3月2日,而不是错误)

我认为这里的主要问题是,ActiveRecord实际上是在创建
日期之前将空值替换为
1
,这也意味着如果访问者只通过年份,那么该日期将在该年的1月1日创建。我想这是一种预期的行为,只允许使用年/月/日选择中的一个,仍然可以创建一个有用的日期。

与此相关,这是我找到的最佳解决方案但是我应该添加:天、月、年作为属性,我不明白为什么…(因为验证?请让我知道…)

User.rb 用户登记表
“月”%>
“日”%>
“年”%>

在遵循贝诺伊特的建议后,我提出了一些类似的虚拟属性。在视图侧的“字段”内有3个单独的选择(年、月、日)。数据提交给控制器的质量分配(控制器中没有修改,请参阅),然后传递给模型中的getter/setter(即虚拟属性)。我正在使用Rails 3.0.3和simpleForm作为视图代码

在视图中:

<%= f.label "Design Date", :class=>"float_left" %>
<%= f.input :design_month, :label => false, :collection => 1..12 %>
<%= f.input :design_day,   :label => false, :collection => 1..31 %>
<%= f.input :design_year,  :label => false, :collection => 1900..2020 %>
validate :design_date_validator 

def design_year
  design_date.year
end
def design_month
  design_date.month
end
def design_day
  design_date.day
end
def design_year=(year)
  if year.to_s.blank?
    @design_date_errors = true  
  else      
    self.design_date = Date.new(year.to_i,design_date.month,design_date.day)
  end
end  
def design_month=(month)
  if month.to_s.blank?
     @design_date_errors = true  
   else      
   self.design_date = Date.new(design_date.year,month.to_i,design_date.day)
  end
end  
def design_day=(day)
  if day.to_s.blank?
    @design_date_errors = true  
  else      
   self.design_date = Date.new(design_date.year,design_date.month,day.to_i)
  end
end  
#validator
def design_date_validator
  if @design_date_errors
    errors.add(:base, "Design Date Is invalid")
  end
end  
“design_date_attr”是虚拟属性,用于设置数据库中design_date的值。getter传回一个类似于表单中提交的内容的散列。setter检查空白并创建一个新的日期对象,设置它,还设置错误变量。自定义验证器:design_date_验证器检查错误实例变量并设置错误变量。我使用“:base”,因为变量名不是人类可读的,并且使用base会从错误字符串中删除该值


需要重构的一些东西可能是错误检查实例变量,但至少它似乎可以工作。如果有人知道更新日期对象的更好方法,我很想听听

Date.parse在这里不起作用,因为日期值不是无效的。只是有点怪。如果你把年份留空,你会得到类似“0007-01-01”的东西。你是对的。您应该使用civil而不是parse。例如:Date.civil(生日[:年])。to_i,生日[:月]。to_i,生日[日]。如果任何字段为空,则应抛出ArgumentError。不幸的是,这也不起作用。即使我正确输入了所有字段,它也会抛出一个错误。我试图在模型类中编写自定义验证方法,但无法使用
生日[:月]
访问字段值,甚至无法附加
。\u I
。有什么办法吗?我注意到你没有
:include\u blank=>true
。甚至可以留一个空白吗?如果你把年份定在2000年,你会得到什么日期?此外,:start_year应早于:end_year.Hi mckeed,
:prompt=>{:month=>'month',:day=>'day',:year=>'year'}
插入月、日和年的空白默认值
:end_year
小于
:start_year
,因为我需要按desc顺序排列的值。将其添加到
attr_ACCESS
的原因是允许批量分配属性。否则,在执行
User.new(params[:User])
@User.update_属性(params[:User])
时,它们将被剥离。但是,我认为这是没有必要的,除非您已经指定了它(也就是说,当它根本没有指定时,散列中的所有属性都会发送到模型,但这可能不适用于虚拟属性),感谢您提供的信息,实际上这是bug rite?。如何解决这个问题?
<%= f.select :month, options_for_select(User::MONTHS), :include_blank => "Month" %>
<%= f.select :day, options_for_select(User::DAYS), :include_blank => "Day" %>
<%= f.select :year, options_for_select(User::YEAR_RANGE), :include_blank =>"Year" %>
<%= f.label "Design Date", :class=>"float_left" %>
<%= f.input :design_month, :label => false, :collection => 1..12 %>
<%= f.input :design_day,   :label => false, :collection => 1..31 %>
<%= f.input :design_year,  :label => false, :collection => 1900..2020 %>
validate :design_date_validator 

def design_year
  design_date.year
end
def design_month
  design_date.month
end
def design_day
  design_date.day
end
def design_year=(year)
  if year.to_s.blank?
    @design_date_errors = true  
  else      
    self.design_date = Date.new(year.to_i,design_date.month,design_date.day)
  end
end  
def design_month=(month)
  if month.to_s.blank?
     @design_date_errors = true  
   else      
   self.design_date = Date.new(design_date.year,month.to_i,design_date.day)
  end
end  
def design_day=(day)
  if day.to_s.blank?
    @design_date_errors = true  
  else      
   self.design_date = Date.new(design_date.year,design_date.month,day.to_i)
  end
end  
#validator
def design_date_validator
  if @design_date_errors
    errors.add(:base, "Design Date Is invalid")
  end
end