【问题标题】:Monitoring process interference Factory's instance initialization监控进程干扰工厂的实例初始化
【发布时间】:2011-11-21 14:47:14
【问题描述】:

在我的项目中,user 将有许多 items,它们的 onshelf_at 属性在创建时默认为 DateTime.now

# item.rb
class Item < ActiveRecord::Base

  before_create :calculate_onshelf_time

  default_scope :order => 'items.onshelf_at DESC'

  def calculate_onshelf_time
    self.onshelf_at = DateTime.now
  end

end

在用户模型测试中,我试图说服自己检索到的订单确实是items.onshelf_at DESC。于是我做了下面的sn-p,结果却是反了。 (即[@item1, @item2]

# spec/models/user_spec.rb
before :each do
  @user = User.create(@attr)
  @item1 = Factory(:item, :owner=>@user, :onshelf_at => 2.days.ago, :created_at => 2.days.ago)
  @item2 = Factory(:item, :owner=>@user, :onshelf_at => 1.day.ago, :created_at => 1.day.ago)        
end


it "should have the right items in the right order" do
  @user.items.should == [@item2, @item1]
end

我检查了控制台,发现 onshelf_at 没有监听 Factory Girl 的实例初始化。取而代之的是,它遵循 before_create 规则,并重视运行测试的时间!

Failure/Error: @user.items.should == [@item2, @item1]
   expected: [#<Item id: 2, description: "this is an item", img_link: "http://www.example.com/photos/some_pic.jpg", category_id: 5, onshelf: true, created_at: "2011-11-20 11:19:15", updated_at: "2011-11-21 11:19:15", onshelf_at: "2011-11-21 11:19:15", owner_id: 1>, #<Item id: 1, description: "this is an item", img_link: "http://www.example.com/photos/some_pic.jpg", category_id: 5, onshelf: true, created_at: "2011-11-19 11:19:15", updated_at: "2011-11-21 11:19:15", onshelf_at: "2011-11-21 11:19:15", owner_id: 1>]
        got: [#<Item id: 1, description: "this is an item", img_link: "http://www.example.com/photos/some_pic.jpg", category_id: 5, onshelf: true, created_at: "2011-11-19 11:19:15", updated_at: "2011-11-21 11:19:15", onshelf_at: "2011-11-21 11:19:15", owner_id: 1>, #<Item id: 2, description: "this is an item", img_link: "http://www.example.com/photos/some_pic.jpg", category_id: 5, onshelf: true, created_at: "2011-11-20 11:19:15", updated_at: "2011-11-21 11:19:15", onshelf_at: "2011-11-21 11:19:15", owner_id: 1>] (using ==)

我该如何解决这个问题?

【问题讨论】:

    标签: ruby-on-rails model rspec factory factory-bot


    【解决方案1】:

    一个快速的解决方法是为您的calculate_onshelf_time 方法添加一个条件:

     self.onshelf_at = DateTime.now if self.onshelf_at.nil?
    

    但是 - 你甚至不需要这一切。如果可以(也就是说,如果您可以控制模式),请将 onshelf_at 属性替换为 created_at 列,该列将在创建时由 Rails 自动设置。如果您使用迁移:

     create_table :foo do |t|
       # ...
       t.timestamps
     end
    

    将为模型添加created_atupdated_at 时间戳。

    【讨论】:

    • 有效!谢谢!你能告诉我你做了什么魔法吗,为什么我失败了?我不太明白 FactoryGirl 实例初始化的工作原理。
    • 是这样,工厂分配给那些属性,然后然后创建模型实例?
    • 如果您指的是第一个解决方案 - factory_girl 创建一个新对象,按指定分配所有属性,然后在模型上调用 save - 然后触发 before_create 回调,继续覆盖onshelf_at 属性。我的解决方案只是检查它是否已经有一个值,如果没有则只分配一个。但同样,我真的建议直接使用 Rails 中的自动时间戳。
    • 我在后期开发中需要onshelf_at属性。不过,我对第一个解决方案感到担忧。如果我的队友或我自己不小心为onshelf_at 分配了一个值,那么该值将与创建时的created_at 不同(或接近)。而且我真的不喜欢在 onshelf_at 稍后手动分配值之前使用 created_at
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-08-21
    • 1970-01-01
    • 1970-01-01
    • 2019-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多