Ruby Sequel SQLite3 应用程序将有效对象保存到具有 NULL 属性的数据库

Ruby Sequel SQLite3 app saves valid objects to database with NULL attributes

我在我的应用程序上创建新对象时遇到问题。显然,数据在我的 Sequel::Model 和数据库 table 本身之间的某处丢失,导致条目的 ID 和所有属性均为 NULL。

这是我的模型:

class Wallet < Sequel::Model(:wallets)
  attr_accessor :address, :balance

  def validate
    super
    errors.add(:address, "Address can't be empty") if address.empty?
    errors.add(:address, "Input address already exists in the db") unless Wallet.where(address: address).empty?
  end
end

这是创建它的迁移 table:

Sequel.migration do
  change do
    create_table(:wallets) do
      primary_key :id, unique: true
      String :address
      Integer :balance
    end
  end
end

我正在使用 roda 框架。这里是 wallet_app.rb,创建 Wallet 对象的地方:

require 'roda'
require 'sequel'
require 'json'

DB = Sequel.connect('sqlite://database.sqlite3')

class WalletApp < Roda
  require './lib/services/balance_service'
  require './models/account'

  route do |r|
    ...

    r.post "wallets" do
      address = r.params["address"]
      balance = BalanceService.get_balance(address)
      wallet = Wallet.new(address: address, balance: balance)
      # Until here we have the attributes correctly set on wallet object 
      if wallet.valid? && wallet.save
        # Now wallet is persisted in the db with an id but address and balance NULL
        wallet.to_json
      else
        wallet.errors.to_json
      end
    end

  end
end

正如上面 class 中的评论所指出的,对象在插入数据库之前是有效的,并且属性设置正确。尽管如此,数据仍保留为所有属性 NULL。我假设迁移或模型定义中有错误,但我找不到任何错误。

如果有帮助,我也将我的 Gemfile 复制到这里:

source "https://rubygems.org"

ruby '2.1.2'

gem 'roda'
gem 'sequel'
gem 'sqlite3'
gem 'httparty'

提前致谢

我习惯了 ActiveRecord 和 Rails,但根据 Sequel documentation 你可以使用 validation_helpers plugin:

# model
class Wallet < Sequel::Model
  # plugin :validation_helpers
  def validate
    super
    validates_presence [:address, :balance], allow_nil: false
    validates_unique :address
  end
end

您最终可以在迁移中的地址列上设置唯一性约束,而不是在模型中进行唯一性验证。 这种方法应该可以防止自定义验证的一些副作用(尽管你的似乎不是假的)

您应该删除 attr_accessor :address, :balance,那是破坏性的东西。 Sequel::Model 将属性存储在 values 散列中,而不是作为单独的实例变量。