【问题标题】:Access parent in scope访问范围内的父级
【发布时间】:2013-01-31 21:59:51
【问题描述】:

我有一个具有简单层次结构的 rails 3.2 应用程序:一个用户有很多客户,一个客户有很多发票。

我希望用户只能通过Client.by_user(current_user)Invoice.by_user(current_user) 使用范围查看他们自己的客户和发票。对于客户,我有这个,效果很好:

scope :by_user, lambda { |user| where(user_id: user.id) }

但是,如果我尝试对发票进行相同操作

scope :by_user, lambda { |user| where(client.user_id => user.id) }

失败了,告诉我undefined local variable or method 'client'

我做错了什么?我不想将 user_ids 添加到发票中。

【问题讨论】:

  • 为什么不直接使用current_user.clientscurrent_user.invoices? (编辑:假设Userhas_many :invoices, :through => :clients
  • 我试过了,但它无法识别invoice.user。我是否必须为此将 user_id 添加到 invoices 表中?
  • 你不应该。您也可以在 Invoice belongs_to :user, :through => :client 处进行逆关系。
  • 附注我最初的怀疑是,这也可能是您的范围出了问题——您是否在 ClientInvoice 模型上设置了反向 belongs_to 关系?

标签: ruby-on-rails scope associations rails-activerecord


【解决方案1】:

正如@gregates 在 cmets 中所说,最好为用户、客户和发票模型定义关联,然后使用 user.clientsuser.invoicesinvoice.user 等:

class User < ActiveRecord::Base
  has_many :clients
  has_many :invoices, through: :clients
end

class Client < ActiveRecord::Base
  belongs_to :user
  has_many :invoices
end

class Invoice < ActiveRecord::Base
  belongs_to :client
  has_one :user, through: :client
end

但如果您更喜欢有范围的想法,您应该将客户表加入您范围内的发票:

class Invoice < ActiveRecord::Base
  ...
  scope :by_user, lambda { |user| joins(:client).where("clients.user_id = ?", user.id) }
  ...
end

【讨论】:

  • belongs_to :userInvoice 模型上,但是,需要user_id 外键,不是吗?你需要through: :client
  • @gregates,正如我在api docs 中看到的那样,belongs_to 没有 :through 选项。
  • 我已经实现了上述操作,但是在创建了属于客户和用户的发票之后,invoice.user 给了我nil - 怎么会?
  • 对不起,你是对的。我以为我以前做过,但实际上我们使用了has_one :through。 @Charles 在您的 Invoice 模型上尝试 has_one :user, through: :client
  • 太棒了,成功了!我已经相应地编辑了答案。谢谢你们两个!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-20
  • 2011-07-03
  • 1970-01-01
  • 1970-01-01
  • 2022-08-16
  • 1970-01-01
相关资源
最近更新 更多