formsruby-on-rails-4timeselect-menu

In Rails, how do I map a millisecond field to hours, minutes, and seconds fields?


I’m using Rails 4.2.3. In my model, I have a field that records the amount of time it took someone to do something. It is a field called “time_in_ms,” which is an integer in my PostGresql database. My question is, in my form, I don’t want the user to have to enter in milliseconds, I would rather have them select from hours, minutes, and seconds. How do I set this up in my Rails form? Since there are no such fields in my model, I don’t know what to put in my “collection_select” attributes …

  <div class="field">
    <%= f.label "Time" %>
    <%= collection_select(:time_unit, :time_unit, @hours, {:prompt => true} ) %> hrs
    <%= collection_select(:time_unit, :time_unit, @minutes, {:prompt => true} ) %> min
    <%= collection_select(:time_unit, :time_unit, @seconds, {:prompt => true} ) %> sec
    <%= f.hidden_field :time_in_ms, :validate => true %>
  </div>

How do I properly write and pre-populate the selectors based on my single “time_in_ms” field in my model?

Thanks, - Dave


Solution

  • As you haven't mentioned your controller, I am assuming the controller as TimersController. You need to make changes in the view as well as timer_params method in the controller.

    Here is the code on view:

    <div class="field">
        <%= f.label "Time" %>
        <%= select_tag('timer[hour]', options_for_select((1..12).to_a), {:prompt => 'Select Hour'} ) %> hrs
        <%= select_tag('timer[minute]', options_for_select((1..60).to_a), {:prompt => 'Select Minutes'} ) %> min
        <%= select_tag('timer[second]', options_for_select((1..60).to_a), {:prompt => 'Select Minutes'} ) %> sec
        <%#= f.number_field :time_in_ms %>
      </div>
    

    and here is the code on controller:

    def create
        @timer = Timer.new(timer_params)
    
        respond_to do |format|
          if @timer.save
            format.html { redirect_to @timer, notice: 'Timer was successfully created.' }
            format.json { render :show, status: :created, location: @timer }
          else
            format.html { render :new }
            format.json { render json: @timer.errors, status: :unprocessable_entity }      
          end
        end
    end
    
    
    def timer_params
       # Main Code goes here
       params.require(:timer).permit(:time_in_ms)
       params[:timer][:time_in_ms] = (params[:timer][:hour].to_i * 60 * 60 + params[:timer][:minute].to_i * 60 + params[:timer][:second].to_i) * 1000
    end
    

    I have left the validation part. You can implement that on client side as well as on server side.