重写ApplicationRecord初始化,坏主意?

Raf*_*sta 6 activerecord overriding ruby-on-rails

我正在创建一个这样的foo对象:

@foo = Foo.new(foo_params)
@foo.bar = Bar.where(name: "baz").first_or_create
Run Code Online (Sandbox Code Playgroud)

但是我还需要做其他一些事情.所以,我想过重写Foo初始化方法来做这样的事情:

class Foo < ApplicationRecord
  def initialize(*args, BarName)
    @foo = super
    @foo.bar = Bar.where(name: BarName).first_or_create
  end
end
Run Code Online (Sandbox Code Playgroud)

并称之为:

@foo = Foo.new(foo_params, "baz")
Run Code Online (Sandbox Code Playgroud)

但是Foo是一个ApplicationRecord,似乎不建议覆盖ApplicationRecord初始化方法.

那怎么能这样呢?还有其他想法吗?这会初始化压倒一切吗?

Dav*_*vid 8

您可以使用 after_initialize 回调并在必要时使用瞬态:

class Foo < ApplicationRecord
  after_initialize :custom_initialization

  attr_accessor :barname

  def custom_initialization()
    self.bar = Bar.where(name: self.barname).first_or_create
  end
end
Run Code Online (Sandbox Code Playgroud)

应用程序记录自己的初始化应该负责设置barname,前提是它在参数中


Nik*_*rin 7

您可以使用活动记录回调.但是,您将无法指定bar_name,并且将以某种方式需要从Foo属性中动态查找它.

如果该选项适用于您.添加到您的模型类似于以下代码.

after_initialize :set_bar

# some other code

def set_bar
  name = # dynamicly_find_name
  self.bar = Bar.where(name: name).first_or_create
end
Run Code Online (Sandbox Code Playgroud)

如果你真的需要指定bar_name,我建议为它创建一个方法.

Foo.new(params).with_bar

def with_bar(bar_name)
  self.bar = Bar.where(name: BarName).first_or_create
end
Run Code Online (Sandbox Code Playgroud)