Postgres JSON column updating individual keys / attributes with a form

I am having problems updating the rails JSON column in the model.

I have an OrderItem model with a column: options with a postgres json data type.

I have a form where I am only trying to update two attributes in this JSON column. However, when I run the update action from my controller, it resets the entire parameter column with only fields in my form, and not just updates two separate attributes. This is mistake? I'm on Rails 4.2.1 and from what I read it should work, and I can manually update individual attributes in the rails console.

In my controller:

def update @order_item.update(order_item_params) respond_with(:update) end private def order_item_params params.require(:order_item).permit(:product_id, :quantity, options:[:esp, :size]) end 

My form:

  <%= f.fields_for :options do |option| %> <%= option.label :size %> <%= option.select :size, options_for_select((5..13), item.options["size"]) %> <%= option.select :esp, options_for_select(["yes","no"], item.options["esp"]) %> <% end %> 

When this form is submitted, it does not update individual attributes. It flushes the entire json column for only these two attributes

 Form Data utf8:✓ _method:patch order_item[quantity]:2 order_item[options][size]:5 order_item[options][esp]:no 

In the console, I can easily update attributes manually ...

 o = OrderItem.last o.options["esp"] = "yes" o.save #PERSISTS! 
+5
source share
2 answers

I do not have your full application, but I assume that when you enter only these 2 parameters, it does not perform the same actions that you launch in the console. When the form is submitted, it is expected that all your parameters will be accepted, and not just those that you added to the form.

To prevent this, you can add all other fields as hidden, and thus save the data.

0
source

You can manually specify how to update your json options separately from the rest of the object.

One strategy may be to remove the parameters from the allowed order_item_params, then do something like this:

 def update @order_item.options.merge!(params[:order_item][:options] @order_item.update(order_item_params) respond_with(:update) end 
0
source

Source: https://habr.com/ru/post/1216322/


All Articles