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,630
  • 3
  • 16
  • 32
Rafael Costa
  • 1,037
  • 1
  • 11
  • 23

2 Answers2

13

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,851
  • 1
  • 10
  • 19
  • 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,400
  • 3
  • 24
  • 36