When trying to create a new record with a has_one
relationship (and all the inverse_of
correctly specified), the form is disabled:
The code for this association is as follow:
class Visit < ActiveRecord::Base
has_one :mri, dependent: :destroy, inverse_of: :visit
accepts_nested_attributes_for :mri, update_only: true
...
end
class Mri < ActiveRecord::Base
belongs_to :visit, inverse_of: :mri, touch: true
...
end
When I remove the whole line with accepts_nested_attributes
, I get a missing form, nothing:
Using the rails_admin configuration to disable the nested form, as follow, gives the same result.
config.model Visit do
edit do
configure :mri do
nested_form false
end
end
end
These problems come from two bugs of Rails Admin, IMO.
It is useful to understand that Rails Admin has two kind of forms for association. One is the classic one (that opens a window for creation) and the other is the "nested_form" that displays the form in the page. The nested_form
parameter can be changed directly, as shown in the question above, but is automatically set to true by Rails Admin for associations included in accepts_nested_attributes_for
.
The first bug is that accepts_nested_attributes_for: ..., update_only: true
get "interpreted" by rails Admin as "I don't want to give parameters at creation". This interpretation seems wrong, since the behavior that update_only
changes in rails concerns solely object updates, and doesn't prevent passing nesting parameters at creation. Moreover, I would have expected a fallback to the classic form instead of a completely disabled form.
A quick - and usually detrimental - way to fix this is to change update_only
to the default false
.
The second bug is more surprising, because 'in your face'. As shown in the wiki, the classic (non nested) association forms for the has_one
relations don't get initialized properly if you don't specify yourself the id setters and getters. Thus, if you don't have nested_attributes, you need to include lines as such in your model:
class Visit < ActiveRecord::Base
has_one :mri, dependent: :destroy, inverse_of: :visit
def mri_id
self.mri.try :id
end
def mri_id=(id)
self.mri = Mri.find_by_id(id)
end
...
end
Finally, leveraging our understanding of the first bug gave us the most elegant solution to my initial problem. The source code of the Rails Admin templates show that Rails Admin stores an update_only
parameter for the nested_form
attribute of the field object. We can directly configure it in order to achieve the desired behavior (that should be the default imo):
config.model Visit do
edit do
configure :mri do
nested_form[:update_only] = false
end
end
end
PS: This post is rather long but this simple problem ended up chasing down a rabbit hole, so I wanted to share my findings - I hope it helps. A huge thanks to the RA devs, who provide Rails with one of the most versatile and feature rich admin portal (ever). I've open a couple of gh issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With