次のような 2 つのクラスがあります。
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に関する別の質問から取得:
聞かないで伝えるとは、基本的に、オブジェクトの状態についてクエリを実行し、その状態に基づいて決定を下し、同じオブジェクトに何をすべきかを伝えてはならないことを意味します。オブジェクトが必要な情報をすべて持っている場合は、それ自体で決定する必要があります。
私はそうしませんが、私のコードは、サイトとサブスクリプションの間の結合だけでなく、データベースに触れずにテストするのが難しくなる ActiveRecord への結合に関しても、かなり結合されているように感じます。
サイトの状態を判断するために、関連するサブスクリプションに問い合わせるのを避けるには、どのように構成しますか? また、これは「聞くな」の違反だと思いますか?