关于 ruby?? on rails:factorygirl 创建模型关联 NoMethodError: undefined method

factorygirl create model association NoMethodError: undefined method

当我尝试运行 FactoryGirl.create(:job, :purchased) 时,出现以下错误。我已经为此奋斗了很长时间,我相信我有一个多元化问题。

问题

enter image description here

型号

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Job < ActiveRecord::Base
  belongs_to :company
  belongs_to :category
  has_one :coupon
  has_many :payments
end

class Payment < ActiveRecord::Base
  belongs_to :job
  belongs_to :coupon
end

class Coupon < ActiveRecord::Base
  belongs_to :job
end

工厂

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
FactoryGirl.define do
  factory :job do
    category
    company
    title { FFaker::Company.position }
    location {"#{FFaker::Address.city}, #{FFaker::AddressUS.state}" }
    language_list { [FFaker::Lorem.word] }
    short_description { FFaker::Lorem.sentence }
    description { FFaker::HTMLIpsum.body }
    application_process {"Please email #{FFaker::Internet.email} about the position." }

    trait :featured do |job|
      job.is_featured true
    end

    trait :reviewed do |job|
      job.reviewed_at { Time.now }
    end

    trait :purchased do |job|
      job.reviewed_at { Time.now }
      job.start_at { Time.now }
      job.end_at { AppConfig.product['settings']['job_active_for_day_num'].day.from_now }
      job.paid_at { Time.now }
      association :payment, factory: :payment
    end

    trait :expired do |job|
      start_at = (200..500).to_a.sample.days.ago
      job.reviewed_at { start_at }
      job.start_at { start_at }
      job.end_at { |j| j.start_at + AppConfig.product['settings']['job_active_for_day_num'].days }
      job.paid_at { start_at }
      # TBD ADD PAYMENT
    end
  end
end

部分模式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  create_table"payments", force: :cascade do |t|
    t.decimal "price_paid",            precision: 8, scale: 2, default: 0.0
    t.string  "stripe_customer_token"
    t.datetime"created_at",            null: false
    t.datetime"updated_at",            null: false
  end

  create_table"jobs", force: :cascade do |t|
    t.string  "title",               limit: 50,                  null: false
    t.string  "slug",                limit: 250,                 null: false, index: {name:"index_jobs_on_slug"}
    t.string  "vanity_url",          limit: 250
    t.string  "location",            limit: 100,                 null: false
    t.string  "short_description",   limit: 250,                 null: false
    t.text    "description",         null: false
    t.text    "application_process", null: false
    t.boolean "is_featured",         default: false
    t.datetime"start_at"
    t.datetime"end_at"
    t.datetime"created_at",          null: false
    t.datetime"updated_at",          null: false
    t.integer "company_id",          index: {name:"index_jobs_on_company_id"}, foreign_key: {references:"companies", name:"fk_jobs_company_id", on_update: :no_action, on_delete: :no_action}
    t.datetime"deleted_at",          index: {name:"index_jobs_on_deleted_at"}
    t.integer "category_id",         index: {name:"index_jobs_on_category_id"}, foreign_key: {references:"categories", name:"fk_jobs_category_id", on_update: :no_action, on_delete: :no_action}
    t.datetime"paid_at"
    t.datetime"reviewed_at"
    t.integer "payment_id",          index: {name:"index_jobs_on_payment_id"}, foreign_key: {references:"payments", name:"fk_jobs_payment_id", on_update: :no_action, on_delete: :no_action}
  end

  create_table"coupons", force: :cascade do |t|
    t.integer "code",             limit: 8, null: false, index: {name:"index_coupons_on_code", unique: true}
    t.integer "percent_discount", limit: 2, null: false
    t.datetime"start_at",         null: false
    t.datetime"end_at",           null: false
    t.datetime"executed_at"
    t.datetime"deleted_at",       index: {name:"index_coupons_on_deleted_at"}
    t.datetime"created_at",       null: false
    t.datetime"updated_at",       null: false
    t.integer "job_id",           index: {name:"index_coupons_on_job_id"}, foreign_key: {references:"jobs", name:"fk_coupons_job_id", on_update: :no_action, on_delete: :no_action}
    t.integer "payment_id",       index: {name:"index_coupons_on_payment_id"}, foreign_key: {references:"payments", name:"fk_coupons_payment_id", on_update: :no_action, on_delete: :no_action}
  end

