在Rails 4.2.10上,我有以下模型:
class RegistrationApproval < ActiveRecord::Base
belongs_to :registering_user, class_name: 'User', inverse_of: :registration_approvals
belongs_to :approver, class_name: 'User', inverse_of: :approved_registrations
end
在我的User
模型中,我有这个:
has_many :registration_approvals, foreign_key: 'registering_user_id', dependent: :destroy, inverse_of: :registering_user
has_many :registration_approvers, through: :registration_approvals, class_name: 'User', source: :approver, inverse_of: :registering_users
has_many :approved_registrations, class_name: 'RegistrationApproval', foreign_key: 'approver_id', dependent: :destroy, inverse_of: :approver
has_many :registering_users, through: :approved_registrations, class_name: 'User', inverse_of: :registration_approvers
def approve_registration(approver)
registration_approvals.create(approver: approver)
Rails.logger.debug "approvers: #{registration_approvers.length}"
return [registration_approvers.size, registration_approvers.count]
end
在approve_registration
方法中,调试语句更改该方法的输出。如果没有debug语句,则用户registration_approvers.size
有两个批准的情况将按您的期望评估为2
,但使用debug语句,则评估为1
。为什么会这样?这是Rails 4.2中的错误吗?
count
评估不受影响。
似乎是对registration_approvers.length
的调用导致了size
这是我失败的测试,显示了此问题:
it 'should have size and count equal' do
registering_user = FactoryBot.create(:user)
_(registering_user).must_be :persisted?
approver1 = FactoryBot.create(:user)
_(approver1).must_be :persisted?
approver2 = FactoryBot.create(:user)
_(approver2).must_be :persisted?
registering_user.approve_registration(approver1)
size, count = registering_user.approve_registration(approver2)
_(count).must_equal 2
_(size).must_equal 2
end
除了size
为1
以外最后一行中失败的断言,测试中的所有断言都通过。从registration_approvers.length
方法中删除对approve_registration
的调用后,测试通过。
这对我来说是个问题,因为在approve_registration
方法中,我想用registration_approvers
遍历each
,但是当我这样做时,它错过了集合中的最后一个,大概是因为each
方法在集合上调用length
,并更改size的值,然后以为已到尽头就退出循环。
如果我可以找到一种无需调用length
即可遍历该集合的变通方法,那会有所帮助。
答案 0 :(得分:2)
#size
在加载查询结果see the doc's code snippet时使用#length
值。
#length
不会触发新查询,而只是在(先前获得/缓存的)结果数组上调用#length。
OTOH:#count
确实触发了一个新查询(实际上是在尚未加载结果时第一次触发该查询。
因此,要修复测试,您可以主动重新加载对象,从而刷新结果的缓存:
registering_user.approve_registration(approver1)
registering_user.reload
size, count = registering_user.approve_registration(approver2)
此外,我认为最好不要依赖动作的返回值进行统计。
答案 1 :(得分:0)
请记住,registration_approvers是ActiveRecord::Association对象,但我认为该类中没有定义长度,它可以从父级继承...
我认为查询的结果是数组,所以我不认为该长度是在该类中定义的,它可以从父级继承...我相信查询的结果是arrays
这是该方法的ruby源代码
static VALUE
rb_ary_length(VALUE ary)
{
long len = RARRAY_LEN(ary);
return LONG2NUM(len);
}
我需要您的一些意见/反馈