views:

298

answers:

2

I am new to Ruby on Rails and have been using Scaffolding. On one of the forms I want to be able to have two fields and then have the difference between the two submitted to the database.

Instead of :pickupamount, I want (Ending Amount - Starting Amount) to be calculated and entered into the pickupamount column of my database.

Thanks in advance!

A: 

In your view:

form_tag '/some_action' do
    text_field_tag 'start_amount'
    text_field_tag 'end_amount'
end

In your controller:

def create
    model = Model.new
    model.pickupamount = params[:end_amount].to_i - params[:start_amount].to_i
    model.save!
end
ez
The question mentioned Ending Amount - Starting Amount, and you show the opposite.
Sarah Vessels
corrected that, thanks Sarah
ez
+2  A: 

You could do this in either your model or your controller. Going along with Skinny Controller Fat Model, it might be better to put the functionality in your model. Check out ActiveRecord callbacks.

class MyModel < ActiveRecord::Base
  attr_accessor :start_amount, :end_amount
  before_create :calculate_pickup_amount

  private
    def calculate_pickup_amount
      self.pickupamount = end_amount.to_i - start_amount.to_i
    end
end

Then, in your controller:

def create
  # Assuming params[:my_model] has all the data for initializing a MyModel,
  # including start_amount and end_amount but not pickupamount:
  my_model = MyModel.new(params[:my_model])

  if my_model.save
    # Yay, do something
  else
    # Fail, do something else
  end
end

It might be useful to include the following extension method to Ruby's String class (thanks to sikelianos), perhaps in a file in your Rails app's lib directory:

class String
  def numeric?
    Float self rescue false
  end
end

Then you could perform a check before setting pickupamount:

def calculate_pickup_amount
  if end_amount.numeric? && start_amount.numeric?
    self.pickupamount = end_amount.to_i - start_amount.to_i
  else
    # Throw exception, set some default value, etc.
  end
end
Sarah Vessels
Thanks Sarah, just stumbled across this looking for an answer to a simliar problem. ActiveRecord Callbacks are exactly what I needed to solve my problem.
brad