ICDevin ICDevin - 1 year ago 101
JSON Question

Saving nested model in Rails 4

Kinda new to the Rails thing, in a bit of a spot.

One of the models is dependent on the other in a has_many/belongs_to association.

Basically, when creating a "Post" on my application, a user can also attach "Images". Ideally these are two separate models. When a user chooses a photo, some JavaScript uploads it to Cloudinary and the returned data (ID, width, height, etc) are JSON stringified and set on a hidden field.

# The HTML
= f.hidden_field :images, :multiple => true, :class => "image-data"

# Set our image data on the hidden field to be parsed by the server
$(".image-data").val JSON.stringify(images)

And of course, the relationship exists in my Post model

has_many :images, :dependent => :destroy
accepts_nested_attributes_for :images

and my Image model

belongs_to :post

Where I'm lost is what to do with the serialized image data on the Post controller's create method? Simply parsing the JSON and saving it doesn't create the Image models with the data upon saving (and doesn't feel right):

params[:post][:images] = JSON.parse(params[:post][:images])

All of this essentially culminates to something like the following parameters:

{"post": {"title": "", "content": "", ..., "images": [{ "public_id": "", "bytes": 12345, "format": "jpg"}, { ..another image ... }]}}

This whole process seems a little convoluted -- What do I do now, and is there a better way to do what I'm trying to do in the first place? (Also are strong parameters required for nested attributes like this...?)


At this point I got this error:

Image(#91891690) expected, got ActionController::Parameters(#83350730)

coming from this line...

@post = current_user.reviews.new(post_params)

Seems like it's not creating the images from the nested attributes but it's expected to.
(The same thing happens when :autosave is there or not).

Answer Source

Just had this issue with that ActionController::Parameters error. You need to make sure you're permitting all the necessary parameters in your posts_controller, like so:

def post_params
  params.fetch(:post).permit(:title, :content,
                             images_attributes: [:id, :public_id, :bytes, :format])

It's important to make sure you're permitting the image.id attribute.