以下每个聊天的更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
  create_table"jobs", force: :cascade do |t|
    t.string  "title",               limit: 50,                  null: false
    t.string  "slug",                limit: 250,                 null: false, index: {name:"index_jobs_on_slug"}
    t.string  "vanity_url",          limit: 250
    t.string  "location",            limit: 100,                 null: false
    t.string  "short_description",   limit: 250,                 null: false
    t.text    "description",         null: false
    t.text    "application_process", null: false
    t.boolean "is_featured",         default: false
    t.datetime"start_at"
    t.datetime"end_at"
    t.datetime"created_at",          null: false
    t.datetime"updated_at",          null: false
    t.integer "company_id",          index: {name:"index_jobs_on_company_id"}, foreign_key: {references:"companies", name:"fk_jobs_company_id", on_update: :no_action, on_delete: :no_action}
    t.datetime"deleted_at",          index: {name:"index_jobs_on_deleted_at"}
    t.integer "category_id",         index: {name:"index_jobs_on_category_id"}, foreign_key: {references:"categories", name:"fk_jobs_category_id", on_update: :no_action, on_delete: :no_action}
    t.datetime"paid_at"
    t.datetime"reviewed_at"
  end

  create_table"coupons", force: :cascade do |t|
    t.integer "code",             limit: 8, null: false, index: {name:"index_coupons_on_code", unique: true}
    t.integer "percent_discount", limit: 2, null: false
    t.datetime"start_at",         null: false
    t.datetime"end_at",           null: false
    t.datetime"executed_at"
    t.datetime"deleted_at",       index: {name:"index_coupons_on_deleted_at"}
    t.datetime"created_at",       null: false
    t.datetime"updated_at",       null: false
    t.integer "job_id",           index: {name:"index_coupons_on_job_id"}, foreign_key: {references:"jobs", name:"fk_coupons_job_id", on_update: :no_action, on_delete: :no_action}
  end

  create_table"payments", force: :cascade do |t|
    t.decimal "price_paid",            precision: 8, scale: 2, default: 0.0
    t.string  "stripe_customer_token"
    t.datetime"created_at",            null: false
    t.datetime"updated_at",            null: false
    t.integer "job_id",                index: {name:"index_payments_on_job_id"}, foreign_key: {references:"jobs", name:"fk_payments_job_id", on_update: :no_action, on_delete: :no_action}
    t.integer "coupon_id",             index: {name:"index_payments_on_coupon_id"}, foreign_key: {references:"coupons", name:"fk_payments_coupon_id", on_update: :no_action, on_delete: :no_action}
  end

错误
enter image description here

特征工作

1
2
3
4
5
6
7
trait :purchased do |job|
  job.reviewed_at { Time.now }
  job.start_at { Time.now }
  job.end_at { AppConfig.product['settings']['job_active_for_day_num'].day.from_now }
  job.paid_at { Time.now }
  payments { |j| [j.association(:payment)] }
end

在您的 trait 中,您正在定义 association :payment, factory: :payment
但工作有_many付款。

为了工作,你的模型应该是:

1
2
3
4
5
6
7
class Job < ActiveRecord::Base
  belongs_to :payment
end

class Payment < ActiveRecord::Base
  has_many :jobs
end

如果你想保持你的模型不变并创建一个包含多个付款的工作的特征,你需要做这样的事情:

如何通过 has_many 关联在 FactoryGirl 中设置工厂