I have a project with ruby 2.5
and rails 5.2
. It has a model called Fruit
, which includes two fields: name:string
and options:json
. I want to use options to store some data like color
, size
, etc.
Now I have a form:
<%= form_with(model: fruit, local: true) do |form| %>
<div class="field">
<%= form.label :name %>
<%= form.text_field :name %>
</div>
<div class="field">
<%= form.label :options %>
<%= form.fields :options do |field| %>
<%= field.text_field :color %>
<%= field.text_field :size %>
<% end %>
</div>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
It will successfully save the data to database, including the color and size in options
. However, it cannot display the existing data in options when I edit
it.
It means when I edit the fruit, if I don't set the color and size again, the existing data will lost.
Does anyone know how to make it work properly?
The problem marked as duplicate is different. In that problem, they are asking if a json object can transfer to string or not.
My question is to display the value in the form by key.
I have found the solution.
The form will show each value by sending a getter method to object
. The object
is stored in the form builder as form.object
, and represent the model.
However, when created a sub-form by fields, the object is not included. It needs to be passed in:
<%= form.fields :options, model: form.object.options do |field| %>
In this way, the field.object
will be assigned to options
as Hash
format.
However, it's not enough. The form tries to get the value by calling the method. But the hash attributes cannot accept method call. options.color
won't return the value so the value isn't shown on the form yet.
One solution is transferring the model to OpenStruct
. OpenStruct
allows you to call the key as a method to get the value. So my solution to make the form works is:
<%= form.fields :options, model: OpenStruct.new(form.object.options) do |field| %>
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