为什么“每个”是“每个”?迭代器方法中断 rspec?
背景
我正在尝试测试我的模型。
app/models/user.rb
class User < ActiveRecord::Base
has_many :payor_transactions, class_name: 'Transaction', inverse_of: :payor, foreign_key: :payor_id
has_many :payee_transactions, class_name: 'Transaction', inverse_of: :payee, foreign_key: :payee_id
def transactions
transactions = Transaction.where(["payor_id=? OR payee_id=?", self.id, self.id])
transactions
end
end
app/models/transaction.rb
class Transaction < ActiveRecord::Base
attr_accessor :user
belongs_to :payor, class_name: 'User'
belongs_to :payee, class_name: 'User'
end
在 Transactions 类中,@user 是表示访问模型的用户的临时对象实例。
spec/models/user_spec.rb
require 'spec_helper'
describe User do
let(:user) { Factory(:user) }
let(:user2) { Factory(:user) }
let(:user3) { Factory(:user) }
let(:transaction_user_user2) { Factory(:transaction, payor: user, payee: user2) }
let(:transaction_user2_user) { Factory(:transaction, payor: user2, payee: user) }
let(:transaction_user2_user3) { Factory(:transaction, payor: user2, payee: user3) }
describe ".transactions" do
it "should include payor and payee transactions but not 3rd party transactions" do
user.transactions.should == [transaction_user_user2, transaction_user2_user]
user2.transactions.should == [transaction_user_user2, transaction_user2_user, transaction_user2_user3]
user3.transactions.should == [transaction_user2_user3]
end
end
end
使用 rspec 2.6.4、factory_girl 2.1.2、rails 3.1.0、ruby 1.9.2p290。如图所示,规范通过。
当我修改 app/models/user.rb 中的 transactions
方法以迭代结果时出现问题
,使其显示为:
class User < ActiveRecord::Base
has_many :payor_transactions, class_name: 'Transaction', inverse_of: :payor, foreign_key: :payor_id
has_many :payee_transactions, class_name: 'Transaction', inverse_of: :payee, foreign_key: :payee_id
def transactions
transactions = Transaction.where(["payor_id=? OR payee_id=?", self.id, self.id])
transactions.each {|transaction| transaction.user = self}
transactions
end
end
the method transactions
now在 rspec 中返回 []
,但它在应用程序视图中完美运行。
由于 Transaction.user 是临时的(表示访问事务的用户),因此每次从数据库记录初始化或构建事务时都必须设置它(如果存在)。
我不知道从哪里开始调试这个。
感谢所有建议!
Background
I'm attempting to test my models.
app/models/user.rb
class User < ActiveRecord::Base
has_many :payor_transactions, class_name: 'Transaction', inverse_of: :payor, foreign_key: :payor_id
has_many :payee_transactions, class_name: 'Transaction', inverse_of: :payee, foreign_key: :payee_id
def transactions
transactions = Transaction.where(["payor_id=? OR payee_id=?", self.id, self.id])
transactions
end
end
app/models/transaction.rb
class Transaction < ActiveRecord::Base
attr_accessor :user
belongs_to :payor, class_name: 'User'
belongs_to :payee, class_name: 'User'
end
In the Transactions class, @user is an ephemeral object instance representing the user accessing the model.
spec/models/user_spec.rb
require 'spec_helper'
describe User do
let(:user) { Factory(:user) }
let(:user2) { Factory(:user) }
let(:user3) { Factory(:user) }
let(:transaction_user_user2) { Factory(:transaction, payor: user, payee: user2) }
let(:transaction_user2_user) { Factory(:transaction, payor: user2, payee: user) }
let(:transaction_user2_user3) { Factory(:transaction, payor: user2, payee: user3) }
describe ".transactions" do
it "should include payor and payee transactions but not 3rd party transactions" do
user.transactions.should == [transaction_user_user2, transaction_user2_user]
user2.transactions.should == [transaction_user_user2, transaction_user2_user, transaction_user2_user3]
user3.transactions.should == [transaction_user2_user3]
end
end
end
Using rspec 2.6.4, factory_girl 2.1.2, rails 3.1.0, ruby 1.9.2p290. As shown, the spec passes.
Problem
When I modify the transactions
method in app/models/user.rb to iterate over the results such that it reads:
class User < ActiveRecord::Base
has_many :payor_transactions, class_name: 'Transaction', inverse_of: :payor, foreign_key: :payor_id
has_many :payee_transactions, class_name: 'Transaction', inverse_of: :payee, foreign_key: :payee_id
def transactions
transactions = Transaction.where(["payor_id=? OR payee_id=?", self.id, self.id])
transactions.each {|transaction| transaction.user = self}
transactions
end
end
the method transactions
now returns []
in rspec, however it works perfectly in the app views.
Since Transaction.user is ephemeral (representing the user accessing the transaction) it must be set (if it exists) every time a Transaction is initialized or built from db records.
I'm at a loss for where to begin to debug this.
All suggestions appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
我认为你的问题在于
let
是懒惰的。基本上发生的情况是,当在测试中调用transactions
方法时,事务甚至还没有创建。使用let!
作为非惰性版本。有关更多信息,请参阅 let 和 let!细节。I think your problem lies in the fact that
let
is lazy. Basically what is happening is that the transactions are not even created yet when thetransactions
method is called in the test. Uselet!
for a non-lazy version. See let and let! for more details.您不能只返回 payor_transactions + payee_transactions 而不是手动选择它们吗?
Couldn't you just return payor_transactions + payee_transactions instead of manually selecting them?
根据 @obrok 的建议,我决定在其他测试中保留延迟加载
let
优势的解决方案是在测试 User#transactions 之前触摸每个事务,如下所示:Following the suggestion from @obrok, the solution I settled on to retain the advantage of lazy-loading
let
in other tests was to touch each transaction before testing User#transactions as so: