Question: I have a date field in a model backed form in my Rails App:

```
<%= 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'}
%>

```

It is being validated in the model code using:

```
validates_presence_of :birthday, :message => 'is a required field'

```

Unfortunately, if the user enters a partial value such as just the year, the form still submits without an error. Instead a funky date value gets written to the db. How do I make all three fields be mandatory?

I'd like to write a custom validation for this, but I don't know how to properly access the indvidual pieces of the birthday element. How can I do this?

Thanks!
Moe

Answer: 
Related to this [post](https://stackoverflow.com/questions/597328/how-do-i-validate-a-date-in-rails), this is the best solution I've found. **However I should add :day, :month, :year as attr\_accessible, thing I don't understand why..** (because of validation? please let me know..)

User.rb
=======

```
MONTHS = ["January", 1], ["February", 2], ...
DAYS = ["01", 1], ["02", 2], ["03", 3], ...
START_YEAR = Time.now.year - 100
END_YEAR = Time.now.year
YEAR_RANGE = START_YEAR..END_YEAR

attr_accessible :day, :month, :year
attr_accessor :day, :month, :year

before_save :prepare_birthday

validate :validate_birthday

private

def prepare_birthday
  begin
    unless year.blank? # in order to avoid Year like 0000
      self.birthday = Date.new(self.year.to_i, self.month.to_i, self.day.to_i)
    end
      rescue ArgumentError
    false
  end
end

def validate_birthday
  errors.add(:birthday, "Birthday is invalid") unless prepare_birthday
end

```

user registration form
======================

```
<%= 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" %>

```
After following Benoitr's suggestions I came up with something similar using virtual attributes. On the View side there are 3 separate select's (year,mon,day) inside of a 'fields\_for'. The data is submitted to the controller's mass assignment (no modifications in controller, see [asciicasts #16](http://asciicasts.com/episodes/16-virtual-attributes)) and then passed to a getter/setter (i.e. virtual attribute) in the model. I'm using Rails 3.0.3, and simpleForm for the view code.

**In the View:**

```
<%= 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 %>

```

**In the Model:**

```
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' is the virtual attribute which sets the value of design\_date in the database. The getter passes back an hash similar to what gets submitted in the form. The setter checks for blanks and creates a new date object and sets it and also sets the error variable. The custom validator :design\_date\_validator checks for the error instance variable and sets the errors variable. I used ':base' because the variable name was not human readable and using base removes that value from the error string. 

A few things to refactor might be the error checking instance variable, but it seems to work at least. If anyone knows a better way to update the Date objects I'd love to hear it.