Co-dependent Models in Rails

Sometimes you have a one-to-many relationship in your Rails models and you want to allow nested attributes at the time of creation. So you do this:

# Seems like it would work, but does NOT:
class User < ApplicationModel
  has_many :tags
  accepts_nested_attributes_for :tags
end

class Tag < ApplicationModel
  belongs_to :user
end

When you try to save a user, though, you run into trouble: ActiveRecord tries to validate autosaved nested records, and those nested records have an implicit required: true validation on the parent model which, in this case, doesn’t have an ID yet.

The fix is simple, but unintuitive: manually specify the inverse_of option on the association. ActiveRecord can create a bidirectional association automatically, but in this particular case, it doesn’t work.

# Redundant, but works
class User < ApplicationModel
  has_many :tags, inverse_of: :user
  accepts_nested_attributes_for :tags
end

class Tag < ApplicationModel
  belongs_to :user, inverse_of: :tags
end

This will give ActiveRecord the information it needs to allow the “required” validation on the belongs_to to verify the associated model is in place even though it doesn’t have an ID, allowing your models to save as expected.

 
1
Kudos
 
1
Kudos

Now read this

Render templates from anywhere in Ruby on Rails

Rails 5 recently shipped, and among many other new features is a new renderer that makes it easy to render fully composed views outside of your controllers. This comes in handy if you want to attach, say, an HTML receipt to an order... Continue →