'undefined method `money' for #<ActiveRecord::Relation [#<Account id: nil, money: 400.0>]>

NoMethodError in AccountsController#update
undefined method `money' for #<ActiveRecord::Relation [#<Account id: nil, money: 400.0>]>

I'm tring to get a value from database and compare to another.
After compere I want to sum then update.
Ex: Value from money database is 4000
money_to_take is 1000
if money is >= money_to_take then money = money - money_to_take update the money value with 3000.

I do not know correctly where do I have to put this code.

Can some one help me how to solve this problem? Help me please!

model/account.rb

class Account < ApplicationRecord
  belongs_to :user
  enum status: {blocked: "blocked", activated: "activated"}

  validates :number, presence: true, uniqueness: true 
  validates :money, presence: true, length: {minimum:1}

   def self.update_withdraw_money(account_number, money_to_take) 
      account = select(:money).where(number:account_number)
      if account.money >= money_to_take
      @account.money -= money_to_take 
      end
   end

end

This is the error line

if account.money >= money_to_take

Controllers/accounts_controller.rb


  def withdraw
    @account = Account.where(params[:number]).first
    account = @account
    account.money = 0.0;
    @account_withdraw = account

    logger.debug {"Last acount attributes hash: #{@account_withdraw.attributes.inspect}"}
  end


  def update

    Account.update_withdraw_money(@account.number, @account.money)

    respond_to do |format|
      if @account.update(account_params)
        format.html { redirect_to account_url(@account), notice: "Account was successfully updated." }
        format.json { render :show, status: :ok, location: @account }
      else
        format.html { render :edit, status: :unprocessable_entity }
        format.json { render json: @account.errors, status: :unprocessable_entity }
      end
   end
  end

    def account_params
      params.require(:account).permit(:money, :status)
    end


account table

class CreateAccounts < ActiveRecord::Migration[7.0]
  def change
    create_table :accounts do |t|
      t.integer :number, default: 10000
      t.float :money, default: 0.5
      t.string :status, default: "activated"
      t.references :user, null: false, foreign_key: true

      t.timestamps
    end
  end
end

accounts/withdraw.html.erb

<h1>Withdraw from my account</h1>

<%= render "accounts/form", account: @account_withdraw%>

accounts/_form

<%= form_with(model: account) do |form| %>
  <% if account.errors.any? %>
    <div style="color: red">
      <h2><%= pluralize(account.errors.count, "error") %> prohibited this account from being saved:</h2>

      <ul>
        <% account.errors.each do |error| %>
          <li><%= error.full_message %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <div>
    <%= form.label :money, style: "display: block" %>
    <%= form.text_field :money %>
  </div>

  <div>
    <%= form.hidden_field :status, value: "activated" %>
  </div>

  <div>
    <%= form.submit %>
  </div>
<% end %>

Use this address to access application http://127.0.0.1:3000/accounts/1000/withdraw .
Here is my code in github https://github.com/Vicente-jpro/negocial-app



Solution 1:[1]

Something like this

def self.update_withdraw_money(account_number, money_to_take) 
  account = find_by(number: account_number)

  if account.money >= money_to_take
    account.decrement!(:money, money_to_take)
  end
end

After that you need @account.reload in the controller, because record is updated

And may be you need to wrap these updates into transaction

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 mechnicov