select date

hello, i am developing one application i want to set work date in which (day,month,year)any be blank. so how i do it? what i do in controller model rhtml. how i achieved it? i saw select date syntax but i haven't understand it?

Sunny, I had a similar requirement in which a date could be only partially known -- could be a full date (Oct 11, 1998), just a month (Oct 1998), or just a year (1998). I ended up creating a new class PartialDate which wrapped two attributes, the date, and the "mask", letting the mask represent the amount of specificity of the date (0 for the date represents a full date, 1 for only month and year, 2 for only year). Saving the date and making it work with ActiveRecord was a real challenge -- I ended up patching execute_callstack_for_multiparameter_attributes to break the date field into its two parts, say, "born_date" and "born_mask".

The born_date would always be a valid date (defaulting to the first of the month if mask was 1 and the first of the year if mask is 2).

<code> class ActiveRecord::Base   class << self

  def mask_attributes (*cols)       self.send("attr", *cols)       write_inheritable_array("attr_masked", cols + (masked_attributes

))

      cols.each do |col|         attr_protected((col.to_s + "_mask").to_sym)         attr_protected((col.to_s + "_date").to_sym)         class_eval <<-"EOL"           def #{col.to_s}             @#{col.to_s} ||= if #{col.to_s}_date                                PartialDate.new #{col.to_s}_date, #{col.to_s}_mask                              else                                nil                              end           end           def #{col.to_s}=(dt)             if dt.nil?               self.#{col.to_s}_date = nil               self.#{col.to_s}_mask = nil             else                case dt                 when String                   @#{col.to_s} = PartialDate.new(dt)                   self.#{col.to_s}_date = @#{col.to_s}.date                   self.#{col.to_s}_mask = @#{col.to_s}.mask                 when PartialDate                   @#{col.to_s} = dt                   self.#{col.to_s}_date = dt.date                   self.#{col.to_s}_mask = dt.mask                 when Date, DateTime                   @#{col.to_s} = PartialDate.new(dt,0)                   self.#{col.to_s}_date = @#{col.to_s}.date                   self.#{col.to_s}_mask = @#{col.to_s}.mask               end #case              end #if else           end #def         EOL       end     end

    def masked_attributes       read_inheritable_attribute("attr_masked") || write_inheritable_array("attr_masked", )     end

    def is_mask_column?(col_name)        col = col_name.to_s        if col =~ /^(.*)(_date|_mask)$/          base_col = $1          return is_masked?(base_col)        end        false     end

    def is_masked?(col_name)       masked_attributes.include?(col_name.to_sym)     end

private   def execute_callstack_for_multiparameter_attributes_with_mask(callstack)     new_callstack = Hash.new()     callstack.each_with_index do |arr, i|       name, values = *arr       if self.class.is_masked? name         date_name = name + "_date"         set_mask(name, values.nil? ? 0 : 3 - values.length)         new_callstack.merge!({date_name => values})       else         new_callstack.merge!({name => values})       end     end

execute_callstack_for_multiparameter_attributes_without_mask(new_callstack)   end

  def set_mask(col,value)     self.send("#{col}_mask=",value)   end

</code>

So I could use it like so:

class Person < ActiveRecord::Base   mask_attributes :born, :died end

and the database would look like

table people   born_date date   born_mask integer   died_date date   died_mask integer

The code for PartialDate is an unreadable mess because of all the regexes I use, but it shouldn't be too hard to cobble something together for your own use.

Hope that helps

Sorry, posted to wrong group -- thought I was in Rails-Talk...