代码之家  ›  专栏  ›  技术社区  ›  Tom Corelis

与轨道固定装置无关联……如何固定?

  •  3
  • Tom Corelis  · 技术社区  · 6 年前

    我有一个使用rspec/fixtures的rails 5.1项目,我在让fixtures加载与所属对象相关联的对象时遇到了困难:我请求fixture的对象返回时,其ID列中填充了一个看似随机的数字,ActiveRecord将关联视为 nil . 这发生在具有许多关联的大型类上,以及只有几个字段的小型数据类上。

    如果,在我的测试代码中,我将这些关联分配给正常的Ruby代码,那么对象的行为就正常,我的测试就通过了。但是,当通过fixture加载相同的数据时,关联的记录不可用,需要跨关联的数据跨越的测试失败。

    例如,这里有两个受影响的类:

    #app/models/location.rb
    class Location < ActiveRecord::Base
      has_many :orders
      has_many :end_user
      belongs_to :retailer
      belongs_to :depot
    end
    
    #app/models/retailer.rb
    class Retailer < ActiveRecord::Base
        has_many :locations
    end
    

    下面是两个对应的装置文件:

    #spec/fixtures/locations.yml
    loc_paris:
      retailer: ret_europe (Retailer)
      name: "Paris"
      nickname: "paris"
    
    loc_washington:
      retailer: ret_usa (Retailer)
      name: "Washington"
      nickname: "washington"
    
    #spec/fixtures/retailers.yml
    ret_europe:
      name: "AcmeCo France"
      nickname: "acmecofr"
      currency_type: "EUR"
    
    ret_usa:
      name: "AcmeCo USA"
      nickname: "acmecousa"
      currency_type: "USD"
    

    使用上述数据,运行 pp locations(:loc_paris) 结果:

    #<Location:0x0000000006eee1d8
     id: 35456173,
     name: "Paris",
     nickname: "paris",
     retailer_id: 399879241,
     created_at: Wed, 23 May 2018 22:39:56 UTC +00:00,
     updated_at: Wed, 23 May 2018 22:39:56 UTC +00:00>
    

    这些ID号通过多个调用是一致的,至少在相同的rspec上下文中是一致的。(我把 PP位置(:loc_Paris) 在一个 let 阻止。)还没有。 pp locations(:loc_paris).retailer 退货 .

    我试过用factrybot,但我们不得不放弃它。我试图给fixtures一个诚实的震动,但似乎我们最好是简单地在实际测试代码中构建数据对象…因为这些解决方案毫无怨言地有效:/

    我在这里做错什么了吗?我们要求的固定装置太多了吗?

    谢谢您!

    汤姆

    1 回复  |  直到 6 年前
        1
  •  3
  •   Ayer    6 年前

    固定装置问题

    看看你做了什么, locations(:loc_paris) 将找到中描述的记录 位置.yml 但是 locations(:loc_paris).retailer 不会。

    Rails关联的工作方式如下:

    地点(:loc_paris)。零售商 将查找 retailer 具有 retailer_id 在中提到 地点(:loc_Paris) 记录。在你的情况下 retailer_id: 399879241 没有 reseller 用这个 id 这就是它回来的原因 Nil .

    解决方案: 描述这样的装置:

    #spec/fixtures/locations.yml
    loc_paris:
      retailer_id: 1
      name: "Paris"
      nickname: "paris"
    
    loc_washington:
      retailer_id: 2
      name: "Washington"
      nickname: "washington"
    
    #spec/fixtures/retailers.yml
    ret_europe:
      id: 1
      name: "AcmeCo France"
      nickname: "acmecofr"
      currency_type: "EUR"
    
    ret_usa:
      id: 2
      name: "AcmeCo USA"
      nickname: "acmecousa"
      currency_type: "USD"
    

    现在, 地点(:loc_paris)。零售商 将寻找零售商 零售商ID 在中提到 地点(:loc_Paris) 记录,即 retailer_id: 1 还有一个经销商 ret_europe 用这个 身份证件 . 问题已解决

    当你运行rspec时,首先 rspec 将这些设备保存到数据库中,并自动生成 身份证件 值(如果 身份证件 这就是为什么 身份证件 reseller_id 是一些随机值吗? 。如果你不想 身份证件 属于 locations.yml 记录为某个随机值,您可以这样自己提供:

    loc_paris:
      id: 1
      retailer_id: 1
      name: "Paris"
      nickname: "paris"
    

    提示: AS RSPEC 磨合 test 环境(在 应用程序/规范/轨道助手.rb )正如我之前提到的,无论你何时跑步 RSPEC ,首先它将设备保存到数据库中。如果你的 local 测试 数据库相同,fixture将替换数据库的实际数据库记录。在你的情况下,记录 locations resellers 表格记录将被完全删除,并用这些固定装置替换。因此,为 测试 环境。

    希望这个答案有帮助