【问题标题】:How to load fixtures in a specific order in Rails 5如何在 Rails 5 中按特定顺序加载夹具
【发布时间】:2017-02-27 22:29:07
【问题描述】:

我有两个相互依赖的模型,帐户和用户。账户总是由用户创建的,其 id 存储在账户的 creator_id 属性中,用户必然属于一个账户(但对属于一个账户的用户数量没有限制),该信息存储在用户的account_id 属性。同一用户可以创建不同的帐户。

我是这样表达这些规则的:

用户模型:

belongs_to :account, inverse_of: :users
has_many :created_accounts, class_name: "Account", :foreign_key => "creator_id"

帐户模型:

 belongs_to :creator, class_name: 'User', optional: true
 has_many :users, inverse_of: :account

由于它们是相互依赖的,我使用了一种肮脏的解决方法来实例化它们:我首先创建帐户,然后在该操作之后强制用户创建他们的个人资料,并将他们的 user_id 作为 creator_id 添加到帐户中更新。

这就是我在帐户模型中拥有的原因:

validate :require_actual_creator_id, on: :update
------------------------------------------------
 def require_actual_creator_id
    User.find(creator_id)
  end

我正在开发一个仅涉及用户模型的身份验证系统,所以我将这些行注释掉,直到昨天我取消注释它们。

我运行 db:migrate:reset、db:seed 和 db:migrate RAILS_ENV=test 没有任何问题,这两个模型在控制台中的行为都正常,但是当涉及到夹具时(例如 testing 或 db:fixtures:load ),我收到以下错误:

NoMethodError: undefined method `id' for nil:NilClass
/home/vincent/workspace/bam-rails/test/fixtures/users.yml:16:in `get_binding'

这是一个导致问题的典型夹具,第 16 行是注释的:

michael:
  id: 1
  handle: Michael Example
  email: michael@example.com
  encrypted_password: <%= User.generate_encrypted_token('password') %>
  role_id: <%= User::ADMIN %>
  is_activated: true
  activated_at: <%= DateTime.now %>
  #account_id: <%#= Account.first.id %>

当我评论最后一行时,就没有问题了。但是,我想为我的测试加载适当的夹具,因为例如这里创建的用户无效。

我在this post 中读到,固定装置按字母顺序加载。如果这是正确的,我不明白为什么我必须评论这一行,因为帐户应该在用户之前加载。

我发现 that solution 可以工作,但它不是来自官方文档,而且它很旧,可以追溯到 2007 年。我担心这会从一天到另一天停止工作。

有谁知道如何在 Rails 5 中按自定义顺序正确加载固定装置,或者对我的问题有其他解决方案吗? 提前谢谢你。

【问题讨论】:

    标签: ruby-on-rails associations ruby-on-rails-5 fixtures ruby-2.3


    【解决方案1】:

    您遇到的问题完全源于您组织代码的方式。解决您创建第一个帐户的地方是您遇到问题的地方。因此,当您的用户被实例化时,您的帐户首先不存在,因为设备尚未加载;这一点我相信你是知道的。 Fixtures 是出了名的脆弱,这就是为什么人们经常远离他们的代码越复杂。在这种情况下,尽管它可以帮助您暴露代码异味,但无论何时订单或运行您的测试或基本的非测试用例特定设置都会导致问题,这意味着您的代码有问题。我建议您找到使用这种“肮脏工作”的方法。

    现在,如果由于某种原因您对代码当前的组织方式感到满意,我建议您切换到 factory girl,它会给您更多的灵活性来控制您的模拟对象以这种方式实例化的点不会遇到这个问题。但是,我会说这只会让您继续沿着这条路走下去,这很可能只会导致更多的问题,您最好的选择是重新实现该功能。

    【讨论】:

    • 感谢您的回答。因素女孩似乎很方便,我将来可能会使用它。关于我的代码是如何组织的,不幸的是我不能改变它,因为我不是那个决定的人。但是,我找到了解决我的精确问题的方法,它不是使用 erb 和 User.first.id 生成 id,而是简单地用纯文本编写它,比如“1”。这样,您无法确定它是一个实际的 id 并且该对象可能是无效的,但至少有一个 id 并且如果您仔细管理您的固定装置,它对应于一个实际的记录。
    • 请注意,我使用的代码库依赖于数据库中的某些记录,这实际上会导致噩梦。你想努力让你的代码尽可能地无状态,但我很高兴你摆脱了困境。
    猜你喜欢
    • 2015-03-18
    • 2012-02-12
    • 2016-11-01
    • 2016-08-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-12
    • 2012-02-01
    相关资源
    最近更新 更多