这些方法如何添加到我的班级?

时间:2012-11-28 20:45:45

标签: ruby-on-rails ruby rspec-rails

我的Writer模型类上没有'posting_posts'或'rejected_posts'属性。但是,使用此SQL:

posts = self.posts.select("sum(case when state = 'posted' then 1 else 0 end) as posted_posts, sum(case when state = 'rejected' then 1 else 0 end) as rejected_posts")

我可以访问Writer实例上的那些“属性”。当我使用RSpec时,我不想进行此查询,但我无法设置Writer实例的这些属性,因为它认为我正在调用方法:

writer.rejected_posts = 8 

以上行导致“未定义的方法'rejected_posts'”

为了“嘲笑”这些属性,我这样做了:

describe "performance_score" do
    it "should return a score based on the posted_posts and rejected_posts algorithm" do
      class Writer
        attr_accessor :posted_posts, :rejected_posts
      end
      writer = Factory(:writer)
      writer.rejected_posts = 8
      writer.posted_posts = 2
      writer.performance_score.should == 80
    end
  end

我的主要问题是如何将这些方法添加到课程中。如何创建一个新的Writer类来与我的编写器工厂“同步”?我以为我正在为这个测试创建一个新的Writer类,但奇怪的是我仍然可以访问我的编写器工厂的其他属性。希望这是有道理的,谢谢。

此外,还有其他人在测试中做过类似的事情,这是处理这种情况的最佳方法吗?如果您尝试设置一个不存在的属性,它会创建它,就好像在JavaScript中一样。

1 个答案:

答案 0 :(得分:2)

从您的选择查询返回的内容可能不是Writer模型。它可能是ActiveRecord::Relation。为了在SQL语句中提供已赋值的方法,它可能正在实现method_missing并检查AREL的某种内部哈希设置。

对于模拟测试,你所做的一定会奏效。另一种选择是使用stub

it "should return a score based on the posted_posts and rejected_posts algorithm" do
  writer = Factory(:writer)
  writer.stub(:rejected_posts => 8)
  writer.stub(:posted_posts => 2)
  writer.performance_score.should == 80
end