activerecordbelongs-toself-reference

How do you create and save an Active Record instance that has a reference to itself?


Files is an Active Record model that has a reference to its parent of the same type:

class Files < ActiveRecord::Base
  belongs_to :parent, class_name: "Files"
end

I want to create a root entry whose parent is itself (which mimics the root directory which has .. that points to itself).

I have tried several various things most of which end up trying to save the record to the database with the parent still set to null. The db is set up to throw an exception if that field is null. I've tried:

Files.new { |f|
  f.parent   = f
}.save

and

Files.create { |f|
  f.parent   = f
}

I've also tried

Files.new { |f|
  f.parent_id = f.id = Files.next_sequence_value
}.save

And I have looked at build_parent


Solution

  • When creating self-referential assocations the foreign key column must be nullable and the assocation must be optional. Otherwise you're stuck in an a chicken vs egg scenario where you can't create the first record since it has to refer to a non existing record.

    class Files < ActiveRecord::Base
      belongs_to :parent, 
        class_name: self.name,
        optional: true
    end
    

    Using the next sequence value isn't actually a good option since it will not work if your have a foreign key constaint.

    Also the naming here is problematic. Files is plural and that will break the conventions and cause all sorts of issues as well trip up your fellow developers. But File will not work since its a part of the Ruby StdLib. I would suggest an alternative such as Attachment, Document or to use a namespace such as MyApp::File.