首页 > 解决方案 > 使用它所属模型的属性在 has_many 关联中设置模型属性的最全面方法是什么?

问题描述

我有两个 ActiveModel,MultivariateExperiment其中has_many MultivariateExperimentVariant. 相反,一个MultivariantExperimentVariant belongs_toa MultivariateExperiment

MultivariateExperiment有一个属性experiment_name

MultivariantExperimentVariant具有属性nameweighting

我希望变体name的格式experiment_name_0为 ,experiment_name_1等。例如,给定以下 MultivariateExperiment:

mve = MultivariateExperiment.create({ experiment_name: 'user_signup' })

我想有一种程序化的方式来让相关的变体成为:

mve.multivariate_experiment_variants.create({ weighting: 1 }) # expected name: "user_signup_0"

mve.multivariate_experiment_variants.create({ weighting: 1 }) # expected name: "user_signup_1"

mve.multivariate_experiment_variants.create({ weighting: 2 }) # expected name: "user_signup_2"

我最初考虑将它放在after_commit回调中,但在代码审查中被告知要避免它,因为该回调是 finnicky (不知道为什么)

我查看了其他一些回调,但它们似乎都不够全面,无法涵盖可以创建关联的无数方式,例如:

# 1st approach
mve.multivariate_experiment_variants.create({ weighting: 1 })

# 2nd approach
variant = MultivariateExperimentVariant.create({ weighting: 1 })
mve << variant
mve.save

# 3rd approach
mve.multivariate_experiment_variants.build({ weighting: 1 })
mve.save


# etc. etc.

那么,考虑到创建关联的各种方式,是否有任何机制或方法可以has_many使用它所属的模型的属性成功地计算关系中模型的属性?

标签: ruby-on-railsrubyruby-on-rails-4activemodel

解决方案


MultivariateExperimentVariant模型中你可以做...

after_save :set_name

private

def set_name
  # Assuming you have a required belongs_to
  update(name: "#{multivariate_experiment.name}_#{multivariate_experiment.multivariate_experiment_variants.length - 1}")
end

after_commit除非您指定on:条件,否则您不想使用

after_commit :set_name, on: [:create, :update]

否则,它会在记录被销毁后尝试设置名称。

旁注:最好改为检查索引......

 update(name: "#{multivariate_experiment.name}_#{multivariate_experiment.multivariate_experiment_variants.index(self)}")

推荐阅读