代码之家  ›  专栏  ›  技术社区  ›  Mathieu

Rails 4.2-创建Factory Bot记录后更新其多个属性

  •  3
  • Mathieu  · 技术社区  · 6 年前

    我有一个与模型步骤相关的交易模型。交易有许多步骤,步骤属于交易。

    我创建了一个交易工厂:

    let!(:deal1)  { create(:deal, 
                                    partner:          partner,                                
                                    title:            "Deal1" ) }
    

    由于与验证和使用gem相关的特定原因 rspec-retry 我无法使用Factory Girl提供的“通常”after\u create或Transients来创建相关步骤,这没关系,因为我的技术迄今为止在我的所有测试中都起到了作用。她是我为交易创建5个相关步骤1所做的:

      (0..4).each do |n|
            let!(:"deal1_step#{n}") {
              FactoryGirl.create(:step,
                order_nb: n,
                message_content: "this is message #{n}",        
               background_asset_filename: "campaigns/assets_for_tests/backgroundimage#{n}.jpg",  
                deal: deal)
            }
          end
    

    这将创建deal1\u step0、deal1\u step1、deal1\u step2、deal1\u step3和deal1\u step4,就像我需要的那样,并且它今天在我的所有测试中都起作用

    我的问题是,我现在必须向每个deal1步骤添加不同的属性,这些属性不能只放在上面的代码中,因为它们每次都完全不同,而且它们只在步骤1中出现(步骤0不能有视频)。我需要向以下属性发送数据:

    • 视频\u url

    • 视频\u x

    • 视频\u y

    第一次尝试:

    我尝试了下面的代码,但失败了,并给出了错误: deal1\u步骤0。video\u url=nil#步骤0上不能有任何视频(已为此设置验证)

    `deal1_step1` is not available on an example group (e.g. a `describe` or `context` block). It is only available from within individual examples (e.g. `it` blocks) or from constructs that run in the scope of an example (e.g. `before`, `let`, etc).
    
    deal1_step0.video_url = nil
    deal1_step0.video_x = nil
    deal1_step0.video_y = nil
    
    deal1_step1.video_url = "https://www.facebook.com/rihanna/videos/10155221800656676/"
    deal1_step1.video_x = 500
    deal1_step1.video_y = 500
    
    deal1_step2.video_url =  "https://www.facebook.com/ClaraLionelFoundation/videos/1821445664574948/"
    deal1_step2.video_x = 500
    deal1_step2.video_y = 300
    
    deal1_step3.video_url  = "https://www.facebook.com/rihanna/videos/10155330511896676/"
    deal1_step4.video_x = 250
    deal1_step4.video_y = 500
    

    第二次尝试:

    我也尝试了类似的操作,但得到了类似于上面的错误: deal1\u步骤1。更新\u属性(视频\u url:

    "https://www.facebook.com/rihanna/videos/10155221800656676/",
    video_x: 500,
    video_y: 500 )
    

    第三次尝试:

    然后我尝试创建某种符号:

      let(:video0) { nil }
      let(:video1) { "https://www.facebook.com/rihanna/videos/10155221800656676/" }
      let(:video2) { "https://www.facebook.com/ClaraLionelFoundation/videos/1821445664574948/" }
      let(:video3) { "https://www.facebook.com/rihanna/videos/10155330511896676/" }
    
    
    (0..4).each do |n|
        let!(:"deal1_step#{n}") {
          FactoryGirl.create(:step,
            video_url: :"video#{n}",
            video_x: 500,
            video_y: 500,
            st_background_asset_filename: "campaigns/042017/assets_for_tests_and_dev/backgroundimage#{n}.jpg",  
            deal: deal1)
        }
      end
    

    这一次,我在能够运行的测试中没有出现错误,但它不起作用,因为视图认为所有这些video\u url都为零,似乎我无法插入/更新这些属性。

    是否有干净/正确的方法来更新deal1\u step0、deal1\u step1、deal1\u step2、deal1\u step3和deal1\u step4的属性?

    1 回复  |  直到 6 年前
        1
  •  1
  •   Thomas Walpole    6 年前

    解决这一问题的最简单方法是定义变化值的数组,并在FactoryGirl步骤中使用这些数组

    urls = [nil, "https://www.facebook.com/rihanna/videos/10155221800656676/", ...]
    xs = [nil, 500, ...]
    ys = [nil, 200, ...]
    (0..4).each do |n|
      let!(:"deal1_step#{n}") {
        FactoryGirl.create(:step,
          video_url: urls[n],
          video_x: xs[n],
          video_y: ys[n],
          st_background_asset_filename: "campaigns/042017/assets_for_tests_and_dev/backgroundimage#{n}.jpg",  
          deal: deal1)
      }
    end
    

    还有什么你需要了解的 let / let! 作品 允许 在示例上定义一个方法(由传入的符号命名)(它实际上位于一个被混入的模块上,效果相同),用于记忆传递给它的块的响应。 允许 呼叫 允许 然后定义调用该方法的before块 允许 定义为在测试示例之前已经运行。这就是为什么你会出错的原因' deal1_step1 在示例组(例如a…)上不可用,因为该方法是在示例上定义的,而不是在组上定义的。

    因此,如果不想像上面的数组示例那样执行操作,那么需要在示例上下文中运行的块中更新属性,因此 before 块状

    (0..4).each do |n|
        let!(:"deal1_step#{n}") {
          FactoryGirl.create(:step,
            order_nb: n,
            message_content: "this is message #{n}",        
           background_asset_filename: "campaigns/assets_for_tests/backgroundimage#{n}.jpg",  
            deal: deal)
        }
      end
    before do 
      deal1_step1.video_url = "https://www.facebook.com/rihanna/videos/10155221800656676/"
      deal1_step1.video_x = 500
      deal1_step1.video_y = 500
      # may need to save deal1_step1 depending on exactly what you're looking for
    
      deal1_step2.update_attributes(video_url: "https://www.facebook.com/rihanna/videos/10155221800656676/", video_x: 500, video_y: 500 )
    
      ...
    end