我已经阅读了大部分有关类似问题的答案,但尚未找到解决方案。代码如下:
设置
class Person < ActiveRecord::Base
# Other inconsequential code
# ...
has_and_belongs_to_many :roles
before_validation: attach_roles
# ...
def attach_roles
roles << Role.default if roles.blank?
end
end
class Role < ActiveRecord::Base
has_and_belongs_to_many: people
def self.default
#
# Get default role
#
end
end
测试
require 'spec_helper'
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
end
describe Person do
context "constructor" do
it "creates a valid Person" do
person = build(:person)
person.should_receive(:attach_roles) # This works
person.valid?
puts person.roles.inspect # Returns []
end
it "creates a another valid Person" do
person = build(:person)
person.valid?
person.should be_valid # This fails
puts person.roles.inspect # Returns []
end
end
end
问题
似乎没有调用attach_roles
回调。但是should_receive
断言是真的
在控制台中
p = FactoryGirl.build(:person)
p.roles # []
p.valid? # true
p.roles # [<Role>]
有人能够解释一下吗?
附注:我们也欢迎尝试创建默认角色的任何其他想法。
的Env :
答案 0 :(得分:1)
您的should_receive
测试证明attach_roles
正在被调用,它只是没有按照您的预期进行。
我认为有两件事让我感到担忧。
一个与@apneadiving指出的相同。
尝试在Ruby中分配实例变量时,必须使用self.roles
。我不确定<< x
的工作原理。如果它是roles= roles + x
之类的语法糖,那么你需要self.roles
,但如果它是roles.insert(x)
那么你就不需要self.roles
。如果有疑问,<<
将始终按照您的期望行事。
我担心的另一件事是你在一个尚未持久化的模型上使用Role
。该操作具有破坏性,并将尝试持久化def attach_roles
roles.build(Role.default)
end
。由于您在第一次创建模型时可能会调用该函数,因此该代码仅在未持久化时才会运行。虽然我觉得它主要起作用,但我不确定这是不是你想要的。我认为你会更好:
Role.default
这假设{{1}}正在返回属性哈希。我对你的意图可能是错的。
我希望有所帮助。