I am always surprised that nested objects have to built manually for accepts_nested_attributes_for to work. Let’s say I have an Employee model that has_one Contract:
class Employee
has_one :contract
accepts_nested_attributes_for :contract
end
class Contract
belongs_to :employee
end
I would expect rails to automatically create the contract record, when its nested attributes are provided:
But this doesn’t work. Instead I have to catch this somewhere, usually in assign_attributes:
class Employee
def assign_attributes(attrs = {})
self.build_contract if self.contract.blank? && attrs.include?(:contract_attributes)
super(attrs)
end
def
This is unnatural and seems unnecessary. Why couldn’t rails handle this automatically?
This also bites me sometimes. Our convention at the moment is to handle it in the controller, to help the form render.
def new
@employee = Employee.new
@employee.build_contract
end
def edit
@employee = Employee.find(params[:id])
@employee.build_contract unless @employee.contract # This is especially easy to forget
end
I can imagine that this might come up in other places than forms which warrants to override assign_attributes but so far it didn’t happen for us so that’s why it’s not in the model.
This is not schema field. Also don’t touch schema fields in the model” approach is strong in Rails - first time hearing about it. All schema fields in rails are for example typecasted.
If you dont want override method you can have new name
def contract_or_build
contract || build_contract
end