9

I am creating a foo obeject like this:

@foo = Foo.new(foo_params)
@foo.bar = Bar.where(name: "baz").first_or_create

But there are other objects that I will need to do this as well. So, I thought of overriding the Foo initialize method to do something like this:

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

and call it like this:

@foo = Foo.new(foo_params, "baz")

But Foo is an ApplicationRecord and it seems that it's not recommended to override the ApplicationRecord initialize method.

So how could I do this? Any other ideas? Would this initialize overriding thing work?

Ilya Lavrov
  • 2,810
  • 3
  • 20
  • 37
Rafael Costa
  • 1,291
  • 2
  • 13
  • 30

2 Answers2

14

You can use active record callbacks for that. However you won't be able to to specify bar_name and will somehow need to find it dynamically from Foo attributes.

If that option works you. Add to your model something like the the following code.

after_initialize :set_bar

# some other code

def set_bar
  name = # dynamicly_find_name
  self.bar = Bar.where(name: name).first_or_create
end

In case you really need to specify bar_name, I would suggest to create a method for it.

Foo.new(params).with_bar

def with_bar(bar_name)
  self.bar = Bar.where(name: BarName).first_or_create
end
Nikita Misharin
  • 1,961
  • 1
  • 11
  • 20
  • 1
    Note that `with_bar` will return `self.bar` after execution. If you want to simply set `bar` and then return `self` (i.e. the object), I recommend using tap: `self.tap { |obj| obj.bar = Bar.where(name: bar_name).first_or_create }`. This allows you to continue chaining methods. – XtraSimplicity Jan 03 '20 at 02:41
9

You can make use of the after_initialize callback and use transients if necessary:

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

The application records own initialisation should take care of setting barname providing it is in the params

David
  • 3,510
  • 3
  • 21
  • 39