【问题标题】:Why does this Rails association shortcut fail? What is the correct way?为什么这个 Rails 关联快捷方式会失败?正确的方法是什么?
【发布时间】:2012-03-12 21:49:11
【问题描述】:

在给定的情况下,用户可以:

  • 邀请许多受邀者 (has_many :invitations)
  • 接受一个邀请(has_one :invitation)

根据http://guides.rubyonrails.org/association_basics.html#the-has_many-through-associationhas_many :through 关联应该允许我使用类似于以下功能测试中的快捷方式。

但是,它失败并出现注释中指出的错误。

来自功能测试的sn-p:

assert_difference('Invitation.count') do # WORKS
  post :create, :user => { :email => invitee_email, :password => "1password" }
end

@invitee = User.find_by_email(invitee_email)
@invitation = Invitation.find_by_issuer_id_and_invitee_id(@issuer.id, @invitee.id)
assert @invitation.valid? # WORKS
assert_present @invitation.issuer # WORKS
assert_present @invitation.invitee # WORKS

# TODO: repair
assert_present @issuer.invitees # FAILS with "[] is blank"
assert_present @invitee.issuer # FAILS with "nil is blank"

来自被测方法的sn-p:

@issuer.create_invitation(:invitee => @invitee, :accepted_at => Time.now)
# tested as well - also fails the test:
# Invitation.create!(:issuer => @issuer, :invitee => @invitee, :accepted_at => Time.now)

invitation.rb 的相关部分:

belongs_to :issuer, :class_name => "User"
belongs_to :invitee, :class_name => "User"

validates_presence_of :issuer
validates_presence_of :invitee

user.rb 的相关部分:

has_many :invitations, :foreign_key => 'invitee_id', :dependent => :destroy
has_many :invitees, :through => :invitations
has_one :invitation, :foreign_key => 'issuer_id', :dependent => :destroy
has_one :issuer, :through => :invitation

现在我想知道:

  • 什么是正确的“快捷方式”?
  • 首先我的模型设置是否正确?

【问题讨论】:

    标签: ruby-on-rails associations has-many-through functional-testing has-one


    【解决方案1】:

    我猜你正在尝试设计这样的逻辑: 用户1可以邀请用户2,用户3,则数据为:

    issuer_id, invitee_id
    1,         2
    1,         3
    

    假设用户2接受了邀请,数据变为:

    issuer_id, invitee_id
    1,         2
    1,         3
    2,         1
    

    如果用户 2 稍后邀请用户 1 怎么办?如果我猜对了,你的设计就行不通了。

    我认为您对关联也有一些误解。 has_many :invitations, :foreign_key => 'invitee_id' 表示用户作为受邀者收到了很多邀请。而has_one :invitation, :foreign_key => 'issuer_id' 表示用户作为发布者发送了邀请。

    【讨论】:

    • 在我的用例中,邀请在新用户注册时创建。因此如果用户 2 接受邀请,以下内容将转到 DB:issuer_id=1, invitee_id=2。如果他从不接受,应用程序根本就不会知道他。但是,我认为您对 :foreign_key 的看法是正确的!当我交换它们时,突然没有创建邀请 ("Invitation.count" didn't change by 1.) - 我目前无法看到原因。
    • 似乎还缺少什么(更正 :foreign_key's 之后)将@issuer 包含在 create_invitation 的属性/参数中:@987654327 @ --- 我原本希望 Rails 知道 :issuer => @issuer, 部分,因为我首先从 @issuer 调用该方法。显然那是错误的。感谢您的帮助!
    • 添加:刚刚注意到它应该是@invitee.create_invitation(而不是@issuer.create_invitation)。否则,受邀者 (!) 的集合将被覆盖。
    猜你喜欢
    • 1970-01-01
    • 2010-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多