有两个这样的类:
class Site < ActiveRecord::Base
has_one :subscription, dependent: :destroy
def self.hostname_active?(hostname)
site = where(hostname: hostname)
site.exists? && site.first.active?
end
def active?
subscription.active?
end
end
class Subscription < ActiveRecord::Base
belongs_to :site
def active?
(starts_at..ends_at).cover?(Date.current)
end
end
describe Site do
let(:site) { Fabricate.build(:site) }
describe "#hostname_active?" do
it "Returns true if site with hostname exists & is active" do
described_class.stub_chain(:where, :exists?).and_return(true)
described_class.stub_chain(:where, :first) { site }
site.stub(:active?).and_return(true)
described_class.hostname_active?('www.example.com').should be_true
end
it "Returns false if site with hostname doesn't exist" do
described_class.stub_chain(:where, :exists?).and_return(false)
described_class.stub_chain(:where, :first) { site }
site.stub(:active?).and_return(false)
described_class.hostname_active?('www.example.com').should be_false
end
it "Returns false if site is not active" do
described_class.stub_chain(:where, :exists?).and_return(true)
described_class.stub_chain(:where, :first) { site }
site.stub(:active?).and_return(false)
described_class.hostname_active?('www.example.com').should be_false
end
end
end
在相关订阅确定站点是否处于活动状态的情况下,我使用该方法hostname_active?
作为路由中的约束以及在需要确定它是否 a) 存在和 b) 处于活动状态的其他类中。
取自关于 SO 的另一个问题:
Tell-don't-ask 基本上意味着你不应该查询一个对象的状态,根据它的状态做出决定,然后告诉同一个对象要做什么。如果对象拥有它需要的所有信息,它应该自己决定。
虽然我不这样做,但我的代码确实感觉非常耦合,无论是在站点和订阅之间的耦合方面,还是在与 ActiveRecord 的耦合方面,这使得在不接触数据库的情况下很难进行测试。
您将如何构建它以避免询问相关订阅以确定站点的状态?而且,你会认为这违反了“不问不问”的规定吗?