【问题标题】:How to use Fabricate-gem to generate objects?如何使用 Fabricate-gem 生成对象?
【发布时间】:2016-10-03 04:30:33
【问题描述】:

我正在使用 Rails 4、FabricateFaker Gems。我正在尝试使用(100 个左右)随机创建的对象(最多包含 3 个冰淇淋的订单)为我的数据库播种。我关注了推荐使用这种方法的This Answer

models/order.rb

  class Order < ActiveRecord::Base
    ...
    has_many :ice_creams
    ...
  end

models/ice_cream.rb

  class IceCream < ActiveRecord::Base
    ...
    has_and_belongs_to_many :flavors
    has_many :added_extras
    has_many :extras, :through => :added_extras
    belongs_to :order
    ...
  end

models/extra.rb

  class Extra < ActiveRecord::Base
    ...
    has_many :added_extras
    has_many :extras, :through => :added_extras
    ...
  end

test/fabricators/order_fabricator.rb

  Fabricator(:order) do

    user { User.offset(rand(User.count)).first } #fine
    shift { Shift.offset(rand(Shift.count)).first } #fine
    created_at { Faker::Date.backward(365) } #fine
    ice_creams(rand: 3) { |attrs| Fabricate( :ice_cream, created_at: attrs[:created_at] ) } #fine

    total { Faker::Number.between(5, 25) }
    #add more logic depending of the total number of randomly created ice creams

    discount { [0, 10, 15, 25].sample } #fine
    total_after_discount { |order| order[:total] -  ( (order[:total] * order[:discount]) / 100 ) }
    paid { [50, 100, 200].sample } #fine
    remaining { |order| order[:paid] -  order[:total_after_discount] } #fine

  end

test/fabricators/ice_cream_fabricator.rb

  Fabricator(:ice_cream) do

    size { Size.offset(rand(Size.count)).first } #fine
    basis { Basis.offset(rand(Basis.count)).first } #fine
    sauce { Sauce.offset(rand(Sauce.count)).first } #fine
    topping { Topping.offset(rand(Topping.count)).first } #fine

    flavors { [ Flavor.offset(rand(Flavor.count)).first ] }
    #add additional ability to be one or two flavors randomly

    extras { [ Extra.offset(rand(Extra.count)).first ] }

    ice_cream_price { [15, 17, 18, 19, 20, 22].sample } #add logic
    extras_price { [5, 10, 15, 20 ].sample } #add logic 

    total_price { |attrs| attrs[:ice_cream_price] + attrs[:extras_price] } #fine
    created_at { Faker::Date.backward(365) }

  end

它工作正常,我现在可以创建包含多达 3 个假 Ice Creams 的假 Orders,但问题是我正在努力弄清楚 Fabricate 的逻辑更现实的订单,您可能会注意到,在我的制造商代码中,有一些属性我标记得很好——我对它的结果很好——还有一些我仍然不完全满意,比如.. .

  • 我希望制作的冰淇淋可以-随机-有一种或两种口味。
  • 我希望对 Extras 做同样的事情
  • 我想将随机制造的 冰淇淋 :total_price 的总和作为:total 传递给 Order

我已尝试通过创建 Flavor Fabricator 来实现,但没有成功..

test/fabricators/flavor_fabricator.rb

  Fabricator(:flavor) do
    Flavor.offset(rand(Flavor.count)).first
  end

我也尝试将:total_price的activeRecord方式相加,但它也没有奏效

test/fabricators/order_fabricator.rb

  Fabricator(:order) do
    ...
    total { self.ice_creams.sum(:total_price) }
    ...
  end

所以我的问题是... - 我希望的事情是可能的还是太多了?如果是这样,如何实现?

我希望我说清楚了,你可以帮助我。谢谢

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4.2 faker fabrication-gem


    【解决方案1】:

    您似乎正在尝试使用制造来为您的模型设置计算值,例如IceCream#total_price。您应该让模型上的方法发挥作用,例如从零件中计算总数,而不是试图通过制造来强迫它们。

    具体回答您的问题:

    1) 我希望预制冰淇淋可以——随机地——有一种或两种口味。

    Fabricator(:ice_cream) do
      flavors { Flavor.all.sample(rand(1..2)) }
    end
    

    2) 同 #1

    3) 你应该在Order 上有一个方法来计算创建时的总数。

    【讨论】:

    • 谢谢,这很有帮助,实际上它对第 1 点和第 2 点很有用。但是你能解释一下如何实现第 3 点吗,其实我是一个你知道的新手。我理解这个概念,但我不知道如何将其付诸实践。
    • 哦,酷。因此,对于数字 3,您可能需要模型中的 before_create 挂钩来执行该计算并保存它。 ``` before_create do self.total ||= ice_creams.sum(:total_price) end ```
    • 不知道为什么它会在那个方法中对* 这么说。不过,在这些 cmets 中谈论代码有点困难。我很乐意在 GitHub 上进行更深入的讨论。如果你愿意,你可以提出反对制造的问题,我们可以在那里解决它。
    • 好的,但首先请编辑您的答案并在适当的上下文中添加您的建议,也许我遗漏了一些东西。
    • 在 GitHub 上继续对话:github.com/paulelliott/fabrication/issues/282
    猜你喜欢
    • 1970-01-01
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多