【问题标题】:Can't access attributes through Has many无法通过 Has many 访问属性
【发布时间】:2017-02-26 10:58:19
【问题描述】:

试图简化我的模型以显示重要的东西似乎缺少的东西让我知道。

在我看来,我正在尝试通过@session.owner 访问会话的所有者。所有者与与会者相关联,所有与会者都通过has_many 与会话相关联。

self.attendees 似乎没有返回任何记录。我确定我遗漏了一些明显的东西。如果您能提供帮助,请提前致谢!

干杯, 泰勒

会话模型

class Session < ApplicationRecord
  has_many :attendees

  def owner
    self.attendees.each do |attendee|
      if attendee.role == "Owner"
        "#{attendee.user_id}"
      end
    end
  end

end

参会者模型

class Attendee < ApplicationRecord
  belongs_to :session

end

【问题讨论】:

标签: ruby-on-rails has-many


【解决方案1】:

有几件事很突出。首先,您实现owner 方法的方式不是很有效,必须查询每条记录并检查角色属性。可以使用 Active Record 关联方法定义关联。例如。您可以在声明关联时定义范围。

为了调查您的问题,即session.attendees 没有返回任何记录,我建议如下:

  1. 验证您是否遵循 Rails 约定并具有正确的参考列。 Attendee 应该有 session_id 列。
  2. 编写一些规范,或者至少加载 Rails 控制台并通过创建一些测试记录并查看返回的一些记录来验证您的 has_many :attendees 关联是否按预期工作。这很可能会揭示您的代码存在的任何问题。

接下来,使用活动记录关联声明您的“会话拥有所有者”关联。在这里想想你想要什么:session.owner 应该返回参加者记录还是用户记录(在我们的示例中,您表示参加者属于用户?)假设session.owner 返回参加者记录,您的关联可能如下所示: has_one :owner, -&gt; { where role: 'Owner' }, class_name: 'Attendee'。 (请注意,这是一个未经测试的示例)。

有关 has_one 关联的更多信息,请参阅http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_one

【讨论】:

  • 感谢您的洞察力。这是个好的观点!我假设我可以以类似的方式进一步定义其他会话,例如 session.admin、session.member?我还为 Role 留下了一个模型以保持简单。我的参加者模型有一个引用角色模型的 role_id 列。关于如何链接的更多见解?我可以去哪里 role_id == '1' 从另一个 sql 调用中提取 1 还是有更简单的方法来解决这个问题?
  • 是的,你可以这样做。此外,您可以调整关联范围以处理更复杂的角色关联。尝试一下活跃的记录关联,看看你是否能弄清楚。这是一条线索 - 关联范围可以包含任何活动记录查询接口方法,例如has_one :owner, -&gt; { joins(:role).where(roles: {name: 'Owner'}) }。见guides.rubyonrails.org/active_record_querying.html
【解决方案2】:

在您的情况下,each 将在找到 owner 后继续工作,并将返回 nil

class Session < ApplicationRecord
  has_many :attendees

  def owner
    user_id = nil
    self.attendees.each do |attendee|
      if attendee.role == "Owner"
        user_id = "#{attendee.user_id}"
        break
      end
    end

    user_id
  end

end

我已重写您的代码以使用sql 方法来查找owner

class Session < ApplicationRecord
  has_many :attendees

  def owner
    self.attendees.find_by(role: "Owner").try(:user_id)
  end
end

【讨论】:

  • Hrm... 仍然没有运气。它返回一个空白值。我可以看到 SQL 命令在我的终端中正确发生,当我在工作台中运行它时,记录就在那里。它只是不想在我的应用中提供价值¯\_(ツ)_/¯
  • 这项工作最终导致我的数据库出现了一些问题,或者我已经解决了一些问题。
  • 值得注意的是,在命名方法时考虑它正在做什么以及返回什么是一种很好的做法。在上面的示例中,owner 方法返回了错误的数据类型,即用户 id。我们希望session.owner 返回所有者对象,因此允许菊花链,例如session.owner.name。例如,如果您打算返回 id,则该方法应命名为 session.owner_id,就像 session.owner? 将返回一个布尔值一样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-09-27
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多