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