【问题标题】:Rails has_many through with specific idRails has_many 通过特定的 id
【发布时间】:2020-04-03 14:14:40
【问题描述】:

我正在尝试创建以下内容:

模型:用户、帐户、交易 逻辑:用户有多个帐户。帐户有许多交易。用户通过账户进行了多次交易。

模型

class User < ApplicationRecord
  has_many :accounts
  has_many :transactions, :through => :accounts
End

class Account < ApplicationRecord
  belongs_to :user
  has_many :transactions
end

class Transaction < ApplicationRecord
  belongs_to :account
end

迁移

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.timestamps
    end
  end
end

class CreateAccounts < ActiveRecord::Migration[5.0]
  def change
    create_table :accounts do |t|
      t.string :account_id
      t.belongs_to :user, index:true
      t.timestamps
    end
  end
end

class CreateTransactions < ActiveRecord::Migration[5.0]
  def change
    create_table :transactions do |t|
      t.string :account_id
      t.decimal :amount, :precision => 8, :scale => 2
      t.belongs_to :account, index:true
      t.timestamps
    end
  end
end

我可以使用以下代码为用户创建帐户:

user = User.create(name: "John")
user.accounts.create(account_id: "123")

但是当涉及到交易时,使用相同的逻辑:

user = User.create(name: "John")
user.accounts.create(account_id: "123")
accounts.transactions.create(account_id: "123", amount: 10)

我收到一个错误

NoMethodError: Account 的未定义方法交易

【问题讨论】:

  • 不应该是单个account而不是accounts为其创建交易吗?

标签: ruby-on-rails has-many-through


【解决方案1】:
class CreateTransactions < ActiveRecord::Migration[5.0]
  def change
    create_table :transactions do |t|
      t.string :account_id
      t.belongs_to :account, index:true
    end
  end
end

belongs_to :account 将创建一个名为 account_id 的列,但您在上面的行中已经有了 account_id。将t.string :account_id 更改为t.string :account_name。一般来说,我只使用 _id 作为外键。

【讨论】:

  • 成功了,现在我可以创建交易了!我的印象是,通过添加 has_many_through 关系,我可以使用这样的东西:“user.transactions”,它现在返回一个空数组。
  • user.transactions 应该返回正确的交易。 Rails 对用户实例中的关系事务有一个缓存,并且并不总是知道数据库中的变化。如果您使用user.transactions &lt;&lt; transaction 创建连接表记录,它会知道它,如果您使用Account.create 它不会知道它。您可以使用user.transactions.reload 使缓存无效并强制读取数据库。
【解决方案2】:

我这里有几个问题,

在帐户和交易中,您都有一个字符串列 account_id。在交易中,账户的外键默认也是 account_id 吗?

因此您可能必须为此保留一个差异名称。

你正在调用accounts.transactions,每个账户都有很多交易,所以应该在单个账户对象上调用交易。(Accounts.last.transactions等)

而且我没有看到任何地方定义了帐户(我假设您没有发布那部分代码。 )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-19
    • 2013-11-18
    • 2014-08-15
    • 2011-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多