Ben Smith
Ben Smith

Reputation: 861

Rails map two fields in form to one field in model

I am using Rails 4.2rc3 and the simple_form gem.

I have an Event model which has a field reservations_open_at which indicates how many seconds before the event starts that reservations can start to be made (e.g. reservations might open up 2 days in advance, or maybe 10 hours in advance).

However, I want to use a form with a text input for a number (reservations_open_at_amount) and a select form for either 'Hours' or 'Days' (reservations_open_at_unit). I.e. the user can input '2 days' or '10 hours' via the two fields.

I can't quite figure out the right way to use virtual attributes to set the reservations_open_at field in seconds using a regular @event.update(event_params) call in my controller.

I don't need to remember whether the user chose Hours or Days when editing an existing record; if the reservations_open_at amount modulo (24*60*60) is zero (i.e. the number of seconds is an exact multiple of days) then I will display the form with reservations_open_at / (24*60*60) and Days, else reservations_open_at / (60*60) and Hours.

Upvotes: 0

Views: 1040

Answers (1)

roob
roob

Reputation: 1136

You are already more than half way there.

In the model, add two virtual attributes, time_amount, time_units. Add these 2 to the views. Add a before_save callback to set the value in reservations_open_at.

Something like:

Edit: add getter for time unit

class Event < ActiveRecord::Base
  attr_accessor :time_unit, time_amount
  before_save :calculate_open_at
  ...
  def time_unit
    return @time_unit if @time_unit

    if ( self.time_amount = reservations_open_at / 1.day.seconds ) > 0
      @time_unit = 'days'
    else
      self.time_amount = reservations_open_at / 1.hour.seconds
      @time_unit = 'hours'
    end
  end

  def calculate_open_at
    conversion_rate = time_unit == "days" ? 1.day.seconds : 1.hour.seconds
    self.reservations_open_at = time_amount * conversion_rate
  end

  ...
end

Upvotes: 1

Related Questions