gpt4 book ai didi

ruby-on-rails - 模型实例方法第一次运行返回错误结果,随后返回正确结果

转载 作者:行者123 更新时间:2023-12-04 02:22:18 24 4
gpt4 key购买 nike

我有三个模型,与 has_many 相关:通过关联:

class Account < ApplicationRecord
has_many :account_owners
has_many :employees, through: account_owners

def is_owned_or_belongs_to_team_of_employees(employee)
employee.team.any? { |m| employees.include?(m) }
end
end

class AccountOwner < ApplicationRecord
belongs_to :account
belongs_to :employee
end

class Employee < ApplicationRecord
has_many :account_owners
has_many :accounts, through: :account_owners

def team
self.class.where(
'id IN (?)',
self. class.find_by_sql(['WITH RECURSIVE search_tree(id, path) AS (
SELECT id, ARRAY[id]
FROM employees
WHERE id = ?
UNION ALL
SELECT employees.id, path || employees.id
FROM search_tree
JOIN employees ON employees.manager_id = search_tree.id
WHERE NOT employees.id = ANY(path)
)
SELECT id FROM search_tree ORDER BY path',
self.id])
).order(:id)
end
end

我正在开发环境中的 Rails 控制台中手动测试 Account#is_owned_or_belongs_to_team_of_employees方法。

当我在控制台中运行该方法时,会发生以下情况:
> a = Account.first
=> #<Account id: 534788375, name: "Sales Rep 1 (elena)-owned account", code: "EEE", created_at: "2018-07-15 09:41:55", updated_at: "2018-07-15 09:41:55">
> e = Employee.find_by(first_name: 'Elena')
=> #<Employee id: 701979064, first_name: "Elena", last_name: "López", manager_id: 1069403509, created_at: "2018-07-15 09:41:55", updated_at: "2018-07-15 09:41:55", mobile: nil, work: nil>
> e.team
=> #<ActiveRecord::Relation [#<Employee id: 701979064, first_name: "Elena", last_name: "López", manager_id: 1069403509, created_at: "2018-07-15 09:41:55", updated_at: "2018-07-15 09:41:55", mobile: nil, work: nil>]>
> a.is_owned_or_belongs_to_team_of e
=> nil
> a.is_owned_or_belongs_to_team_of e
=> true

如您所见,该方法返回 nil (错误!)第一次,返回 true (正确!)以下时间。

令人惊奇的是,如果我定义这样的方法,我可以纠正问题:
def is_owned_or_belongs_to_team_of employee
puts "employees are #{employees.inspect}"
employee.team.any? { |m| employees.include?(m) }
end

现在执行是正确的,并且该方法始终返回相同的结果(在我的示例中为 true):
> a = Account.first
=> #<Account id: 534788375, name: "Sales Rep 1 (elena)-owned account", code: "EEE", created_at: "2018-07-15 09:41:55", updated_at: "2018-07-15 09:41:55">
> e = Employee.find_by(first_name: 'Elena')
=> #<Employee id: 701979064, first_name: "Elena", last_name: "López", manager_id: 1069403509, created_at: "2018-07-15 09:41:55", updated_at: "2018-07-15 09:41:55", mobile: nil, work: nil>
> e.team
=> #<ActiveRecord::Relation [#<Employee id: 701979064, first_name: "Elena", last_name: "López", manager_id: 1069403509, created_at: "2018-07-15 09:41:55", updated_at: "2018-07-15 09:41:55", mobile: nil, work: nil>]>
> a.is_owned_or_belongs_to_team_of e
=> true
> a.is_owned_or_belongs_to_team_of e
=> true

如果我删除 puts声明,我们回到第一方:方法返回 nil第一次, true以下时间。

而且,令人惊讶的是,如果我保留 puts声明,但删除 inspect (也就是说,我只是做 puts "employees are #{employees}" 我们也回到了第一阶段: nil 第一次, true 下一次。

任何的想法?这里发生了什么?

顺便说一句,我正在运行 Ruby 2.5.1 和 Rails 5.2.0。

最佳答案

我很高兴我偶然发现了这只 unicorn 的 bug !

在调试了几个小时后,我发现了以下内容:

  • any? rails 5.2 release 有新变化应该将其委托(delegate)给 Enumerable
  • 令人惊讶的是,如果您在 any? 的实现中放置一个 binding.pry并调用super它甚至第一次返回true,然后该方法返回nil . ~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.0/lib/active_record/relation.rb @ line 228 ActiveRecord::Relation#any?:
  • 如果您添加到 employee.team .to_a一切正常。
  • 如果你把 any? { |_| true }它返回真。
  • 如果您检查 block 内的值 include?它返回 true 但 any?仍然返回 nil !!!
  • 如果您避免解决 has_may through关联(通过在 block 之前调用 .to_a)甚至在 any? 中使用不同的关联阻止一切按预期工作。
  • 使用任何其他 ruby​​ 版本可以解决问题。

  • 概括

    该问题是在 ruby​​ 2.5.1 中引入的 rails v5.2.0ActiveRecord::Relation开始包括 Enumerable .它发生在 %w(none? any? one? many?)在尝试解决 has many through 时关联在其 block 中。

    关于ruby-on-rails - 模型实例方法第一次运行返回错误结果,随后返回正确结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51347748/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com