mardi 4 août 2015

Rails transfer form data modification error

I have a form in which I input a transfer. This transfer is stored into a database (and used for a transaction in the controller).

It worked roughly, but now for the finetuning the input needs modification before I save or a transaction is made.

  • The name of the recipient needs to be a transformed into this users id.
  • The amount has a two decimal number input and should be modified to cents by multiplying it by a hundred and making it an integer. Banks need a solid integer basis as you know.

I thought this could work:

Transfer model

  #transfer.rb
  has_one :sender,
          :class_name => "User", 
          :foreign_key => "sender_id"
  has_one :recipient, 
          :class_name => "User", 
          :foreign_key => "recipient_id"

  validates :sender_id, presence: true
  validates :recipient_id, presence: true
  validates :amount, numericality: {:greater_than => 0}

  before_validation :recipient_name_to_id 
  before_validation :amount_to_cents

  def recipient_name_to_id
    recipient = User.find_by_user_name(self.recipient_id)
    self.recipient_id = recipient.id
  end

  def amount_to_cents
    cents = self.amount
    cents = cents*100
    cents.to_i
    self.amount = cents 
  end

To modify the :recipient_id and the :amount taken from the form while the app asks for a name and any number.

It doesn't work, because in the transaction it can't find the recipients banksaldo.

NoMethodError in TransfersController#create

undefined method `cents' for nil:NilClass

 @account_b.cents += @transfer.amount

Everything else works fine. I checked it thoroughly.

But maybe it helps to add the controller

TransfersController

  def create
    @user = User.find(params[:user_id])
    #transfer
    @transfer = Transfer.new(transfer_params)
    @transfer.sender_id = @user.id

    #transactie tussen accounts
    @account_a = @user.account
    @account_b = Account.find_by_user_id(@transfer.recipient_id)
      if @account_a != @account_b
        if @account_a.cents >= @transfer.amount
          Account.transaction do
              @account_a.cents -= @transfer.amount
              @account_a.save!
              @account_b.cents += @transfer.amount
              @account_b.save!
              @transfer.save!
              flash.notice = "Uw opdracht is verzonden."
          end
        else
          flash.notice = "U beschikt niet over voldoende saldo om uw opdracht te doen slagen."
        end
      else
        flash.notice = "U kunt geen geld overmaken naar uw eigen account."
      end
    redirect_to user_path(@user)
  end

  private
  def transfer_params
    params.require(:transfer).permit(:sender_id, :recipient_id, :amount)
  end

Update

I am now working with current setting (is this more clever, or does it not really matter?).

#same transfer.rb model but now with this as non private methods.
def recipient_id=(value)
  user = User.find_by_user_name(value)
  self[:recipient_id] = user.id 
end

def amount=(value)
  cents = value * 100
  cents.to_i
  self[:amount] = cents
end

The code now gives:

Validation failed: Amount is not a number

and can't @transfer.save! in the controller.

Update 2

All right it nearly works. I had to make the value into a float first by to_f. Then it worked... until I turned on the validation again (which I commented out) and now it gives an error that amount is not an integer... Which I state in the def. Hmprff :S

Update 3

It all works now. My methods look like this now:

  def recipient_id=(value)
    user = User.find_by_user_name(value)
    self[:recipient_id] = user.id 
  end

  def amount=(value)
    cents = value.to_f * 100
    self[:amount] = cents.to_i
  end

Bad thing about it is that with wrong form information the app gives it's validation error screen, while I want it to give a notice and redirect it to the show window where it was.

It can't find both methods flash and redirect in these methods I defined above in the transfermodel.

Aucun commentaire:

Enregistrer un commentaire