railsで、ポイント（数量）を使う（支払う）機能をつくっており、  
支払量をバリデーションしたいと考えています。

具体的には、 **支払量が支払ユーザーの口座残高以下ならバリデーション成功とみなし、BankAccountモデルのbalance(残高)を更新したい**
と思っています。  
（残高が1000なら、支払量は1000までならモデル更新。支払量1001以上となり残高がマイナスになってしまうならばモデルは更新しない）

あらかじめ決まった数値なら

```

    validates :amount, numericality: {only_integer: true, less_than_or_equal_to: 5000}
    
```

みたいにすればいいと思うのですが、  
今回の様に **更新され変化し続ける残高の数値をバリデーションに使う** にはどうすればいいのでしょうか？

テーブルの状況

```

    create_table "bank_accounts", force: :cascade do |t|
      t.integer "user_id"
      t.string "account_number"
      t.decimal "balance"
      t.datetime "created_at", null: false
      t.datetime "updated_at", null: false
      t.index ["user_id"], name: "index_bank_accounts_on_user_id"
      end
    
```

User(会員）モデル。※deviseで管理しています。

```

    class User < ApplicationRecord
      has_one :bank_account
      devise :database_authenticatable, :registerable,
           :recoverable, :rememberable, :trackable, :validatable
    end
    
```

BankAccount（口座）モデル。

```

    class BankAccount < ApplicationRecord
    #BankAccountはuserから1:1の関係で所有されている
    belongs_to :user
    
    #口座残高は数値か小数点のみ有効
    validates :balance, presence: true, numericality: true
    end
    
```

入力フォーム

```

    <%= form_for @account_transaction do |f|%>
    <div class="field">
      <%= f.label :支払量 %>
      <%= f.number_field :amount,min:1,max:9999999 %>
      <%= f.submit"確認" %>
    </div>
    <% end %>
    
```
CC BY-SA 3.0
2017-12-15T11:32:08.890
40306
2021-05-05T00:51:09.657
2021-05-05T00:51:09.657
19110
26666
question
ruby-on-rails ruby バリデーション
railsで変化し続けるカラム（数値）をバリデーションに使いたい
標準のバリデータでは機能が不足する場合、バリデータを自分で実装することができます。

簡単には、

```

    class なんとか < ApplicationRecord
      belongs_to :user
      validate :check_balance
    
      private
      def check_balance
        errors.add(:amount, "残高が不足しています") if amount > user.bank_account.balance
      end
    end
    
```

こんな感じです。

詳しくは[リファレンス](http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-
i-
validate)や[Railsガイド](https://railsguides.jp/active_record_validations.html#%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%92%E5%AE%9F%E8%A1%8C%E3%81%99%E3%82%8B)を見てください。
CC BY-SA 3.0
2017-12-16T00:44:40.273
40316
2017-12-16T00:44:40.273
5793
40306
answer
質問の意図（変化し続ける値をバリデーションに使いたい）から離れるかもしれませんが、  
最終的に実現したい「残高以下の支払量のみ有効」という結果を引き起こすことができます。

「残高以下の支払量のみ有効」ということは、  
言い換えるならば「残高を超える支払をして、残高をマイナスにしたくない（残高はプラスか０でなければならない）」、  
即ち「残高が０以上なら検証成功」というシンプルで標準的なバリデーションでも解決することができました。

```

    class BankAccount < ApplicationRecord
      #BankAccountはuserから1:1の関係で所有されている
      belongs_to :user
    
      #口座残高は数値か小数点であり、計算の結果、指定値0.00以上になる（残高がマイナスにならない）なら検証成功
      validates :balance, presence: true, numericality: {greater_than_or_equal_to: 0.00}
    end
    
```
CC BY-SA 3.0
2017-12-16T23:17:16.627
40331
2017-12-17T03:26:42.667
2017-12-17T03:26:42.667
26666
26666
40306
answer