简体   繁体   English

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

[英]Rails 4.2 - Update multiple attributes of a Factory Bot record after it is created

I have a Deal model with a model Step associated. 我有一个交易模型与模型步骤相关联。 a deal has_many Steps and a step belongs to a Deal. 交易has_many步骤和步骤属于交易。

I create a Deal Factory: 我创建了一个Deal Factory:

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

For specific reasons related to validations and the use of the gem rspec-retry I can't create the associated Steps by using the "usual" after_create or Transients provided by Factory Girl, and it's Ok because my technique so far worked on all my tests. 由于与验证相关的特定原因以及gem rspec-retry的使用,我无法通过使用Factory Girl提供的“通常”after_create或Transients来创建关联的步骤,并且它没关系,因为我的技术到目前为止在我的所有测试中都有效。 Her's what I do to create 5 associated Steps for Deal1: 她是我为Deal1创建5个相关步骤的方法:

  (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

This creates deal1_step0, deal1_step1, deal1_step2, deal1_step3 and deal1_step4, just as I need and it's working today on all my tests 这创建了deal1_step0,deal1_step1,deal1_step2,deal1_step3和deal1_step4,就像我需要的那样,它今天在我的所有测试中都有效

My issue comes because I now must add to each deal1 steps attributes that differ and can't just be put in the code above as they are completely different from each other each time PLUS they only begin being present on step1 (step0 can't have a video). 我的问题来了,因为我现在必须添加每个deal1步骤属性,这些属性不同,不能只是放在上面的代码中,因为它们彼此完全不同,每次PLUS它们才开始出现在step1上(step0不能有一段录像)。 These attributes I need to send data to are: 我需要发送数据的这些属性是:

  • video_url VIDEO_URL

  • video_x video_x

  • video_y video_y

1st attempt: 第一次尝试:

I tried the code below but it fails and gives me the error: deal1_step0.video_url = nil # there can't be any video on step0 (a validation is set for this) 我尝试了下面的代码,但它失败并给我错误:deal1_step0.video_url = nil#在step0上没有任何视频(为此设置了验证)

`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

2nd attempt: 第二次尝试:

I also tried something like but got a similar error like above: deal1_step1.update_attributes( video_url: 我也尝试了类似但有类似上面的错误:deal1_step1.update_attributes(video_url:

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

3rd attempt: 第三次尝试:

I tried then to create sort of symbols: 然后我尝试创建一些符号:

  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

This time I got no error on the test that was able to be run BUT it does not work as the view thinks all those video_url are nil, it seems i don't manage to inject/update those attributes. 这次我没有在能够运行的测试上没有错误但它不起作用,因为视图认为所有那些video_url都是零,似乎我无法注入/更新这些属性。

Is there a clean/proper way to update the attributes of deal1_step0, deal1_step1, deal1_step2, deal1_step3 and deal1_step4 ? 是否有一种干净/正确的方法来更新deal1_step0,deal1_step1,deal1_step2,deal1_step3和deal1_step4的属性?

The easiest solution to this is to just define arrays of the changing values and use those in your FactoryGirl steps 对此最简单的解决方案是仅定义更改值的数组并使用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

For anything else you need to understand how let / let! 对于其他任何事情你需要了解let / let! works. 作品。 let defines a method (named by the symbol passed in) on the example (it's actually on a module that gets mixed in, same effect) which memoizes the response of the block passed to it. let定义一个方法(由传入的符号命名)在示例上(它实际上是一个混合的模块,效果相同),它会记忆传递给它的块的响应。 let! calls let and then defines a before block that calls the method let defined so it has already been run before the test example is. 调用let然后定义一个调用方法let的前块,以便在测试示例之前运行它。 That's why you're getting the error ' deal1_step1 is not available on an example group (eg a ...', because the method is defined on the example, not on the group. 这就是为什么你得到错误' deal1_step1在示例组上不可用(例如......),因为该方法是在示例上定义的,而不是在组上。

Therefore, if you don't want to do something like the arrays example above then you'd need to do your attribute updating in a block that gets run in the example context, so a before block - like 因此,如果您不想执行上面的数组示例之类的操作,那么您需要在一个在示例上下文中运行的块中进行属性更新,因此在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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM