我是ActiveRecord协会的新手。我正在草拟一个应用程序,该应用程序可以跟踪在一组用户中欠谁的钱。 Expense
模型和User
模型似乎是自然选择,我只是不确定如何定义两者之间的关系。例如,我想跟踪债权人(“所有者”)和每笔费用的债务人,但这实际上只是两个回到用户的外键。此外,每个用户可以有多种费用(作为债权人和债务人)我到目前为止对协会的最佳猜测是:
class Expense
# belongs_to or has_one here?
# Not sure about class => User syntax:
# need to alias to foreign keys that reference the same model
belongs_to :creditor, :class => User
belongs_to :debtor, :class => User
class User
# has_many expenses defines a creditor relationship (user owns expense)
# how to define debtor relationship? (belongs_to...?)
has_and_belongs_to_many :expenses
我已经阅读了关于关联的Rails指南,但我仍然在外键和连接表上相当丢失。任何意见都非常感谢!
答案 0 :(得分:23)
所以这肯定不是多对多关系的has_and_belongs_to_many
。您只需要使用几个has_many
关系。我认为它应该看起来像这样:
编辑:哎呀我有点不好意思让我再来一次:
class Expense
# make sure expense table has 'creditor_id' and 'debtor_id' rows
belongs_to :creditor, :class_name => "User", :foreign_key => :creditor_id
belongs_to :debtor, :class_name => "User", :foreign_key => :debtor_id
class User
has_many :debts, :class_name => "Expense", :foreign_key => :debtor_id
has_many :credits, :class_name => "Expense", :foreign_key => :creditor_id
答案 1 :(得分:18)
其他答案告诉你你需要做什么,但是对于那些刚接触Rails的人来说,这可能会让我感到困惑,因为我将所有这些东西拼凑在一起,所以这里有一个完整的解决方案,包括两个迁移和模特。
另外,作为旁注:我更倾向于贷款,贷款人和借款人,费用,债权人和债务人,或债务,债权人和债务人。主要是因为费用含糊不清,债务与债务人太相似。但 并不重要;只是做对你有意义的事情,因为你将维护你的代码。
class CreateLoans < ActiveRecord::Migration
create_table :loans do |t|
def up
t.references :lender
t.references :borrower
end
end
end
此处指定此表中有两列将被称为:lender和:borrower,它们包含对另一个表的引用。 Rails实际上会为你创建名为'lender_id'和'borrower_id'的列。在我们的例子中,他们将每个引用Users表中的行,但我们在模型中指定,而不是在迁移中。
class Loan < ActiveRecord::Base
belongs_to :lender, class_name => 'User'
belongs_to :borrower, class_name => 'User'
end
在这里,您要在Loan模型上创建一个名为:lender的属性,然后指定此属性与User类相关。看到'belongs_to'的Rails将在loan表中查找一个名为'lender_id'的列,我们在上面定义了这个列,并使用它来存储外键。然后你为借款人做了同样的事情。
这将允许您通过贷款模型的实例访问您的贷方和借款人,这两个用户模型的实例,如下所示:
@loan.lender # Returns an instance of the User model
@loan.borrower.first_name # Returns a string, as you would expect
作为旁注:在这种情况下,'belongs_to'命名法具有不错的意义,但在其他地方可能会有点混乱。请记住,它始终用于包含外键的任何内容。
class User < ActiveRecord::Base
has_many :loans_as_lender, :class_name => 'Loan', :foreign_key => 'lender_id'
has_many :loans_as_borrower, :class_name => 'Loan', :foreign_key => 'borrower_id'
end
在这里,您要在User模型上创建一个名为:loans_as_lender的属性,指定此属性与Loan模型相关,并且Loan模型上与此属性相关的外键称为“lender_id”。然后你正在做同样的事情:loans_as_borrower。
这使您可以获得用户是贷款人或借款人的所有贷款,如下所示:
@address.loans_as_lender
@address.loans_as_borrower
执行其中任何一项操作都会返回Loan模型的实例数组。
答案 2 :(得分:1)
如果费用迁移如下:
create_table :expenses do |t|
t.integer :creditor_id, :null => false
t.integer :debtor_id, :null => false
# other attributes here
end
然后您的费用模型就足够了。如果您查看documentation for belongs_to,您会看到它会正确地将外键推断到用户表中:
:foreign_key
指定用于关联的外键。默认情况下,这被认为是具有“_id”后缀的关联的名称。所以 定义belongs_to:person关联的类将使用 “person_id”作为默认值:foreign_key。同样,belongs_to :favorite_person,:class_name =&gt; “人”将使用外键 “favorite_person_id”。
因此,您无需在此明确指定外键。如果您在费用模型中对ID使用其他命名约定,则需要在关联中明确指定它们。
对于您的用户模型,您与费用之间没有多少关系 - 费用总是属于一个债务人而且恰好属于一个债权人。所以你需要的只是两个has_many关联:
has_many :debts, :class_name => 'Expense', :foreign_key => :debtor_id
has_many :credits :class_name => 'Expense', :foregin_key => :creditor_id